2026-06-06 20:12:40 +07:00
parent de84b2bf48
commit 97ac0f71f5
13682 changed files with 1125938 additions and 0 deletions
@@ -0,0 +1,98 @@
// utils/embedding.js - OpenAI Embedding API integration for tool similarity search
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY || ''
});
// In-memory cache for embeddings
const embeddingCache = new Map();
/**
* Get embedding vector for text using OpenAI API
* @param {string} text - Text to embed
* @returns {Promise<number[]>} - Embedding vector (1536 dimensions)
*/
export async function getEmbedding(text) {
if (!text || text.trim().length === 0) {
console.warn('[Embedding] Empty text provided, returning zero vector');
return new Array(1536).fill(0);
}
// Check cache first
const cacheKey = text.toLowerCase().trim();
if (embeddingCache.has(cacheKey)) {
return embeddingCache.get(cacheKey);
}
try {
if (!process.env.OPENAI_API_KEY) {
console.warn('[Embedding] No OpenAI API key, using zero vector fallback');
return new Array(1536).fill(0);
}
const response = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
});
const embedding = response.data[0].embedding;
// Cache the result
embeddingCache.set(cacheKey, embedding);
return embedding;
} catch (error) {
console.error('[Embedding] Error:', error.message);
// Fallback: return zero vector
return new Array(1536).fill(0);
}
}
/**
* Calculate cosine similarity between two vectors
* @param {number[]} vecA - First vector
* @param {number[]} vecB - Second vector
* @returns {number} - Similarity score (0-1)
*/
export function cosineSimilarity(vecA, vecB) {
if (!vecA || !vecB || vecA.length !== vecB.length) {
return 0;
}
let dotProduct = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < vecA.length; i++) {
dotProduct += vecA[i] * vecB[i];
normA += vecA[i] * vecA[i];
normB += vecB[i] * vecB[i];
}
const denominator = Math.sqrt(normA) * Math.sqrt(normB);
if (denominator === 0) {
return 0;
}
return dotProduct / denominator;
}
/**
* Clear embedding cache (useful for testing)
*/
export function clearCache() {
embeddingCache.clear();
}
/**
* Get cache statistics
*/
export function getCacheStats() {
return {
size: embeddingCache.size,
keys: Array.from(embeddingCache.keys())
};
}