LangChain 向量数据库检索器实战:从基础检索到多查询优化全攻略
默认提示词可能不适合所有场景,我们可以自定义查询生成逻辑:python运行# 1. 定义输出解析器(将LLM结果拆分为查询列表)return list(filter(None, lines)) # 移除空行# 2. 自定义提示词模板template="""你是AI助手,任务是生成五个不同版本的用户查询,用于从向量数据库检索相关文档。通过生成多角度查询,帮助用户克服基于距离检索的局限性。原始问题:
在开发智能问答系统或文档检索应用时,我们常常会遇到这样的困境:传统的关键词检索无法捕捉语义关联,导致检索结果相关性低下。尤其是当数据规模增大时,如何高效准确地从海量文档中找到相关信息成为关键挑战。今天我们就来系统聊聊 LangChain 中向量数据库检索器的核心技术,从基础的相似性搜索到高级的多查询优化,帮你构建更智能的检索系统。
一、向量存储检索器基础:从向量数据库到检索接口的无缝转换
核心概念与工作原理
向量存储检索器是向量数据库的轻量级包装器,它将向量数据库的相似性搜索功能转换为统一的检索器接口。其核心原理是将文本转换为高维向量,通过计算向量间的距离(如余弦相似度)来衡量文本相关性,相比传统关键词匹配能更好地捕捉语义关系。
快速入门:从 FAISS 向量库创建检索器
python
运行
# 安装必要依赖
!pip install -qU langchain-openai faiss-cpu
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter
# 1. 加载文档
loader = TextLoader("state_of_the_union.txt")
documents = loader.load()
# 2. 拆分文档
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
# 3. 创建向量数据库
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(texts, embeddings)
# 4. 从向量数据库创建检索器
retriever = vectorstore.as_retriever()
# 5. 执行检索
query = "what did the president say about ketanji brown jackson?"
docs = retriever.invoke(query)
print(f"检索到{len(docs)}篇相关文档")
核心方法解析
- as_retriever():向量数据库的通用转换方法,返回
VectorStoreRetriever
实例 - invoke(query):执行检索并返回相关文档,默认使用相似性搜索
- 底层实现:封装了向量数据库的
similarity_search
方法,支持多种向量库(FAISS、Chroma 等)
二、高级检索策略:从相似性搜索到语义优化
1. 最大边际相关检索 (MMR)
MMR(Maximum Marginal Relevance)检索在相关性基础上增加多样性考虑,避免返回内容重复的文档:
python
运行
# 启用MMR检索
retriever = vectorstore.as_retriever(search_type="mmr")
# 执行检索(结果更具多样性)
docs = retriever.invoke("what did the president say about ketanji brown jackson?")
print("MMR检索结果:")
for doc in docs:
print(f"相关性得分:{doc.metadata.get('score', 'N/A')}")
print(f"内容片段:{doc.page_content[:100]}...\n")
2. 相似度阈值检索
通过设置得分阈值过滤低相关性文档,减少噪声干扰:
python
运行
# 设置相似度阈值为0.5
retriever = vectorstore.as_retriever(
search_type="similarity_score_threshold",
search_kwargs={"score_threshold": 0.5}
)
# 执行检索(仅返回高相关性文档)
docs = retriever.invoke("what did the president say about ketanji brown jackson?")
print(f"阈值检索结果:{len(docs)}篇有效文档")
3. 限制返回结果数量
通过k
参数控制返回文档数量,优化性能:
python
运行
# 仅返回最相关的1篇文档
retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
docs = retriever.invoke("what did the president say about ketanji brown jackson?")
print(f"Top-1检索结果:{docs[0].page_content[:200]}...")
三、MultiQueryRetriever:LLM 驱动的智能多查询优化
核心原理与优势
传统基于距离的检索容易受查询措辞影响,MultiQueryRetriever 通过 LLM 生成多个语义等价查询,从不同角度检索后合并结果,显著提升召回率:
- 问题:用户查询 "任务分解的方法"
- LLM 生成:"任务分解的不同实现方式有哪些?"、"常用的任务分解策略是什么?" 等多个查询
- 结果:合并多查询结果,获取更全面的相关文档
实战示例:构建智能检索系统
python
运行
# 安装依赖(若未安装)
!pip install -qU langchain-chroma
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.retrievers.multi_query import MultiQueryRetriever
# 1. 加载网络文档
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
data = loader.load()
# 2. 拆分文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
splits = text_splitter.split_documents(data)
# 3. 创建向量数据库
embedding = OpenAIEmbeddings()
vectordb = Chroma.from_documents(documents=splits, embedding=embedding)
# 4. 初始化LLM
llm = ChatOpenAI(temperature=0)
# 5. 创建MultiQueryRetriever(自动生成查询)
retriever_from_llm = MultiQueryRetriever.from_llm(
retriever=vectordb.as_retriever(),
llm=llm
)
# 6. 执行检索
question = "What are the approaches to Task Decomposition?"
unique_docs = retriever_from_llm.invoke(question)
print(f"多查询检索结果:{len(unique_docs)}篇文档")
自定义提示词优化
默认提示词可能不适合所有场景,我们可以自定义查询生成逻辑:
python
运行
from typing import List
from langchain_core.output_parsers import BaseOutputParser
from langchain_core.prompts import PromptTemplate
from pydantic import BaseModel, Field
# 1. 定义输出解析器(将LLM结果拆分为查询列表)
class LineListOutputParser(BaseOutputParser[List[str]]):
def parse(self, text: str) -> List[str]:
lines = text.strip().split("\n")
return list(filter(None, lines)) # 移除空行
output_parser = LineListOutputParser()
# 2. 自定义提示词模板
QUERY_PROMPT = PromptTemplate(
input_variables=["question"],
template="""你是AI助手,任务是生成五个不同版本的用户查询,用于从向量数据库检索相关文档。
通过生成多角度查询,帮助用户克服基于距离检索的局限性。
原始问题: {question}
请用换行分隔不同查询:""",
)
# 3. 构建LLM链
llm = ChatOpenAI(temperature=0)
llm_chain = QUERY_PROMPT | llm | output_parser
# 4. 初始化MultiQueryRetriever(使用自定义提示词)
retriever = MultiQueryRetriever(
retriever=vectordb.as_retriever(),
llm_chain=llm_chain,
parser_key="lines" # 解析输出的键名
)
# 5. 执行检索
unique_docs = retriever.invoke("What does the course say about regression?")
print("自定义提示词生成的查询:")
# 查看LLM生成的具体查询(日志中可查看)
四、实战优化策略与场景应用
性能优化组合拳
- 缓存策略:结合
CacheBackedEmbeddings
缓存嵌入结果,避免重复计算 - 批量处理:一次性检索多个查询,减少 API 调用次数
- 硬件加速:FAISS 支持 GPU 加速,Chroma 支持 SQLite 后端优化
典型应用场景
- 企业知识库问答:客服系统、内部培训资料检索
- 学术文献检索:多语言论文语义检索
- 代码库搜索:基于功能描述的代码片段检索
- 法律文档审查:案例与条款的智能匹配
五、总结与进阶方向
通过今天的实践,我们掌握了 LangChain 中向量数据库检索器的核心技术,从基础的相似性搜索到高级的多查询优化,这些技术能显著提升检索的准确性和召回率。在实际项目中,建议按照以下流程实施:
- 数据预处理:根据文档类型选择合适的拆分策略
- 向量库选型:FAISS 适合内存计算,Chroma 适合持久化存储
- 检索策略选择:从基础相似性搜索开始,逐步引入 MMR 和多查询优化
- 参数调优:通过阈值、k 值等参数平衡相关性和性能
如果本文对你有帮助,别忘了点赞收藏,关注我,一起探索更高效的开发方式~

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)