如何合并多个检索器的结果
前提条件
本指南假设您已经熟悉以下概念:
EnsembleRetriever 支持合并多个检索器的结果。它通过一组 BaseRetriever 对象进行初始化。EnsembleRetriever 会根据 Reciprocal Rank Fusion 算法对各个子检索器的结果进行重新排序。
通过结合不同算法的优势,EnsembleRetriever 可以实现比单一算法更好的性能。
一个常见的有效模式是将关键词匹配检索器与稠密检索器(如基于嵌入向量的相似度检索)结合使用,因为它们的优势是互补的。这种组合可以被视为一种“混合搜索”。稀疏检索器擅长根据关键词查找相关文档,而稠密检索器则擅长根据语义相似性查找相关文档。
下面我们将演示如何将一个简单的自定义检索器(该检索器仅返回直接包含输入查询的文档)与一个基于内存中的向量存储的检索器进行集成。
import { EnsembleRetriever } from "langchain/retrievers/ensemble";
import { MemoryVectorStore } from "langchain/vectorstores/memory";
import { OpenAIEmbeddings } from "@langchain/openai";
import { BaseRetriever, BaseRetrieverInput } from "@langchain/core/retrievers";
import { Document } from "@langchain/core/documents";
class SimpleCustomRetriever extends BaseRetriever {
lc_namespace = [];
documents: Document[];
constructor(fields: { documents: Document[] } & BaseRetrieverInput) {
super(fields);
this.documents = fields.documents;
}
async _getRelevantDocuments(query: string): Promise<Document[]> {
return this.documents.filter((document) =>
document.pageContent.includes(query)
);
}
}
const docs1 = [
new Document({ pageContent: "I like apples", metadata: { source: 1 } }),
new Document({ pageContent: "I like oranges", metadata: { source: 1 } }),
new Document({
pageContent: "apples and oranges are fruits",
metadata: { source: 1 },
}),
];
const keywordRetriever = new SimpleCustomRetriever({ documents: docs1 });
const docs2 = [
new Document({ pageContent: "You like apples", metadata: { source: 2 } }),
new Document({ pageContent: "You like oranges", metadata: { source: 2 } }),
];
const vectorstore = await MemoryVectorStore.fromDocuments(
docs2,
new OpenAIEmbeddings()
);
const vectorstoreRetriever = vectorstore.asRetriever();
const retriever = new EnsembleRetriever({
retrievers: [vectorstoreRetriever, keywordRetriever],
weights: [0.5, 0.5],
});
const query = "apples";
const retrievedDocs = await retriever.invoke(query);
console.log(retrievedDocs);
/*
[
Document { pageContent: 'You like apples', metadata: { source: 2 } },
Document { pageContent: 'I like apples', metadata: { source: 1 } },
Document { pageContent: 'You like oranges', metadata: { source: 2 } },
Document {
pageContent: 'apples and oranges are fruits',
metadata: { source: 1 }
}
]
*/
API Reference:
- EnsembleRetriever from
langchain/retrievers/ensemble - MemoryVectorStore from
langchain/vectorstores/memory - OpenAIEmbeddings from
@langchain/openai - BaseRetriever from
@langchain/core/retrievers - BaseRetrieverInput from
@langchain/core/retrievers - Document from
@langchain/core/documents
下一步
现在您已经学会了如何合并多个检索器的结果。
接下来,您可以查看其他一些检索相关的指南,例如如何通过为每个文档使用多个嵌入向量来提升检索效果,
或者如何创建您自己的自定义检索器。