feat: add OpenRouter as embedding provider name#304
feat: add OpenRouter as embedding provider name#304BeamNawapat wants to merge 1 commit intozilliztech:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds OpenRouter as a first-class embedding provider (via OpenRouter’s OpenAI-compatible API) so users no longer need to rely on the OPENAI_BASE_URL workaround and can use OpenRouter-style model IDs like openai/text-embedding-3-small.
Changes:
- Introduce
OpenRouterEmbeddingprovider in core (OpenAI SDK + OpenRouter base URL, supported-model metadata). - Wire
OpenRouterinto MCP config/env (OPENROUTER_API_KEY) and embedding-provider selection switch. - Export the new provider from the core embedding barrel.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| packages/core/src/embedding/openrouter-embedding.ts | New embedding provider implementation using OpenAI SDK routed through OpenRouter. |
| packages/core/src/embedding/index.ts | Exports the new OpenRouter embedding provider. |
| packages/mcp/src/config.ts | Extends config/provider union, adds OpenRouter default model and API key env wiring. |
| packages/mcp/src/embedding.ts | Adds OpenRouter provider case to instance creation and provider-info logging. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (knownModels[model]) { | ||
| return knownModels[model].dimension; | ||
| } | ||
|
|
There was a problem hiding this comment.
OpenRouterEmbedding.getDimension() returns the default this.dimension for unknown/custom models without any warning. Since other implementations (e.g., OpenAIEmbedding) explicitly warn that the value may be incorrect until detectDimension()/embed() is called, this can lead to misleading logs and harder debugging when users supply non-listed OpenRouter model IDs. Consider adding a warning for the unknown-model path (or otherwise documenting that the returned dimension may be stale until detection runs).
| console.warn( | |
| `OpenRouter model "${model}" is not in the supported models list; returning cached/default dimension ` + | |
| `${this.dimension}. This value may be incorrect until detectDimension(), embed(), or embedBatch() runs.` | |
| ); |
| voyageaiApiKey: envManager.get('VOYAGEAI_API_KEY'), | ||
| geminiApiKey: envManager.get('GEMINI_API_KEY'), | ||
| geminiBaseUrl: envManager.get('GEMINI_BASE_URL'), | ||
| // OpenRouter configuration | ||
| openrouterApiKey: envManager.get('OPENROUTER_API_KEY'), |
There was a problem hiding this comment.
createMcpConfig() prints a debug summary of relevant env vars (e.g., GEMINI_API_KEY, OPENAI_API_KEY), but the newly introduced OPENROUTER_API_KEY isn’t included. Adding it to the debug output (ideally with the same “SET (length: …)” pattern) would make troubleshooting OpenRouter configuration consistent with the other providers.
zc277584121
left a comment
There was a problem hiding this comment.
Thanks for the contribution! The motivation makes sense — giving OpenRouter users a cleaner config experience. However, I have some concerns about the current approach.
Main issue: code duplication
openrouter-embedding.ts (151 lines) is nearly identical to openai-embedding.ts. Both use the openai npm package, same embeddings.create() calls, same error handling, same detectDimension logic. The only real differences are:
- Default
baseURL→https://openrouter.ai/api/v1 - Default model →
openai/text-embedding-3-small - Supported model list (3 entries, all just OpenAI models with
openai/prefix)
Users can already achieve the same result today:
EMBEDDING_PROVIDER=OpenAI \
OPENAI_BASE_URL=https://openrouter.ai/api/v1 \
OPENAI_API_KEY=sk-or-v1-xxx \
EMBEDDING_MODEL=openai/text-embedding-3-smallSuggested alternatives
If we do want a first-class OpenRouter provider name for better UX, it should reuse OpenAIEmbedding rather than duplicate it. Something like:
// In createEmbeddingInstance:
case 'OpenRouter':
if (!config.openrouterApiKey) {
throw new Error('OPENROUTER_API_KEY is required');
}
return new OpenAIEmbedding({
apiKey: config.openrouterApiKey,
model: config.embeddingModel,
baseURL: 'https://openrouter.ai/api/v1',
});This achieves the same user-facing behavior (~5 lines vs 151 lines) and avoids maintaining two copies of the same logic.
Alternatively, just document the OPENAI_BASE_URL approach in the README — that may be sufficient.
Add OpenRouter as a first-class provider name for cleaner UX. Reuses OpenAIEmbedding internally with OpenRouter's OpenAI-compatible endpoint, avoiding code duplication. New env vars: EMBEDDING_PROVIDER=OpenRouter, OPENROUTER_API_KEY
df317bf to
24c2bb9
Compare
|
Good call — 151 lines of duplication was unnecessary. Reworked to reuse case 'OpenRouter':
return new OpenAIEmbedding({
apiKey: config.openrouterApiKey,
model: config.embeddingModel,
baseURL: 'https://openrouter.ai/api/v1',
});Force-pushed. Now 2 files changed, ~30 lines total. No new files, no new dependencies. |
Summary
Add OpenRouter as a first-class provider name for cleaner UX. Reuses
OpenAIEmbeddinginternally with OpenRouter's OpenAI-compatible endpoint — zero code duplication.Motivation
Users can achieve the same result via
OPENAI_BASE_URLworkaround, but a named provider gives better discoverability and simpler configuration.Changes (2 files, ~30 lines)
packages/mcp/src/config.ts— AddOpenRouterto provider union,OPENROUTER_API_KEYenv var, default model, help messagepackages/mcp/src/embedding.ts— AddOpenRoutercase that createsOpenAIEmbeddingwithbaseURL: 'https://openrouter.ai/api/v1'No new files. No new dependencies. No code duplication.
Usage
Test plan
pnpm buildpasses