UNPKG

@jackhua/mini-langchain

Version:

A lightweight TypeScript implementation of LangChain with cost optimization features

179 lines 5.28 kB
"use strict"; /** * In-memory vector store implementation */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MemoryVectorStore = void 0; const uuid_1 = require("uuid"); const base_1 = require("./base"); /** * Simple in-memory vector store */ class MemoryVectorStore extends base_1.VectorStore { constructor(embeddings) { super(embeddings); this.vectors = new Map(); this.documents = new Map(); } /** * Add documents to the vector store */ async addDocuments(documents) { const texts = documents.map(doc => doc.pageContent); const embeddings = await this.embeddings.embedDocuments(texts); return this.addVectors(embeddings, documents); } /** * Add vectors directly */ async addVectors(vectors, documents) { const ids = []; for (let i = 0; i < vectors.length; i++) { const id = (0, uuid_1.v4)(); const vector = { id, values: vectors[i], metadata: documents[i].metadata }; this.vectors.set(id, vector); this.documents.set(id, documents[i]); ids.push(id); } return ids; } /** * Similarity search */ async similaritySearch(query, k = 4, filter) { const results = await this.similaritySearchWithScore(query, k, filter); return results.map(([doc]) => doc); } /** * Similarity search with score */ async similaritySearchWithScore(query, k = 4, filter) { const queryEmbedding = await this.embeddings.embedQuery(query); return this.similaritySearchVectorWithScore(queryEmbedding, k, filter); } /** * Similarity search by vector */ async similaritySearchVectorWithScore(query, k, filter) { const scores = []; // Calculate similarity scores for (const [id, vector] of this.vectors.entries()) { const doc = this.documents.get(id); // Apply filter if provided if (filter && !this.matchesFilter(doc.metadata || {}, filter)) { continue; } const similarity = this.cosineSimilarity(query, vector.values); scores.push([id, similarity]); } // Sort by similarity (descending) scores.sort((a, b) => b[1] - a[1]); // Return top k results return scores.slice(0, k).map(([id, score]) => { const doc = this.documents.get(id); return [doc, score]; }); } /** * Delete documents */ async delete(params) { if (!params) { // Clear all this.vectors.clear(); this.documents.clear(); return; } const { ids, filter } = params; if (ids) { // Delete by IDs for (const id of ids) { this.vectors.delete(id); this.documents.delete(id); } } if (filter) { // Delete by filter const toDelete = []; for (const [id, doc] of this.documents.entries()) { if (this.matchesFilter(doc.metadata || {}, filter)) { toDelete.push(id); } } for (const id of toDelete) { this.vectors.delete(id); this.documents.delete(id); } } } /** * Calculate cosine similarity between two vectors */ cosineSimilarity(a, b) { let dotProduct = 0; let normA = 0; let normB = 0; for (let i = 0; i < a.length; i++) { dotProduct += a[i] * b[i]; normA += a[i] * a[i]; normB += b[i] * b[i]; } normA = Math.sqrt(normA); normB = Math.sqrt(normB); if (normA === 0 || normB === 0) { return 0; } return dotProduct / (normA * normB); } /** * Check if metadata matches filter */ matchesFilter(metadata, filter) { for (const [key, value] of Object.entries(filter)) { if (metadata[key] !== value) { return false; } } return true; } /** * Create from texts */ static async fromTexts(texts, metadatas, embeddings) { const docs = []; for (let i = 0; i < texts.length; i++) { const metadata = Array.isArray(metadatas) ? metadatas[i] : metadatas; docs.push({ pageContent: texts[i], metadata: metadata || {} }); } return MemoryVectorStore.fromDocuments(docs, embeddings); } /** * Create from documents */ static async fromDocuments(docs, embeddings) { const store = new MemoryVectorStore(embeddings); await store.addDocuments(docs); return store; } /** * Get all documents */ getAllDocuments() { return Array.from(this.documents.values()); } /** * Get document count */ getDocumentCount() { return this.documents.size; } } exports.MemoryVectorStore = MemoryVectorStore; //# sourceMappingURL=memory.js.map