vecbox 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../main.ts","../src/providers/openai.ts","../src/providers/base/EmbeddingProvider.ts","../src/util/logger.ts","../src/providers/gemini.ts","../src/providers/claude.ts","../src/providers/mistral.ts","../src/providers/deepseek.ts","../src/providers/llamacpp.ts","../src/factory/EmbeddingFactory.ts","../index.ts"],"sourcesContent":["import * as dotenv from 'dotenv';\nimport { EmbeddingFactory } from '@src/factory/EmbeddingFactory.js';\nimport type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index.js';\nimport { Logger } from '@src/util/logger.js';\n\n// Load environment variables\ndotenv.config();\n\nconst logger = Logger.createModuleLogger('main');\n\n/**\n * Main embedding interface - Simple and minimal API\n * \n * @param config - Provider configuration\n * @param input - Text or file to embed\n * @returns Promise<EmbedResult | BatchEmbedResult>\n */\nexport async function embed(\n config: EmbedConfig,\n input: EmbedInput | EmbedInput[]\n): Promise<EmbedResult | BatchEmbedResult> {\n try {\n logger.info(`Starting embedding with provider: ${config.provider}`);\n \n // Create provider instance\n const provider = EmbeddingFactory.create(config);\n \n // Check if provider is ready\n const isReady = await provider.isReady();\n if (!isReady) {\n throw new Error(`Provider ${config.provider} is not ready`);\n }\n \n // Handle single input or batch\n if (Array.isArray(input)) {\n logger.debug(`Processing batch of ${input.length} items`);\n return await provider.embedBatch(input);\n } else {\n logger.debug(`Processing single item`);\n return await provider.embed(input);\n }\n \n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Embedding failed: ${errorMessage}`);\n throw error;\n }\n}\n\n/**\n * Convenience function for quick embedding with auto-detection\n * \n * @param input - Text or file to embed\n * @returns Promise<EmbedResult | BatchEmbedResult>\n */\nexport async function autoEmbed(\n input: EmbedInput | EmbedInput[]\n): Promise<EmbedResult | BatchEmbedResult> {\n logger.info('Auto-detecting best provider...');\n \n // Try providers in order of preference\n const providers = [\n { provider: 'llamacpp' as const, model: 'nomic-embed-text-v1.5.Q4_K_M.gguf' }, // Local & free (llama.cpp)\n { provider: 'openai' as const, model: 'text-embedding-3-small', apiKey: process.env.OPENAI_API_KEY || undefined },\n { provider: 'gemini' as const, model: 'gemini-embedding-001', apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY || undefined },\n { provider: 'mistral' as const, model: 'mistral-embed', apiKey: process.env.MISTRAL_API_KEY || undefined },\n { provider: 'deepseek' as const, model: 'deepseek-chat', apiKey: process.env.DEEPSEEK_API_KEY || undefined },\n ];\n \n for (const config of providers) {\n try {\n // Llama.cpp provider doesn't need API key and should be tried first\n if (config.provider === 'llamacpp' || config.apiKey) {\n logger.info(`Trying provider: ${config.provider}`);\n // Create a clean config object without undefined properties\n const cleanConfig: EmbedConfig = {\n provider: config.provider,\n model: config.model,\n };\n \n if (config.apiKey) {\n cleanConfig.apiKey = config.apiKey;\n }\n \n return await embed(cleanConfig, input);\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.warn(`Provider ${config.provider} failed: ${errorMessage}`);\n continue;\n }\n }\n \n throw new Error('No available embedding provider found');\n}\n\n/**\n * Get supported providers\n */\nexport function getSupportedProviders() {\n return EmbeddingFactory.getSupportedProviders();\n}\n\n/**\n * Create a specific provider instance\n */\nexport function createProvider(config: EmbedConfig) {\n return EmbeddingFactory.create(config);\n}\n\n// Export types for external use\nexport type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult, ProviderType } from './src/types/index.js';","import OpenAI from 'openai';\nimport { EmbeddingProvider } from '@providers/base/EmbeddingProvider';\nimport type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';\nimport { Logger } from '@src/util/logger';\n\nconst logger = Logger.createModuleLogger('openai');\n\nexport class OpenAIProvider extends EmbeddingProvider {\n private client: OpenAI;\n\n constructor(config: EmbedConfig) {\n super(config);\n \n if (!config.apiKey) {\n throw new Error('OpenAI API key is required');\n }\n\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseUrl,\n timeout: config.timeout || 30000,\n });\n\n logger.info('OpenAI provider initialized');\n }\n\n async embed(input: EmbedInput): Promise<EmbedResult> {\n try {\n const text = await this.readInput(input);\n logger.debug(`Embedding text with model: ${this.getModel()}`);\n\n const response = await this.client.embeddings.create({\n model: this.getModel(),\n input: text,\n });\n\n const embedding = response.data[0];\n if (!embedding) {\n throw new Error('No embedding returned from OpenAI API');\n }\n\n return {\n embedding: embedding.embedding || [],\n dimensions: embedding.embedding?.length || 0,\n model: response.model,\n provider: 'openai',\n usage: response.usage ? {\n promptTokens: response.usage.prompt_tokens,\n totalTokens: response.usage.total_tokens,\n } : undefined,\n };\n } catch (error: unknown) {\n logger.error(`OpenAI embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n async embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult> {\n try {\n const texts = await Promise.all(inputs.map(input => this.readInput(input)));\n logger.debug(`Batch embedding ${texts.length} texts with model: ${this.getModel()}`);\n\n const response = await this.client.embeddings.create({\n model: this.getModel(),\n input: texts,\n });\n\n const embeddings = response.data.map(item => item.embedding);\n\n return {\n embeddings,\n dimensions: embeddings[0]?.length || 0,\n model: response.model,\n provider: 'openai',\n usage: response.usage ? {\n promptTokens: response.usage.prompt_tokens,\n totalTokens: response.usage.total_tokens,\n } : undefined,\n };\n } catch (error: unknown) {\n logger.error(`OpenAI batch embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n getDimensions(): number {\n // Common OpenAI embedding dimensions\n const model = this.getModel();\n if (model.includes('text-embedding-3-large')) return 3072;\n if (model.includes('text-embedding-3-small')) return 1536;\n if (model.includes('text-embedding-ada-002')) return 1536;\n return 1536; // default\n }\n\n getProviderName(): string {\n return 'OpenAI';\n }\n\n async isReady(): Promise<boolean> {\n try {\n await this.client.models.list();\n return true;\n } catch (error: unknown) {\n logger.error(`OpenAI readiness check failed: ${(error instanceof Error ? error.message : String(error))}`);\n return false;\n }\n }\n}\n","import type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';\n\nexport abstract class EmbeddingProvider {\n protected config: EmbedConfig;\n\n constructor(config: EmbedConfig) {\n this.config = config;\n }\n\n abstract embed(input: EmbedInput): Promise<EmbedResult>;\n abstract embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult>;\n abstract getDimensions(): number;\n abstract getProviderName(): string;\n abstract isReady(): Promise<boolean>;\n\n protected getModel(): string {\n return this.config.model || 'default';\n }\n\n protected async readInput(input: EmbedInput): Promise<string> {\n if (input.text) {\n return input.text;\n }\n \n if (input.filePath) {\n const fs = await import('fs/promises');\n return await fs.readFile(input.filePath, 'utf-8');\n }\n \n throw new Error('Either text or filePath must be provided');\n }\n}\n","export enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n}\n\nexport interface LogEntry {\n level: LogLevel;\n message: string;\n module: string;\n timestamp: Date;\n}\n\nexport class Logger {\n private static instance: Logger;\n private currentLevel: LogLevel;\n private moduleName: string;\n\n // ANSI color codes - simplified for better readability\n private static readonly COLORS = {\n RESET: '\\x1b[0m',\n DEBUG: '\\x1b[36m', // Cyan\n INFO: '\\x1b[32m', // Green \n WARN: '\\x1b[33m', // Yellow\n ERROR: '\\x1b[31m', // Red\n };\n\n private static readonly LEVEL_NAMES = {\n [LogLevel.DEBUG]: 'DEBUG',\n [LogLevel.INFO]: 'INFO',\n [LogLevel.WARN]: 'WARN',\n [LogLevel.ERROR]: 'ERROR',\n };\n\n constructor(moduleName: string = 'embedbox', level: LogLevel = LogLevel.INFO) {\n this.moduleName = moduleName;\n this.currentLevel = level;\n }\n\n static getInstance(moduleName?: string, level?: LogLevel): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger(moduleName || 'embedbox', level);\n }\n return Logger.instance;\n }\n\n setLevel(level: LogLevel): void {\n this.currentLevel = level;\n }\n\n getLevel(): LogLevel {\n return this.currentLevel;\n }\n\n private formatMessage(level: LogLevel, message: string): string {\n const levelName = Logger.LEVEL_NAMES[level];\n const color = Logger.COLORS[levelName as keyof typeof Logger.COLORS];\n const reset = Logger.COLORS.RESET;\n\n return `${color}[${levelName}(${this.moduleName})]${reset} ${message}\\n\\n`;\n }\n\n private log(level: LogLevel, message: string): void {\n if (level < this.currentLevel) {\n return;\n }\n\n const formattedMessage = this.formatMessage(level, message);\n process.stdout.write(formattedMessage);\n }\n\n debug(message: string): void {\n this.log(LogLevel.DEBUG, message);\n }\n\n info(message: string): void {\n this.log(LogLevel.INFO, message);\n }\n\n warn(message: string): void {\n this.log(LogLevel.WARN, message);\n }\n\n error(message: string): void {\n this.log(LogLevel.ERROR, message);\n }\n\n // Static methods for quick access\n static debug(message: string, moduleName?: string): void {\n const logger = new Logger(moduleName || 'embedbox');\n logger.debug(message);\n }\n\n static info(message: string, moduleName?: string): void {\n const logger = new Logger(moduleName || 'embedbox');\n logger.info(message);\n }\n\n static warn(message: string, moduleName?: string): void {\n const logger = new Logger(moduleName || 'embedbox');\n logger.warn(message);\n }\n\n static error(message: string, moduleName?: string): void {\n const logger = new Logger(moduleName || 'embedbox');\n logger.error(message);\n }\n\n // Method to create a logger instance for a specific module\n static createModuleLogger(moduleName: string, level?: LogLevel): Logger {\n return new Logger(`embedbox:${moduleName}`, level);\n }\n}\n\n// Export a default logger instance\nexport const logger = Logger.getInstance();\n\n// Export convenience functions\nexport const log = {\n debug: (message: string, moduleName?: string) => Logger.debug(message, moduleName),\n info: (message: string, moduleName?: string) => Logger.info(message, moduleName),\n warn: (message: string, moduleName?: string) => Logger.warn(message, moduleName),\n error: (message: string, moduleName?: string) => Logger.error(message, moduleName),\n};\n","import { GoogleGenerativeAI } from '@google/generative-ai';\nimport { EmbeddingProvider } from '@providers/base/EmbeddingProvider';\nimport type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';\nimport { Logger } from '@src/util/logger';\n\nconst logger = Logger.createModuleLogger('gemini');\n\nexport class GeminiProvider extends EmbeddingProvider {\n private client: GoogleGenerativeAI;\n\n constructor(config: EmbedConfig) {\n super(config);\n \n if (!config.apiKey) {\n throw new Error('Google API key is required');\n }\n\n this.client = new GoogleGenerativeAI(config.apiKey);\n logger.info('Gemini provider initialized');\n }\n\n async embed(input: EmbedInput): Promise<EmbedResult> {\n try {\n const text = await this.readInput(input);\n logger.debug(`Embedding text with model: ${this.getModel()}`);\n\n // Get the embedding model\n const model = this.client.getGenerativeModel({ \n model: this.getModel() \n });\n\n // Use the embedding task\n const result = await model.embedContent(text);\n const embedding = result.embedding;\n\n return {\n embedding: embedding.values,\n dimensions: embedding.values.length,\n model: this.getModel(),\n provider: 'gemini',\n };\n } catch (error: unknown) {\n logger.error(`Gemini embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n async embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult> {\n try {\n const texts = await Promise.all(inputs.map(input => this.readInput(input)));\n logger.debug(`Batch embedding ${texts.length} texts with model: ${this.getModel()}`);\n\n const model = this.client.getGenerativeModel({ \n model: this.getModel() \n });\n\n const results = await Promise.all(\n texts.map(text => model.embedContent(text))\n );\n\n const embeddings = results.map((result: { embedding: { values: number[] } }) => result.embedding.values);\n\n return {\n embeddings,\n dimensions: embeddings[0]?.length || 0,\n model: this.getModel(),\n provider: 'gemini',\n };\n } catch (error: unknown) {\n logger.error(`Gemini batch embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n getDimensions(): number {\n const model = this.getModel();\n if (model.includes('gemini-embedding-001')) return 768;\n if (model.includes('text-embedding-004')) return 768;\n if (model.includes('embedding-001')) return 768;\n if (model.includes('multimodalembedding')) return 768;\n return 768; // default for Gemini embeddings\n }\n\n getProviderName(): string {\n return 'Google Gemini';\n }\n\n protected getModel(): string {\n return this.config.model || 'gemini-embedding-001';\n }\n\n async isReady(): Promise<boolean> {\n try {\n const model = this.client.getGenerativeModel({ \n model: this.getModel() \n });\n // Test with a simple embedding\n await model.embedContent('test');\n return true;\n } catch (error: unknown) {\n logger.error(`Gemini readiness check failed: ${(error instanceof Error ? error.message : String(error))}`);\n return false;\n }\n }\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport { EmbeddingProvider } from '@providers/base/EmbeddingProvider';\nimport type { EmbedConfig, EmbedResult, BatchEmbedResult } from '@src/types/index';\nimport { Logger } from '@src/util/logger';\n\nconst logger = Logger.createModuleLogger('claude');\n\nexport class ClaudeProvider extends EmbeddingProvider {\n private client: Anthropic;\n\n constructor(config: EmbedConfig) {\n super(config);\n \n if (!config.apiKey) {\n throw new Error('Anthropic API key is required');\n }\n\n this.client = new Anthropic({\n apiKey: config.apiKey,\n baseURL: config.baseUrl,\n timeout: config.timeout || 30000,\n });\n\n logger.info('Claude provider initialized');\n }\n\n async embed(): Promise<EmbedResult> {\n try {\n logger.debug(`Embedding text with model: ${this.getModel()}`);\n\n // Note: Claude doesn't have native embeddings API yet\n // This is a placeholder implementation\n throw new Error('Claude embeddings API not yet available. Please use another provider.');\n \n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? (error instanceof Error ? error.message : String(error)) : 'Unknown error';\n logger.error(`Claude embedding failed: ${errorMessage}`);\n throw error;\n }\n }\n\n async embedBatch(): Promise<BatchEmbedResult> {\n try {\n // Note: Claude doesn't have native embeddings API yet\n throw new Error('Claude embeddings API not yet available. Please use another provider.');\n \n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? (error instanceof Error ? error.message : String(error)) : 'Unknown error';\n logger.error(`Claude batch embedding failed: ${errorMessage}`);\n throw error;\n }\n }\n\n getDimensions(): number {\n // Claude doesn't have embeddings yet\n return 0;\n }\n\n getProviderName(): string {\n return 'Anthropic Claude';\n }\n\n async isReady(): Promise<boolean> {\n try {\n // Test API access\n await this.client.messages.create({\n model: 'claude-3-haiku-20240307',\n max_tokens: 10,\n messages: [{ role: 'user', content: 'test' }]\n });\n return true;\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? (error instanceof Error ? error.message : String(error)) : 'Unknown error';\n logger.error(`Claude readiness check failed: ${errorMessage}`);\n return false;\n }\n }\n}\n","import { Mistral } from '@mistralai/mistralai';\nimport { EmbeddingProvider } from '@providers/base/EmbeddingProvider';\nimport type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';\nimport { Logger } from '@src/util/logger';\n\nconst logger = Logger.createModuleLogger('mistral');\n\nexport class MistralProvider extends EmbeddingProvider {\n private client: Mistral;\n\n constructor(config: EmbedConfig) {\n super(config);\n \n if (!config.apiKey) {\n throw new Error('Mistral API key is required');\n }\n\n this.client = new Mistral({\n apiKey: config.apiKey,\n serverURL: config.baseUrl,\n timeoutMs: config.timeout || 30000,\n });\n\n logger.info('Mistral provider initialized');\n }\n\n async embed(input: EmbedInput): Promise<EmbedResult> {\n try {\n const text = await this.readInput(input);\n logger.debug(`Embedding text with model: ${this.getModel()}`);\n\n const response = await this.client.embeddings.create({\n model: this.getModel(),\n inputs: [text],\n });\n\n const embedding = response.data[0];\n if (!embedding) {\n throw new Error('No embedding returned from Mistral API');\n }\n\n return {\n embedding: embedding.embedding || [],\n dimensions: embedding.embedding?.length || 0,\n model: response.model,\n provider: 'mistral',\n usage: response.usage?.promptTokens && response.usage?.totalTokens ? {\n promptTokens: response.usage.promptTokens,\n totalTokens: response.usage.totalTokens,\n } : undefined,\n };\n } catch (error: unknown) {\n logger.error(`Mistral embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n async embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult> {\n try {\n const texts = await Promise.all(inputs.map(input => this.readInput(input)));\n logger.debug(`Batch embedding ${texts.length} texts with model: ${this.getModel()}`);\n\n const response = await this.client.embeddings.create({\n model: this.getModel(),\n inputs: texts,\n });\n\n const embeddings = response.data.map((item) => {\n if (!item.embedding) throw new Error('No embedding returned from Mistral API');\n return item.embedding as number[];\n });\n\n return {\n embeddings,\n dimensions: embeddings[0]?.length || 0,\n model: response.model,\n provider: 'mistral',\n usage: response.usage?.promptTokens && response.usage?.totalTokens ? {\n promptTokens: response.usage.promptTokens,\n totalTokens: response.usage.totalTokens,\n } : undefined,\n };\n } catch (error: unknown) {\n logger.error(`Mistral batch embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n getDimensions(): number {\n // Mistral embedding dimensions\n const model = this.getModel();\n if (model.includes('mistral-embed')) return 1024;\n return 1024; // default for Mistral\n }\n\n getProviderName(): string {\n return 'Mistral AI';\n }\n\n async isReady(): Promise<boolean> {\n try {\n // Test with a simple embedding request\n const response = await this.client.embeddings.create({\n model: this.getModel(),\n inputs: ['test'],\n });\n return response.data.length > 0;\n } catch (error: unknown) {\n logger.error(`Mistral readiness check failed: ${(error instanceof Error ? error.message : String(error))}`);\n return false;\n }\n }\n}\n","import { DeepSeek } from 'deepseek';\nimport { EmbeddingProvider } from '@providers/base/EmbeddingProvider';\nimport type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';\nimport { Logger } from '@src/util/logger';\n\nconst logger = Logger.createModuleLogger('deepseek');\n\nexport class DeepSeekProvider extends EmbeddingProvider {\n private client: DeepSeek;\n\n constructor(config: EmbedConfig) {\n super(config);\n \n if (!config.apiKey) {\n throw new Error('DeepSeek API key is required');\n }\n\n const clientOptions: { apiKey: string; timeout: number; baseURL?: string } = {\n apiKey: config.apiKey,\n timeout: config.timeout || 30000,\n };\n \n if (config.baseUrl) {\n clientOptions.baseURL = config.baseUrl;\n }\n\n this.client = new DeepSeek(clientOptions);\n\n logger.info('DeepSeek provider initialized');\n }\n\n async embed(input: EmbedInput): Promise<EmbedResult> {\n try {\n const text = await this.readInput(input);\n logger.debug(`Embedding text with model: ${this.getModel()}`);\n\n const response = await this.client.embeddings.create({\n model: this.getModel(),\n input: text,\n });\n\n const embedding = response.data[0];\n if (!embedding) {\n throw new Error('No embedding returned from DeepSeek API');\n }\n\n return {\n embedding: embedding.embedding || [],\n dimensions: embedding.embedding?.length || 0,\n model: embedding.model || this.getModel(),\n provider: 'deepseek',\n usage: response.usage ? {\n promptTokens: response.usage.prompt_tokens,\n totalTokens: response.usage.total_tokens,\n } : undefined,\n };\n } catch (error: unknown) {\n logger.error(`DeepSeek embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n async embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult> {\n try {\n const texts = await Promise.all(inputs.map(input => this.readInput(input)));\n logger.debug(`Batch embedding ${texts.length} texts with model: ${this.getModel()}`);\n\n const response = await this.client.embeddings.create({\n model: this.getModel(),\n input: texts,\n });\n\n const embeddings = response.data.map((item: { embedding: number[] }) => item.embedding);\n\n return {\n embeddings,\n dimensions: embeddings[0]?.length || 0,\n model: response.model,\n provider: 'deepseek',\n usage: response.usage ? {\n promptTokens: response.usage.prompt_tokens,\n totalTokens: response.usage.total_tokens,\n } : undefined,\n };\n } catch (error: unknown) {\n logger.error(`DeepSeek batch embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n getDimensions(): number {\n // DeepSeek embedding dimensions\n const model = this.getModel();\n if (model.includes('deepseek-chat')) return 4096;\n return 4096; // default for DeepSeek\n }\n\n getProviderName(): string {\n return 'DeepSeek';\n }\n\n async isReady(): Promise<boolean> {\n try {\n // Test with a simple embedding request\n await this.client.embeddings.create({\n model: this.getModel(),\n input: 'test',\n });\n return true;\n } catch (error: unknown) {\n logger.error(`DeepSeek readiness check failed: ${(error instanceof Error ? error.message : String(error))}`);\n return false;\n }\n }\n}\n","/**\n * Llama.cpp Provider - Local embeddings using llama.cpp directly\n * Uses llama-embedding binary without any external dependencies\n */\n\nimport { access, constants } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport { EmbeddingProvider } from '@providers/base/EmbeddingProvider';\nimport type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';\nimport { logger } from '@src/util/logger';\nimport * as http from 'http';\n\n// Extend EmbedConfig to include llamaPath\ninterface LlamaCppConfig extends EmbedConfig {\n llamaPath?: string;\n}\n\nexport class LlamaCppProvider extends EmbeddingProvider {\n private llamaPath: string;\n private modelPath: string;\n\n constructor(config: LlamaCppConfig) {\n super({ ...config, provider: 'llamacpp' });\n this.modelPath = config.model || 'nomic-embed-text-v1.5.Q4_K_M.gguf';\n this.llamaPath = config.llamaPath || './llama.cpp/build/bin/llama-embedding';\n logger.info(`Llama.cpp provider initialized with model: ${this.modelPath}`);\n }\n\n // Public API methods\n getProviderName(): string {\n return 'Llama.cpp';\n }\n\n getDimensions(): number {\n // Known dimensions for common models\n const model = this.getModel();\n if (model.includes('nomic-embed-text-v1.5')) return 768;\n if (model.includes('nomic-embed-text-v1')) return 768;\n if (model.includes('all-MiniLM-L6-v2')) return 384;\n if (model.includes('bge-base')) return 768;\n if (model.includes('bert-base')) return 768;\n return 768; // default\n }\n\n async isReady(): Promise<boolean> {\n try {\n // Check if llama-embedding exists and is executable\n await access(this.llamaPath, constants.F_OK);\n await access(this.llamaPath, constants.X_OK);\n \n // Check if model file exists\n const modelPath = await this.getModelPath();\n await access(modelPath, constants.F_OK);\n \n logger.debug('Llama.cpp provider is ready');\n return true;\n } catch (error: unknown) {\n logger.error(`Llama.cpp readiness check failed: ${(error instanceof Error ? error.message : String(error))}`);\n return false;\n }\n }\n\n async embed(input: EmbedInput): Promise<EmbedResult> {\n try {\n logger.debug(`Embedding text with llama.cpp: ${this.getModel()}`);\n \n const text = await this.readInput(input);\n if (!text.trim()) {\n throw new Error('Text input cannot be empty');\n }\n\n // Use HTTP API instead of CLI arguments\n const requestBody = {\n input: text,\n model: await this.getModelPath(),\n pooling: 'mean',\n normalize: 2\n };\n\n // Execute HTTP request to llama.cpp server\n const result = await this.executeLlamaEmbedding([JSON.stringify(requestBody)]);\n \n // Parse output to extract embedding\n const embedding = this.parseRawOutput(result.stdout);\n \n return {\n embedding,\n dimensions: embedding.length,\n model: this.getModel(),\n provider: 'llamacpp',\n };\n } catch (error: unknown) {\n logger.error(`Llama.cpp embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n async embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult> {\n try {\n logger.debug(`Batch embedding ${inputs.length} texts with llama.cpp`);\n \n const texts = [];\n for (const input of inputs) {\n const text = await this.readInput(input);\n if (text.trim()) {\n texts.push(text);\n }\n }\n \n if (texts.length === 0) {\n throw new Error('No valid texts to embed');\n }\n\n // For batch processing, use HTTP API\n const modelPath = await this.getModelPath();\n const requests = inputs.map(input => ({\n input: input.text || '',\n model: modelPath,\n pooling: 'mean',\n normalize: 2\n }));\n\n // Execute batch requests (for now, do individual requests)\n const embeddings: number[][] = [];\n for (const request of requests) {\n const result = await this.executeLlamaEmbedding([JSON.stringify(request)]);\n const embedding = this.parseRawOutput(result.stdout);\n embeddings.push(embedding);\n }\n \n return {\n embeddings,\n dimensions: embeddings[0]?.length || 0,\n model: this.getModel(),\n provider: 'llamacpp',\n };\n } catch (error: unknown) {\n logger.error(`Llama.cpp batch embedding failed: ${(error instanceof Error ? error.message : String(error))}`);\n throw error;\n }\n }\n\n // Protected methods\n protected getModel(): string {\n return this.modelPath;\n }\n\n // Private helper methods\n private async getModelPath(): Promise<string> {\n // Try different model paths\n const possiblePaths = [\n this.modelPath, // As provided\n join('./llama.cpp/models', this.modelPath), // In llama.cpp/models\n join('./llama.cpp', this.modelPath), // In llama.cpp root\n this.modelPath // Fallback\n ];\n\n for (const path of possiblePaths) {\n try {\n await access(path, constants.F_OK);\n return resolve(path);\n } catch {\n continue;\n }\n }\n\n throw new Error(`Model file not found: ${this.modelPath}`);\n }\n\n private async executeLlamaEmbedding(args: string[]): Promise<{stdout: string; stderr: string}> {\n return new Promise((resolve, reject) => {\n // Use HTTP API instead of CLI for cleaner output\n const port = 8080; // Default llama.cpp server port\n \n // Parse the request body from args[0] (JSON string)\n let requestBody;\n try {\n requestBody = JSON.parse(args[0] || '{}');\n } catch {\n reject(new Error('Invalid request body for HTTP API'));\n return;\n }\n\n const postData = JSON.stringify(requestBody);\n\n const options = {\n hostname: 'localhost',\n port: port,\n path: '/embedding',\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(postData)\n }\n };\n\n const req = http.request(options, (res: http.IncomingMessage) => {\n let data = '';\n \n res.on('data', (chunk: Buffer | string) => {\n data += chunk;\n });\n \n res.on('end', () => {\n if (res.statusCode === 200) {\n resolve({ stdout: data, stderr: '' });\n } else {\n reject(new Error(`HTTP ${res.statusCode}: ${data}`));\n }\n });\n });\n\n req.on('error', (error: Error) => {\n reject(new Error(`Failed to connect to llama.cpp server: ${(error instanceof Error ? error.message : String(error))}`));\n });\n\n req.write(postData);\n req.end();\n });\n }\n\n private parseRawOutput(output: string): number[] {\n try {\n const response = JSON.parse(output);\n \n logger.debug(`PARSE DEBUG: Response type: ${typeof response}`);\n logger.debug(`PARSE DEBUG: Is Array: ${Array.isArray(response)}`);\n \n // CASE 1: Array of objects with nested embedding\n // Format: [{index: 0, embedding: [[...]]}]\n if (Array.isArray(response) && response.length > 0) {\n const first = response[0];\n \n if (first && first.embedding && Array.isArray(first.embedding)) {\n const emb = first.embedding;\n \n // Check if nested: [[...]]\n if (Array.isArray(emb[0])) {\n const flat = emb[0]; // ← Take the inner array\n logger.debug(`Parsed ${flat.length} dimensions (nested)`);\n return flat;\n }\n \n // Not nested: [...]\n logger.debug(`Parsed ${emb.length} dimensions (direct)`);\n return emb;\n }\n }\n \n // CASE 2: Direct object {embedding: [...]}\n if (response.embedding && Array.isArray(response.embedding)) {\n const emb = response.embedding;\n \n // Check nested\n if (Array.isArray(emb[0])) {\n return emb[0];\n }\n \n return emb;\n }\n \n // CASE 3: Direct array of numbers\n if (Array.isArray(response) && typeof response[0] === 'number') {\n logger.debug(`Parsed ${response.length} dimensions (flat array)`);\n return response;\n }\n \n throw new Error(`Unexpected format: ${JSON.stringify(Object.keys(response))}`);\n \n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? (error instanceof Error ? error.message : String(error)) : 'Unknown error';\n throw new Error(`Parse failed: ${errorMessage}`, { cause: error });\n }\n }\n\n private parseArrayOutput(output: string): number[][] {\n // Parse array format: [[val1,val2,...], [val1,val2,...], ...]\n const arrayPattern = /\\[([^\\]]+)\\]/g;\n const matches = [...output.matchAll(arrayPattern)];\n \n if (matches.length === 0) {\n throw new Error('No array embeddings found in output');\n }\n\n const embeddings = matches.map(match => {\n const values = match[1]?.split(',').map(v => v.trim()) || [];\n return values.map(v => parseFloat(v)).filter(v => !isNaN(v));\n }).filter(embedding => embedding.length > 0);\n\n return embeddings;\n }\n}\n","import type { EmbedConfig, ProviderType } from '@src/types/index';\nimport { EmbeddingProvider } from '@providers/base/EmbeddingProvider';\nimport { OpenAIProvider } from '@providers/openai';\nimport { GeminiProvider } from '@providers/gemini';\nimport { ClaudeProvider } from '@providers/claude';\nimport { MistralProvider } from '@providers/mistral';\nimport { DeepSeekProvider } from '@providers/deepseek';\nimport { LlamaCppProvider } from '@providers/llamacpp';\nimport { Logger } from '@src/util/logger';\n\nconst logger = Logger.createModuleLogger('factory');\n\nexport class EmbeddingFactory {\n private static providers = new Map<ProviderType, new (config: EmbedConfig) => EmbeddingProvider>([\n ['openai', OpenAIProvider],\n ['gemini', GeminiProvider],\n ['claude', ClaudeProvider],\n ['mistral', MistralProvider],\n ['deepseek', DeepSeekProvider],\n ['llamacpp', LlamaCppProvider], // Local embeddings with llama.cpp\n ]);\n\n static create(config: EmbedConfig) {\n logger.info(`Creating provider: ${config.provider}`);\n \n const ProviderClass = this.providers.get(config.provider);\n if (!ProviderClass) {\n throw new Error(`Unsupported provider: ${config.provider}`);\n }\n\n return new ProviderClass(config);\n }\n\n static getSupportedProviders(): ProviderType[] {\n return Array.from(this.providers.keys());\n }\n}\n","/**\n * Embedbox v1.0.0 - Main Entry Point\n * \n * A minimal and powerful embedding library that supports multiple providers\n * with automatic detection and fallback capabilities.\n */\n\n// Export main functions\nexport { embed, autoEmbed, getSupportedProviders, createProvider } from './main.js';\n\n// Export types\nexport type { \n EmbedConfig, \n EmbedInput, \n EmbedResult, \n BatchEmbedResult, \n ProviderType \n} from './src/types/index.js';\n\n// Export provider factory for advanced usage\nexport { EmbeddingFactory } from './src/factory/EmbeddingFactory.js';\n\n// Export base provider for custom implementations\nexport { EmbeddingProvider } from './src/providers/base/EmbeddingProvider.js';\n\n// Version information\nexport const VERSION = '1.0.0';\n\n/**\n * Get library version\n */\nexport function getVersion(): string {\n return VERSION;\n}\n\n/**\n * Library information\n */\nexport const LIB_INFO = {\n name: 'embedbox',\n version: VERSION,\n description: 'A minimal and powerful embedding library',\n homepage: 'https://embedbox.dev',\n repository: 'https://github.com/embedbox/embedbox.git',\n supportedProviders: [\n 'openai',\n 'gemini', \n 'claude',\n 'mistral',\n 'deepseek',\n 'llamacpp'\n ] as const\n} as const;\n"],"mappings":"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","names":["config","logger","logger","config","logger","config","logger","config","logger","config","logger","config","config","request","resolve","logger","config","logger","config"]}
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "vecbox",
3
+ "version": "0.1.0",
4
+ "description": "A minimal and powerful embedding library that supports multiple providers with automatic detection and fallback capabilities",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "src",
11
+ "README.md",
12
+ "CHANGELOG.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsup",
17
+ "dev": "tsx watch main.ts",
18
+ "test": "vitest",
19
+ "test:run": "vitest run",
20
+ "example": "tsx examples/basic-usage.ts",
21
+ "lint": "eslint . --ext .ts,.js",
22
+ "lint:fix": "eslint . --ext .ts,.js --fix",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "embeddings",
27
+ "vector",
28
+ "ai",
29
+ "machine-learning",
30
+ "openai",
31
+ "gemini",
32
+ "claude",
33
+ "mistral",
34
+ "deepseek",
35
+ "llamacpp",
36
+ "semantic-search",
37
+ "similarity",
38
+ "nlp",
39
+ "typescript"
40
+ ],
41
+ "author": {
42
+ "name": "Embedbox Team",
43
+ "email": "boxsafe.org@gmail.com",
44
+ "url": "https://boxsafe.org"
45
+ },
46
+ "license": "MIT",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "https://github.com/embedbox/embedbox.git"
50
+ },
51
+ "homepage": "https://embedbox.dev",
52
+ "bugs": {
53
+ "url": "https://github.com/embedbox/embedbox/issues"
54
+ },
55
+ "engines": {
56
+ "node": ">=16.0.0"
57
+ },
58
+ "packageManager": "pnpm@10.28.2",
59
+ "devDependencies": {
60
+ "@eslint/js": "^10.0.1",
61
+ "@types/node": "^25.2.3",
62
+ "eslint": "^10.0.0",
63
+ "globals": "^17.3.0",
64
+ "jiti": "^2.6.1",
65
+ "tsup": "^8.5.1",
66
+ "tsx": "^4.21.0",
67
+ "typescript": "^5.9.3",
68
+ "typescript-eslint": "^8.55.0",
69
+ "vitest": "^4.0.18"
70
+ },
71
+ "dependencies": {
72
+ "@anthropic-ai/sdk": "^0.74.0",
73
+ "@google/generative-ai": "^0.24.1",
74
+ "@mistralai/mistralai": "^1.14.0",
75
+ "deepseek": "^0.0.2",
76
+ "dotenv": "^17.3.1",
77
+ "openai": "^6.21.0"
78
+ }
79
+ }
@@ -0,0 +1,37 @@
1
+ import type { EmbedConfig, ProviderType } from '@src/types/index';
2
+ import { EmbeddingProvider } from '@providers/base/EmbeddingProvider';
3
+ import { OpenAIProvider } from '@providers/openai';
4
+ import { GeminiProvider } from '@providers/gemini';
5
+ import { ClaudeProvider } from '@providers/claude';
6
+ import { MistralProvider } from '@providers/mistral';
7
+ import { DeepSeekProvider } from '@providers/deepseek';
8
+ import { LlamaCppProvider } from '@providers/llamacpp';
9
+ import { Logger } from '@src/util/logger';
10
+
11
+ const logger = Logger.createModuleLogger('factory');
12
+
13
+ export class EmbeddingFactory {
14
+ private static providers = new Map<ProviderType, new (config: EmbedConfig) => EmbeddingProvider>([
15
+ ['openai', OpenAIProvider],
16
+ ['gemini', GeminiProvider],
17
+ ['claude', ClaudeProvider],
18
+ ['mistral', MistralProvider],
19
+ ['deepseek', DeepSeekProvider],
20
+ ['llamacpp', LlamaCppProvider], // Local embeddings with llama.cpp
21
+ ]);
22
+
23
+ static create(config: EmbedConfig) {
24
+ logger.info(`Creating provider: ${config.provider}`);
25
+
26
+ const ProviderClass = this.providers.get(config.provider);
27
+ if (!ProviderClass) {
28
+ throw new Error(`Unsupported provider: ${config.provider}`);
29
+ }
30
+
31
+ return new ProviderClass(config);
32
+ }
33
+
34
+ static getSupportedProviders(): ProviderType[] {
35
+ return Array.from(this.providers.keys());
36
+ }
37
+ }
Binary file
@@ -0,0 +1,32 @@
1
+ import type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';
2
+
3
+ export abstract class EmbeddingProvider {
4
+ protected config: EmbedConfig;
5
+
6
+ constructor(config: EmbedConfig) {
7
+ this.config = config;
8
+ }
9
+
10
+ abstract embed(input: EmbedInput): Promise<EmbedResult>;
11
+ abstract embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult>;
12
+ abstract getDimensions(): number;
13
+ abstract getProviderName(): string;
14
+ abstract isReady(): Promise<boolean>;
15
+
16
+ protected getModel(): string {
17
+ return this.config.model || 'default';
18
+ }
19
+
20
+ protected async readInput(input: EmbedInput): Promise<string> {
21
+ if (input.text) {
22
+ return input.text;
23
+ }
24
+
25
+ if (input.filePath) {
26
+ const fs = await import('fs/promises');
27
+ return await fs.readFile(input.filePath, 'utf-8');
28
+ }
29
+
30
+ throw new Error('Either text or filePath must be provided');
31
+ }
32
+ }
@@ -0,0 +1,78 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { EmbeddingProvider } from '@providers/base/EmbeddingProvider';
3
+ import type { EmbedConfig, EmbedResult, BatchEmbedResult } from '@src/types/index';
4
+ import { Logger } from '@src/util/logger';
5
+
6
+ const logger = Logger.createModuleLogger('claude');
7
+
8
+ export class ClaudeProvider extends EmbeddingProvider {
9
+ private client: Anthropic;
10
+
11
+ constructor(config: EmbedConfig) {
12
+ super(config);
13
+
14
+ if (!config.apiKey) {
15
+ throw new Error('Anthropic API key is required');
16
+ }
17
+
18
+ this.client = new Anthropic({
19
+ apiKey: config.apiKey,
20
+ baseURL: config.baseUrl,
21
+ timeout: config.timeout || 30000,
22
+ });
23
+
24
+ logger.info('Claude provider initialized');
25
+ }
26
+
27
+ async embed(): Promise<EmbedResult> {
28
+ try {
29
+ logger.debug(`Embedding text with model: ${this.getModel()}`);
30
+
31
+ // Note: Claude doesn't have native embeddings API yet
32
+ // This is a placeholder implementation
33
+ throw new Error('Claude embeddings API not yet available. Please use another provider.');
34
+
35
+ } catch (error: unknown) {
36
+ const errorMessage = error instanceof Error ? (error instanceof Error ? error.message : String(error)) : 'Unknown error';
37
+ logger.error(`Claude embedding failed: ${errorMessage}`);
38
+ throw error;
39
+ }
40
+ }
41
+
42
+ async embedBatch(): Promise<BatchEmbedResult> {
43
+ try {
44
+ // Note: Claude doesn't have native embeddings API yet
45
+ throw new Error('Claude embeddings API not yet available. Please use another provider.');
46
+
47
+ } catch (error: unknown) {
48
+ const errorMessage = error instanceof Error ? (error instanceof Error ? error.message : String(error)) : 'Unknown error';
49
+ logger.error(`Claude batch embedding failed: ${errorMessage}`);
50
+ throw error;
51
+ }
52
+ }
53
+
54
+ getDimensions(): number {
55
+ // Claude doesn't have embeddings yet
56
+ return 0;
57
+ }
58
+
59
+ getProviderName(): string {
60
+ return 'Anthropic Claude';
61
+ }
62
+
63
+ async isReady(): Promise<boolean> {
64
+ try {
65
+ // Test API access
66
+ await this.client.messages.create({
67
+ model: 'claude-3-haiku-20240307',
68
+ max_tokens: 10,
69
+ messages: [{ role: 'user', content: 'test' }]
70
+ });
71
+ return true;
72
+ } catch (error: unknown) {
73
+ const errorMessage = error instanceof Error ? (error instanceof Error ? error.message : String(error)) : 'Unknown error';
74
+ logger.error(`Claude readiness check failed: ${errorMessage}`);
75
+ return false;
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,115 @@
1
+ import { DeepSeek } from 'deepseek';
2
+ import { EmbeddingProvider } from '@providers/base/EmbeddingProvider';
3
+ import type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';
4
+ import { Logger } from '@src/util/logger';
5
+
6
+ const logger = Logger.createModuleLogger('deepseek');
7
+
8
+ export class DeepSeekProvider extends EmbeddingProvider {
9
+ private client: DeepSeek;
10
+
11
+ constructor(config: EmbedConfig) {
12
+ super(config);
13
+
14
+ if (!config.apiKey) {
15
+ throw new Error('DeepSeek API key is required');
16
+ }
17
+
18
+ const clientOptions: { apiKey: string; timeout: number; baseURL?: string } = {
19
+ apiKey: config.apiKey,
20
+ timeout: config.timeout || 30000,
21
+ };
22
+
23
+ if (config.baseUrl) {
24
+ clientOptions.baseURL = config.baseUrl;
25
+ }
26
+
27
+ this.client = new DeepSeek(clientOptions);
28
+
29
+ logger.info('DeepSeek provider initialized');
30
+ }
31
+
32
+ async embed(input: EmbedInput): Promise<EmbedResult> {
33
+ try {
34
+ const text = await this.readInput(input);
35
+ logger.debug(`Embedding text with model: ${this.getModel()}`);
36
+
37
+ const response = await this.client.embeddings.create({
38
+ model: this.getModel(),
39
+ input: text,
40
+ });
41
+
42
+ const embedding = response.data[0];
43
+ if (!embedding) {
44
+ throw new Error('No embedding returned from DeepSeek API');
45
+ }
46
+
47
+ return {
48
+ embedding: embedding.embedding || [],
49
+ dimensions: embedding.embedding?.length || 0,
50
+ model: embedding.model || this.getModel(),
51
+ provider: 'deepseek',
52
+ usage: response.usage ? {
53
+ promptTokens: response.usage.prompt_tokens,
54
+ totalTokens: response.usage.total_tokens,
55
+ } : undefined,
56
+ };
57
+ } catch (error: unknown) {
58
+ logger.error(`DeepSeek embedding failed: ${(error instanceof Error ? error.message : String(error))}`);
59
+ throw error;
60
+ }
61
+ }
62
+
63
+ async embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult> {
64
+ try {
65
+ const texts = await Promise.all(inputs.map(input => this.readInput(input)));
66
+ logger.debug(`Batch embedding ${texts.length} texts with model: ${this.getModel()}`);
67
+
68
+ const response = await this.client.embeddings.create({
69
+ model: this.getModel(),
70
+ input: texts,
71
+ });
72
+
73
+ const embeddings = response.data.map((item: { embedding: number[] }) => item.embedding);
74
+
75
+ return {
76
+ embeddings,
77
+ dimensions: embeddings[0]?.length || 0,
78
+ model: response.model,
79
+ provider: 'deepseek',
80
+ usage: response.usage ? {
81
+ promptTokens: response.usage.prompt_tokens,
82
+ totalTokens: response.usage.total_tokens,
83
+ } : undefined,
84
+ };
85
+ } catch (error: unknown) {
86
+ logger.error(`DeepSeek batch embedding failed: ${(error instanceof Error ? error.message : String(error))}`);
87
+ throw error;
88
+ }
89
+ }
90
+
91
+ getDimensions(): number {
92
+ // DeepSeek embedding dimensions
93
+ const model = this.getModel();
94
+ if (model.includes('deepseek-chat')) return 4096;
95
+ return 4096; // default for DeepSeek
96
+ }
97
+
98
+ getProviderName(): string {
99
+ return 'DeepSeek';
100
+ }
101
+
102
+ async isReady(): Promise<boolean> {
103
+ try {
104
+ // Test with a simple embedding request
105
+ await this.client.embeddings.create({
106
+ model: this.getModel(),
107
+ input: 'test',
108
+ });
109
+ return true;
110
+ } catch (error: unknown) {
111
+ logger.error(`DeepSeek readiness check failed: ${(error instanceof Error ? error.message : String(error))}`);
112
+ return false;
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,105 @@
1
+ import { GoogleGenerativeAI } from '@google/generative-ai';
2
+ import { EmbeddingProvider } from '@providers/base/EmbeddingProvider';
3
+ import type { EmbedConfig, EmbedInput, EmbedResult, BatchEmbedResult } from '@src/types/index';
4
+ import { Logger } from '@src/util/logger';
5
+
6
+ const logger = Logger.createModuleLogger('gemini');
7
+
8
+ export class GeminiProvider extends EmbeddingProvider {
9
+ private client: GoogleGenerativeAI;
10
+
11
+ constructor(config: EmbedConfig) {
12
+ super(config);
13
+
14
+ if (!config.apiKey) {
15
+ throw new Error('Google API key is required');
16
+ }
17
+
18
+ this.client = new GoogleGenerativeAI(config.apiKey);
19
+ logger.info('Gemini provider initialized');
20
+ }
21
+
22
+ async embed(input: EmbedInput): Promise<EmbedResult> {
23
+ try {
24
+ const text = await this.readInput(input);
25
+ logger.debug(`Embedding text with model: ${this.getModel()}`);
26
+
27
+ // Get the embedding model
28
+ const model = this.client.getGenerativeModel({
29
+ model: this.getModel()
30
+ });
31
+
32
+ // Use the embedding task
33
+ const result = await model.embedContent(text);
34
+ const embedding = result.embedding;
35
+
36
+ return {
37
+ embedding: embedding.values,
38
+ dimensions: embedding.values.length,
39
+ model: this.getModel(),
40
+ provider: 'gemini',
41
+ };
42
+ } catch (error: unknown) {
43
+ logger.error(`Gemini embedding failed: ${(error instanceof Error ? error.message : String(error))}`);
44
+ throw error;
45
+ }
46
+ }
47
+
48
+ async embedBatch(inputs: EmbedInput[]): Promise<BatchEmbedResult> {
49
+ try {
50
+ const texts = await Promise.all(inputs.map(input => this.readInput(input)));
51
+ logger.debug(`Batch embedding ${texts.length} texts with model: ${this.getModel()}`);
52
+
53
+ const model = this.client.getGenerativeModel({
54
+ model: this.getModel()
55
+ });
56
+
57
+ const results = await Promise.all(
58
+ texts.map(text => model.embedContent(text))
59
+ );
60
+
61
+ const embeddings = results.map((result: { embedding: { values: number[] } }) => result.embedding.values);
62
+
63
+ return {
64
+ embeddings,
65
+ dimensions: embeddings[0]?.length || 0,
66
+ model: this.getModel(),
67
+ provider: 'gemini',
68
+ };
69
+ } catch (error: unknown) {
70
+ logger.error(`Gemini batch embedding failed: ${(error instanceof Error ? error.message : String(error))}`);
71
+ throw error;
72
+ }
73
+ }
74
+
75
+ getDimensions(): number {
76
+ const model = this.getModel();
77
+ if (model.includes('gemini-embedding-001')) return 768;
78
+ if (model.includes('text-embedding-004')) return 768;
79
+ if (model.includes('embedding-001')) return 768;
80
+ if (model.includes('multimodalembedding')) return 768;
81
+ return 768; // default for Gemini embeddings
82
+ }
83
+
84
+ getProviderName(): string {
85
+ return 'Google Gemini';
86
+ }
87
+
88
+ protected getModel(): string {
89
+ return this.config.model || 'gemini-embedding-001';
90
+ }
91
+
92
+ async isReady(): Promise<boolean> {
93
+ try {
94
+ const model = this.client.getGenerativeModel({
95
+ model: this.getModel()
96
+ });
97
+ // Test with a simple embedding
98
+ await model.embedContent('test');
99
+ return true;
100
+ } catch (error: unknown) {
101
+ logger.error(`Gemini readiness check failed: ${(error instanceof Error ? error.message : String(error))}`);
102
+ return false;
103
+ }
104
+ }
105
+ }