| 16 | * migrated to gemini-embedding-001 for backward compatibility. |
| 17 | */ |
| 18 | export class GeminiEmbedder implements IEmbedder { |
| 19 | private readonly openAICompatibleEmbedder: OpenAICompatibleEmbedder |
| 20 | private static readonly GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/" |
| 21 | private static readonly DEFAULT_MODEL = "gemini-embedding-001" |
| 22 | /** |
| 23 | * Deprecated models that are automatically migrated to their replacements. |
| 24 | * Users with these models configured will be silently migrated without interruption. |
| 25 | */ |
| 26 | private static readonly DEPRECATED_MODEL_MIGRATIONS: Record<string, string> = { |
| 27 | "text-embedding-004": "gemini-embedding-001", |
| 28 | } |
| 29 | private readonly modelId: string |
| 30 | |
| 31 | /** |
| 32 | * Migrates deprecated model IDs to their replacements. |
| 33 | * @param modelId The model ID to potentially migrate |
| 34 | * @returns The migrated model ID, or the original if no migration is needed |
| 35 | */ |
| 36 | private static migrateModelId(modelId: string): string { |
| 37 | return GeminiEmbedder.DEPRECATED_MODEL_MIGRATIONS[modelId] ?? modelId |
| 38 | } |
| 39 | |
| 40 | /** |
| 41 | * Creates a new Gemini embedder |
| 42 | * @param apiKey The Gemini API key for authentication |
| 43 | * @param modelId The model ID to use (defaults to gemini-embedding-001) |
| 44 | */ |
| 45 | constructor(apiKey: string, modelId?: string) { |
| 46 | if (!apiKey) { |
| 47 | throw new Error(t("embeddings:validation.apiKeyRequired")) |
| 48 | } |
| 49 | |
| 50 | // Migrate deprecated models to their replacements silently |
| 51 | const migratedModelId = modelId ? GeminiEmbedder.migrateModelId(modelId) : undefined |
| 52 | |
| 53 | // Use provided model (after migration) or default |
| 54 | this.modelId = migratedModelId || GeminiEmbedder.DEFAULT_MODEL |
| 55 | |
| 56 | // Create an OpenAI Compatible embedder with Gemini's configuration |
| 57 | this.openAICompatibleEmbedder = new OpenAICompatibleEmbedder( |
| 58 | GeminiEmbedder.GEMINI_BASE_URL, |
| 59 | apiKey, |
| 60 | this.modelId, |
| 61 | GEMINI_MAX_ITEM_TOKENS, |
| 62 | ) |
| 63 | } |
| 64 | |
| 65 | /** |
| 66 | * Creates embeddings for the given texts using Gemini's embedding API |
| 67 | * @param texts Array of text strings to embed |
| 68 | * @param model Optional model identifier (uses constructor model if not provided) |
| 69 | * @returns Promise resolving to embedding response |
| 70 | */ |
| 71 | async createEmbeddings(texts: string[], model?: string): Promise<EmbeddingResponse> { |
| 72 | try { |
| 73 | // Use the provided model or fall back to the instance's model |
| 74 | const modelToUse = model || this.modelId |
| 75 | return await this.openAICompatibleEmbedder.createEmbeddings(texts, modelToUse) |
nothing calls this directly
no outgoing calls
no test coverage detected