@jackhua/mini-langchain
Version:
A lightweight TypeScript implementation of LangChain with cost optimization features
92 lines • 3.38 kB
JavaScript
;
/**
* Base vector store interface and implementations
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.VectorStore = exports.VectorStoreSearchType = void 0;
/**
* Vector store search type
*/
var VectorStoreSearchType;
(function (VectorStoreSearchType) {
VectorStoreSearchType["SIMILARITY"] = "similarity";
VectorStoreSearchType["MMR"] = "mmr";
})(VectorStoreSearchType || (exports.VectorStoreSearchType = VectorStoreSearchType = {}));
/**
* Base vector store interface
*/
class VectorStore {
constructor(embeddings) {
this.embeddings = embeddings;
}
/**
* Max marginal relevance search
*/
async maxMarginalRelevanceSearch(query, options = {}) {
const { k = 4, fetchK = 20, lambda = 0.5, filter } = options;
// Embed query
const queryEmbedding = await this.embeddings.embedQuery(query);
// Fetch more candidates
const candidates = await this.similaritySearchVectorWithScore(queryEmbedding, fetchK, filter);
// MMR algorithm
const selected = new Set();
const selectedDocs = [];
while (selectedDocs.length < k && selected.size < candidates.length) {
let bestScore = -Infinity;
let bestIdx = -1;
for (let i = 0; i < candidates.length; i++) {
if (selected.has(i))
continue;
const [doc, simScore] = candidates[i];
// Calculate diversity score
let diversityScore = Infinity;
for (const selectedIdx of selected) {
const [selectedDoc] = candidates[selectedIdx];
const diversity = this.calculateDiversity(doc, selectedDoc);
diversityScore = Math.min(diversityScore, diversity);
}
// MMR score
const mmrScore = lambda * simScore - (1 - lambda) * (1 - diversityScore);
if (mmrScore > bestScore) {
bestScore = mmrScore;
bestIdx = i;
}
}
if (bestIdx !== -1) {
selected.add(bestIdx);
selectedDocs.push(candidates[bestIdx][0]);
}
else {
break;
}
}
return selectedDocs;
}
/**
* Calculate diversity between two documents
*/
calculateDiversity(doc1, doc2) {
// Simple text-based diversity (can be overridden)
const text1 = doc1.pageContent.toLowerCase();
const text2 = doc2.pageContent.toLowerCase();
const words1 = new Set(text1.split(/\s+/));
const words2 = new Set(text2.split(/\s+/));
const intersection = new Set([...words1].filter(x => words2.has(x)));
const union = new Set([...words1, ...words2]);
return intersection.size / union.size;
}
/**
* Create vector store from texts
*/
static async fromTexts(texts, metadatas, embeddings, dbConfig) {
throw new Error('fromTexts must be implemented by subclass');
}
/**
* Create vector store from documents
*/
static async fromDocuments(docs, embeddings, dbConfig) {
throw new Error('fromDocuments must be implemented by subclass');
}
}
exports.VectorStore = VectorStore;
//# sourceMappingURL=base.js.map