如何使用多向量检索器提升文档检索效果

老铁们,今天咱们聊聊如何用多向量检索器(MultiVectorRetriever)来提升文档检索效果。某些情况下,存储一个文档的多个向量可以带来很多好处,比如我们可以对文档的多个片段进行嵌入,并将这些嵌入与父文档关联,允许在子片段上的检索命中返回整个更大的文档。

LangChain提供了一个名为baseMultiVectorRetriever的实现,它简化了这个过程。事实上,很多复杂性都在于如何为每个文档创建多个向量。今天我们会聊到几种常见的方法来生成这些向量,并如何使用MultiVectorRetriever。

技术背景介绍

创建多个向量的方法包括:

  1. 较小的片段:将文档分割为较小的块,然后对这些块进行嵌入(这是ParentDocumentRetriever的一部分功能)。
  2. 摘要:为每个文档创建一个摘要,并对摘要进行嵌入(可以替代或补充原始文档)。
  3. 假设性问题:生成适用于每个文档的假设性问题,并对这些问题进行嵌入。

此外,你还可以手动添加需要嵌入的内容,比如特定问题或查询,这样可以更精准地控制检索结果。

原理深度解析

我们先从一个例子开始,初始化一些文档,然后将它们索引到一个内存中的Chroma向量存储中,使用OpenAI嵌入。实际上,任何LangChain支持的向量存储或嵌入模型都可以使用。

%pip install --upgrade --quiet langchain-chroma langchain langchain-openai > /dev/null

from langchain.storage import InMemoryByteStore
from langchain_chroma import Chroma
from langchain_community.document_loaders import TextLoader
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

loaders = [
    TextLoader("paul_graham_essay.txt"),
    TextLoader("state_of_the_union.txt"),
]
docs = []
for loader in loaders:
    docs.extend(loader.load())
text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000)
docs = text_splitter.split_documents(docs)

vectorstore = Chroma(
    collection_name="full_documents", embedding_function=OpenAIEmbeddings()
)

实战代码演示

我们使用较小的片段进行嵌入。这个过程类似于ParentDocumentRetriever的内部机制。这里我们展示了一些幕后操作。

import uuid

from langchain.retrievers.multi_vector import MultiVectorRetriever

store = InMemoryByteStore()
id_key = "doc_id"

retriever = MultiVectorRetriever(
    vectorstore=vectorstore,
    byte_store=store,
    id_key=id_key,
)

doc_ids = [str(uuid.uuid4()) for _ in docs]
child_text_splitter = RecursiveCharacterTextSplitter(chunk_size=400)

sub_docs = []
for i, doc in enumerate(docs):
    _id = doc_ids[i]
    _sub_docs = child_text_splitter.split_documents([doc])
    for _doc in _sub_docs:
        _doc.metadata[id_key] = _id
    sub_docs.extend(_sub_docs)

retriever.vectorstore.add_documents(sub_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))

优化建议分享

对于在实际应用中提高检索效果,建议你在检索时使用Max Marginal Relevance(最大边际相关性)方法,增强检索多样性。

from langchain.retrievers.multi_vector import SearchType

retriever.search_type = SearchType.mmr

补充说明和总结

同时,我们也可以为文档生成摘要并进行嵌入,这可以更准确地获取文档的主题。你甚至可以使用LLM生成假设性问题来提升检索的语义关联性。

说白了,通过多向量检索器,你大可以像做魔术一般灵活控制你的文档检索,实现更高效的信息获取。

今天的技术分享就到这里,希望对大家有帮助。开发过程中遇到问题也可以在评论区交流~

—END—

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值