UNPKG

@codai/cbd

Version:

Codai Better Database - High-Performance Vector Memory System with HPKV-inspired architecture and MCP server

146 lines 5.11 kB
/** * CBD Embedding Service * Supports multiple embedding models (OpenAI, local, custom) */ export class OpenAIEmbeddingModel { name = 'openai'; dimensions = 1536; apiKey; modelName; constructor(apiKey, modelName = 'text-embedding-ada-002') { this.apiKey = apiKey; this.modelName = modelName; } async generateEmbedding(text) { try { const response = await fetch('https://api.openai.com/v1/embeddings', { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ input: text, model: this.modelName }) }); if (!response.ok) { throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`); } const data = await response.json(); return new Float32Array(data.data[0].embedding); } catch (error) { throw new Error(`Failed to generate OpenAI embedding: ${error}`); } } async generateBatchEmbeddings(texts) { if (texts.length === 0) return []; try { const response = await fetch('https://api.openai.com/v1/embeddings', { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ input: texts, model: this.modelName }) }); if (!response.ok) { throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`); } const data = await response.json(); return data.data.map((item) => new Float32Array(item.embedding)); } catch (error) { throw new Error(`Failed to generate batch OpenAI embeddings: ${error}`); } } } export class LocalEmbeddingModel { name = 'local'; dimensions = 384; // Default for sentence-transformers/all-MiniLM-L6-v2 pipeline; modelName; initialized = false; constructor(modelName = 'Xenova/all-MiniLM-L6-v2') { this.modelName = modelName; } async initialize() { if (this.initialized) return; try { const { pipeline } = await import('@xenova/transformers'); this.pipeline = await pipeline('feature-extraction', this.modelName); this.initialized = true; console.log(`🤖 Initialized local embedding model: ${this.modelName}`); } catch (error) { throw new Error(`Failed to initialize local embedding model: ${error}`); } } async generateEmbedding(text) { if (!this.initialized) await this.initialize(); try { const output = await this.pipeline(text, { pooling: 'mean', normalize: true }); return new Float32Array(output.data); } catch (error) { throw new Error(`Failed to generate local embedding: ${error}`); } } async generateBatchEmbeddings(texts) { if (!this.initialized) await this.initialize(); if (texts.length === 0) return []; try { const results = await Promise.all(texts.map(text => this.generateEmbedding(text))); return results; } catch (error) { throw new Error(`Failed to generate batch local embeddings: ${error}`); } } } export class EmbeddingService { model; constructor(model) { this.model = model; } async generateEmbedding(text) { return this.model.generateEmbedding(text); } async generateBatchEmbeddings(texts) { return this.model.generateBatchEmbeddings(texts); } async generateConversationEmbedding(userRequest, assistantResponse) { // Combine user request and assistant response for conversation context const conversationText = `User: ${userRequest}\nAssistant: ${assistantResponse}`; return this.generateEmbedding(conversationText); } getDimensions() { return this.model.dimensions; } getModelName() { return this.model.name; } static createFromConfig(config) { switch (config.type) { case 'openai': if (!config.apiKey) { throw new Error('OpenAI API key required for OpenAI embedding model'); } return new EmbeddingService(new OpenAIEmbeddingModel(config.apiKey, config.modelName)); case 'local': return new EmbeddingService(new LocalEmbeddingModel(config.modelName)); default: throw new Error(`Unsupported embedding model type: ${config.type}`); } } } //# sourceMappingURL=EmbeddingService.js.map