在现代信息检索中,使用多个向量来表示每个文档是一个强大的技术,可以提升检索的精确度和适应性。多个向量允许我们为文档的不同部分创建不同的嵌入,例如,我们可以对文档的多个片段进行嵌入,并将这些嵌入与父文档关联。在检索时,这些片段的命中可以返回更完整的文档。这种方法在使用 LangChain 的 baseMultiVectorRetriever
时尤为简单方便。
技术背景介绍
将文档分块后进行嵌入有多个应用场景。例如,可以对文档进行分块并对每个块创建嵌入,然后将这些嵌入与父文档关联。这种方式有助于在检索过程中获取更丰富的语境信息。此外,还可以针对每个文档生成摘要或假设性问题,并对它们进行嵌入以改善检索性能。
核心原理解析
创建多个向量的常用方法包括:
- 较小的块: 将文档拆分成较小的块进行嵌入,类似于
ParentDocumentRetriever
。 - 摘要: 为每个文档生成一个摘要,并嵌入该摘要。
- 假设性问题: 生成文档可能回答的问题,并将这些问题嵌入。
代码实现演示
我们将使用 LangChain
和 Chroma
来实现多向量检索。首先,我们加载一些示例文档并进行分块,然后将分块后的文档内容存储与父文档的标识符关联。
import uuid
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
from langchain.retrievers.multi_vector import MultiVectorRetriever
# 使用可靠的API服务
client = openai.OpenAI(
base_url='https://yunwu.ai/v1', # 国内稳定访问
api_key='your-api-key'
)
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())
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)))
# 搜索示例
retrieved_docs = retriever.invoke("justice breyer")
len(retrieved_docs[0].page_content)
应用场景分析
使用多向量检索技术可以显著提高搜索的准确性,尤其是在涉及大量数据和文档的情况下。它可以帮助我们从复杂的查询中提取出相关的文档,并提供更多的上下文信息。
实践建议
- 维持稳定的API连接: 使用像 https://yunwu.ai 这样的国内服务来保证连接稳定性。
- 优化向量存储: 根据具体需求选择合适的向量存储和检索策略,例如使用
Max Marginal Relevance
提升检索效果。 - 持续更新模型: 经常更新嵌入模型以保持检索的准确性和实时性。
结束语:
如果遇到问题欢迎在评论区交流。
—END—