UNPKG

agentis

Version:

A TypeScript framework for building sophisticated multi-agent systems

212 lines (211 loc) 8.31 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnhancedMemoryClient = void 0; const SupabaseClient_1 = require("../utils/SupabaseClient"); const openai_1 = __importDefault(require("openai")); class EnhancedMemoryClient { constructor(dimension = 1536) { this.dimension = dimension; this.llmClient = new openai_1.default({ baseURL: 'https://api.openai.com/v1', apiKey: process.env.OPENAI_API_KEY, }); } async getMemory(agentId) { const { data, error } = await SupabaseClient_1.supabase .from('memory_entries') .select('*') .eq('agent_id', agentId) .order('created_at', { ascending: false }); if (error) { console.error("Error fetching memory:", error); return []; } return data || []; } async searchSimilar(agentId, embedding, limit = 5, threshold = 0.8) { const { data, error } = await SupabaseClient_1.supabase.rpc('match_memories', { query_embedding: embedding, match_threshold: threshold, match_count: limit, p_agent_id: agentId }); if (error) throw error; return data || []; } async createEmbedding(text) { try { const response = await this.llmClient.embeddings.create({ model: 'text-embedding-3-small', input: text, dimensions: this.dimension }); if (!response.data?.[0]?.embedding) { console.warn('Embedding API failed, using fallback vector'); return new Array(this.dimension).fill(0).map(() => Math.random()); } return response.data[0].embedding; } catch (error) { console.error('Error creating embedding:', error); if (error instanceof Error) { console.error('Error details:', { message: error.message, name: error.name, stack: error.stack }); } return new Array(this.dimension).fill(0).map(() => Math.random()); } } async saveMemory(agentId, input) { try { let entry; if (typeof input === 'string') { entry = { content: input, type: 'message', metadata: { timestamp: Date.now() } }; } else { entry = input; } const embedding = entry.embedding || await this.createEmbedding(entry.content); // Save to memory_entries const { error } = await SupabaseClient_1.supabase .from('memory_entries') .insert([{ agent_id: agentId, content: entry.content, type: entry.type, metadata: entry.metadata, embedding, created_at: new Date().toISOString() }]); if (error) { console.error("Error inserting into memory_entries:", error); throw error; } // Also save to messages table if it's a message if (entry.type === 'message') { const { error: msgError } = await SupabaseClient_1.supabase .from('messages') .insert([{ id: `msg-${Date.now()}`, sender_id: agentId, recipient_id: entry.metadata?.recipient_id || 'system', content: entry.content, timestamp: new Date().toISOString() }]); if (msgError) { console.error("Error saving message:", msgError); } } // Log if it's a task result or observation if (entry.type === 'task_result' || entry.type === 'observation') { const { error: logError } = await SupabaseClient_1.supabase .from('logs') .insert([{ agent_id: agentId, log_type: entry.type, details: { content: entry.content, ...entry.metadata }, created_at: new Date().toISOString() }]); if (logError) { console.error("Error saving log:", logError); } } } catch (error) { console.error("Error saving memory:", error); throw error; } } async searchMemories(agentId, query, options = {}) { const { limit = 5, threshold = 0.8, type } = options; try { const queryEmbedding = await this.createEmbedding(query); const { data, error } = await SupabaseClient_1.supabase.rpc('search_memories', { query_embedding: queryEmbedding, match_threshold: threshold, match_count: limit, p_agent_id: agentId, p_memory_type: type }); if (error) throw error; return data || []; } catch (error) { console.error("Error searching memories:", error); return []; } } async summarizeMemories(memories) { if (memories.length === 0) return "No relevant memories found."; try { const memoryTexts = memories.map(m => m.content).join('\n'); const response = await this.llmClient.chat.completions.create({ model: 'gpt-3.5-turbo', messages: [{ role: 'system', content: 'Summarize the following memories concisely:' }, { role: 'user', content: memoryTexts }] }); return response.choices[0]?.message?.content || "Failed to generate summary."; } catch (error) { console.error("Error summarizing memories:", error); return "Error generating summary."; } } calculateConfidence(memories) { if (memories.length === 0) return 0; // Simple confidence calculation based on number of memories and recency const maxMemories = 10; // Arbitrary max for scaling const quantityScore = Math.min(memories.length / maxMemories, 1); // Calculate recency score (higher for more recent memories) const now = Date.now(); const recencyScores = memories.map(m => { const age = now - new Date(m.created_at).getTime(); const maxAge = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds return Math.max(0, 1 - age / maxAge); }); const avgRecency = recencyScores.reduce((a, b) => a + b, 0) / recencyScores.length; // Combine scores (equal weighting) return (quantityScore + avgRecency) / 2; } async getContextWindow(agentId, query, options = {}) { const memories = await this.searchMemories(agentId, query, { limit: options.maxItems, threshold: options.relevanceThreshold }); // Filter by time window if specified const filteredMemories = options.timeWindow ? memories.filter(m => Date.now() - new Date(m.created_at).getTime() < (options.timeWindow ?? Infinity)) : memories; // Generate context summary const context = await this.summarizeMemories(filteredMemories); return { relevant: filteredMemories, context, confidence: this.calculateConfidence(filteredMemories) }; } } exports.EnhancedMemoryClient = EnhancedMemoryClient;