-
Notifications
You must be signed in to change notification settings - Fork 1.3k
feat(providers): add Eden AI as an OpenAI-compatible provider #4894
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package edenai_test | ||
|
|
||
| import ( | ||
| "context" | ||
| "os" | ||
| "testing" | ||
|
|
||
| bifrost "github.com/maximhq/bifrost/core" | ||
| "github.com/maximhq/bifrost/core/providers/edenai" | ||
| "github.com/maximhq/bifrost/core/schemas" | ||
| ) | ||
|
|
||
| // TestEdenAILiveChatCompletion performs a real chat completion against the Eden AI | ||
| // API through the Bifrost provider. It is skipped unless EDENAI_API_KEY is set, | ||
| // so CI stays hermetic. | ||
| func TestEdenAILiveChatCompletion(t *testing.T) { | ||
| apiKey := os.Getenv("EDENAI_API_KEY") | ||
| if apiKey == "" { | ||
| t.Skip("EDENAI_API_KEY not set; skipping live Eden AI test") | ||
| } | ||
|
|
||
| config := &schemas.ProviderConfig{} | ||
| config.CheckAndSetDefaults() | ||
| provider, err := edenai.NewEdenAIProvider(config, bifrost.NewNoOpLogger()) | ||
| if err != nil { | ||
| t.Fatalf("NewEdenAIProvider failed: %v", err) | ||
| } | ||
|
|
||
| ctx := schemas.NewBifrostContext(context.Background(), schemas.NoDeadline) | ||
| key := schemas.Key{Value: *schemas.NewSecretVar(apiKey), Models: schemas.WhiteList{"*"}} | ||
| content := "Reply with exactly: BIFROST-EDEN-OK" | ||
| request := &schemas.BifrostChatRequest{ | ||
| Provider: schemas.EdenAI, | ||
| Model: "openai/gpt-4o-mini", | ||
| Input: []schemas.ChatMessage{ | ||
| {Role: schemas.ChatMessageRoleUser, Content: &schemas.ChatMessageContent{ContentStr: &content}}, | ||
| }, | ||
| } | ||
|
|
||
| resp, bifErr := provider.ChatCompletion(ctx, key, request) | ||
| if bifErr != nil { | ||
| msg := "" | ||
| if bifErr.Error != nil { | ||
| msg = bifErr.Error.Message | ||
| } | ||
| t.Fatalf("live ChatCompletion returned error: %s", msg) | ||
| } | ||
| if resp == nil || len(resp.Choices) == 0 { | ||
| t.Fatalf("expected at least one choice in the response, got %+v", resp) | ||
| } | ||
| t.Logf("Eden AI live chat completion succeeded via Bifrost provider (%d choice(s))", len(resp.Choices)) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package edenai | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/maximhq/bifrost/core/schemas" | ||
| ) | ||
|
|
||
| // Compile-time check that edenaiProvider satisfies the full Provider interface. | ||
| var _ schemas.Provider = (*edenaiProvider)(nil) | ||
|
|
||
| func TestEdenAIProviderConstructorDefaults(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| config := &schemas.ProviderConfig{} | ||
| config.CheckAndSetDefaults() | ||
| provider, err := NewEdenAIProvider(config, nil) | ||
| if err != nil { | ||
| t.Fatalf("NewEdenAIProvider failed: %v", err) | ||
| } | ||
| if provider.GetProviderKey() != schemas.EdenAI { | ||
| t.Errorf("expected provider key %s, got %s", schemas.EdenAI, provider.GetProviderKey()) | ||
| } | ||
| if provider.networkConfig.BaseURL != "https://api.edenai.run/v3" { | ||
| t.Errorf("expected base URL https://api.edenai.run/v3, got %s", provider.networkConfig.BaseURL) | ||
| } | ||
| } | ||
|
|
||
| func TestEdenAIUnsupportedOperations(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| p := &edenaiProvider{} | ||
|
|
||
| if _, err := p.TextCompletion(nil, schemas.Key{}, nil); err == nil { | ||
| t.Error("expected TextCompletion to be unsupported") | ||
| } | ||
| if _, err := p.Embedding(nil, schemas.Key{}, nil); err == nil { | ||
| t.Error("expected Embedding to be unsupported") | ||
| } | ||
| if _, err := p.Speech(nil, schemas.Key{}, nil); err == nil { | ||
| t.Error("expected Speech to be unsupported") | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| --- | ||
| title: "Eden AI" | ||
| description: "Eden AI integration guide - a European, OpenAI-compatible gateway to 100+ models with a single key." | ||
| icon: "globe" | ||
| --- | ||
|
|
||
| ## Overview | ||
|
|
||
| [Eden AI](https://www.edenai.co/) is a **European, OpenAI-compatible** gateway that provides access to 100+ models from many providers (Mistral, OpenAI, Anthropic, Google, Cohere, DeepSeek, and more) through a single unified API and one key. Bifrost delegates to the OpenAI implementation, pointing at Eden's endpoint (`https://api.edenai.run/v3`). Key points: | ||
|
|
||
| - **One key, many providers** — route to models from many vendors through a single `EDENAI_API_KEY`. | ||
| - **EU-based gateway** — requests are served through an Europe-based gateway with GDPR-aligned data handling, useful for data-residency requirements. | ||
| - **OpenAI-compatible** — chat completions, streaming (SSE), tool calling, and `reasoning_effort` are handled through the OpenAI-compatible surface. | ||
| - **Model naming** — models keep the underlying `provider/model` form, e.g. `mistral/mistral-small-latest`, `openai/gpt-4o-mini`, `anthropic/claude-sonnet-4-5`. | ||
|
|
||
| ### Supported Operations | ||
|
|
||
| | Operation | Non-Streaming | Streaming | Endpoint | | ||
| |-----------|---------------|-----------|----------| | ||
| | Chat Completions | ✅ | ✅ | `/chat/completions` | | ||
| | Responses API | ✅ | ✅ | (delegated to Chat Completions) | | ||
| | List Models | ✅ | - | `/models` | | ||
| | Text Completions | ❌ | ❌ | - | | ||
| | Embeddings | ❌ | ❌ | - | | ||
| | Image Generation | ❌ | ❌ | - | | ||
| | Speech (TTS) | ❌ | ❌ | - | | ||
| | Transcriptions (STT) | ❌ | ❌ | - | | ||
|
|
||
| <Note> | ||
| Eden AI exposes its API under the `/v3` base path (`https://api.edenai.run/v3`), so the chat completions endpoint is `https://api.edenai.run/v3/chat/completions`. Errors are returned in the standard OpenAI error envelope. | ||
| </Note> | ||
|
|
||
| ## Setup & Configuration | ||
|
|
||
| Configure Eden AI as a provider. | ||
|
|
||
| <Tabs> | ||
| <Tab title="Web UI"> | ||
|
|
||
| 1. Navigate to **Models** > **Model Providers**. If **Eden AI** is not listed under **Configured Providers**, click **Add New Provider** and select **Eden AI**. | ||
| 2. Click **Add Key** or edit an existing key. | ||
| 3. Set a name for your key. | ||
| 4. Paste your API key directly or use an environment variable (for example, `env.EDENAI_API_KEY`). | ||
| 5. Set **Allowed Models** to **All Models** (default) or a specific allowlist. | ||
| 6. Save the provider configuration. | ||
|
|
||
| </Tab> | ||
| <Tab title="config.json"> | ||
|
|
||
| ```json | ||
| { | ||
| "providers": { | ||
| "edenai": { | ||
| "keys": [ | ||
| { | ||
| "name": "edenai-key-1", | ||
| "value": "env.EDENAI_API_KEY", | ||
| "models": [ | ||
| "*" | ||
| ], | ||
| "weight": 1.0 | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The default base URL is `https://api.edenai.run/v3`. You can override it via the provider's `network_config.base_url` if needed. | ||
|
|
||
| </Tab> | ||
| </Tabs> | ||
|
|
||
| ## Usage | ||
|
|
||
| ```bash | ||
| curl -X POST http://localhost:8080/v1/chat/completions \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{ | ||
| "model": "edenai/mistral/mistral-small-latest", | ||
| "messages": [{"role": "user", "content": "Hello from a sovereign EU stack!"}] | ||
| }' | ||
| ``` | ||
|
|
||
| Get an API key from your [Eden AI account](https://www.edenai.co/) and see the [Eden AI documentation](https://docs.edenai.co/) for the full list of available models. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only 3 of the ~30 unsupported operations are asserted. If a future refactor accidentally wires one of the others (e.g.
Embedding,Rerank,ImageGeneration) to a real implementation path, the test suite won't catch the regression. The repo pattern for new providers uses table-driven sweeps over all unsupported ops — e.g. looping over a slice offunc() *schemas.BifrostErrorcalls and asserting each returns non-nil. Also note that the repo'smake test-coretarget runs the shared provider scenario suite; the PR description references barego test ./core/providers/edenai/..., which skips that broader coverage.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!