文章目录
- **一、基础流程实现**
- 1. **全自动索引构建(VectorstoreIndexCreator)**
- 2. **标准问答链(RetrievalQA)**
- 3. **Document Chain + 手动检索**
- 4. **load_qa_chain(传统方式)**
- **二、高级定制化实现**
- 1. **自定义提示工程**(RetrievalQA)
- 2. **混合检索策略**
- **三、性能优化实现**
- 1. **重排序(Re-ranking)**
- 2. **上下文压缩(Context Compression)**
- **四、扩展功能实现**
- 1. **多模态 RAG**
- 2. **多步检索(Multi-hop Retrieval)**
- **五、生产级实现(基于 LCEL)**
- 1. **链式组合(LCEL Pipeline)**
- **总结对比**
以下是 LangChain 中主流的 RAG 实现方式及其核心原理、应用场景和代码示例,综合多篇技术文档的实践经验整理而成:
一、基础流程实现
1. 全自动索引构建(VectorstoreIndexCreator)
原理:封装文档加载→分块→向量化→存储→检索全流程,适合快速原型开发。通过指定向量
存储类型(如 FAISS)和嵌入模型,自动完成索引构建。
特点:自动处理文本分块和向量索引,但灵活性较低
代码示例:
from langchain.indexes import VectorstoreIndexCreator
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISSindex_creator = VectorstoreIndexCreator(vectorstore_cls=FAISS,embedding=OpenAIEmbeddings() # 需提前配置
)
loader = WebBaseLoader("https://example.com")
index = index_creator.from_loaders([loader]) # 自动完成分块+索引
result = index.query("文章主题是什么?", llm=ChatOpenAI()) # 需显式传入LLM
2. 标准问答链(RetrievalQA)
原理:基于内置模板实现检索增强生成,支持stuff
(文档拼接)、map_reduce
(分块处理)等链类型。
优化点:通过search_kwargs
控制检索数量和质量(如过滤低分文档)。
代码示例:
内置默认模板:
LangChain 的 RetrievalQA
默认使用以下隐式模板(未显式声明时自动应用):
template = """Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.{context}Question: {question}
Helpful Answer:"""
特点:
- 仅包含
{context}
和{question}
两个占位符 - 无语言或格式约束,依赖 LLM 的通用生成能力
- 未明确处理文档来源或回答规范(易产生幻觉)
示例(修改prompt):
from langchain_core.prompts import PromptTemplate
# 修改默认template
template = """你是一个专业的知识库助手。根据以下检索到的文档内容回答问题:
{context}问题:{question}
回答要求:
1. 用中文简洁回答,引用来源编号(如[来源1])
2. 若文档不相关,回答“知识库中无相关信息”
3. 禁止编造未提及的内容"""QA_PROMPT = PromptTemplate(template=template, input_variables=["context", "question"]
)
from langchain.chains import RetrievalQA
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI, OpenAIEmbeddings# 初始化组件
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.load_local("db", embeddings)
llm = ChatOpenAI(model="gpt-4", temperature=0.2)# 构建问答链
qa_chain = RetrievalQA.from_chain_type(llm=llm,chain_type="stuff",retriever=vectorstore.as_retriever(search_kwargs={"k": 3, "score_threshold": 0.7} #注意score_threshold的设置可能会过滤所有文档,应该进行测试以确定是否用该参数。),chain_type_kwargs={"prompt": QA_PROMPT}, # 注入自定义模板return_source_documents=True # 必须启用以显示来源
)# 提问与回答示例
question = "如何优化RAG系统的检索精度?"
result = qa_chain.invoke({"query": question})# 解析结果
print(f"问题:{question}")
print(f"回答:{result['result']}\n")print("=== 参考来源 ===")
for i, doc in enumerate(result['source_documents'][:3], 1):print(f"[来源{i}] 文件:{doc.metadata.get('source', '未知')}")print(f"内容片段:{doc.page_content[:150]}...\n")
3. Document Chain + 手动检索
原理:分离检索与生成步骤,适合需要预处理文档的场景
优势:可手动过滤/排序检索结果
from langchain.chains.combine_documents import create_stuff_documents_chaindocument_chain = create_stuff_documents_chain(llm=ChatOpenAI(),prompt=prompt # 需提前定义
)
docs = vectorstore.similarity_search("问题", k=4, filter={"source": "权威.pdf"})
answer = document_chain.invoke({"input": "问题","context": [d.page_content for d in docs] # 可手动处理文档
})
4. load_qa_chain(传统方式)
原理:直接传入文档列表,适合小规模数据
注意:文档需预先处理好分块 ,该方法的result是字符串,没有metadata信息。
from langchain.chains.question_answering import load_qa_chainchain = load_qa_chain(llm=ChatOpenAI(),chain_type="map_reduce" # 支持stuff/map_reduce/refine
)
result = chain.run(input_documents=chunks, # 需自行加载文档question="核心观点是什么?"
)
二、高级定制化实现
1. 自定义提示工程(RetrievalQA)
原理:通过设计模板控制生成风格,强制 LLM 基于上下文回答,减少幻觉。
关键:模板需包含{context}
和{question}
变量,支持中文指令约束。
优化点:
- 引用标注:强制显示来源文档编号(需配合
return_source_documents=True
) - 语言约束:限定中文回答(适配中文知识库)
- 防幻觉指令:明确禁止编造答案(降低错误率)
代码示例:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
import os# 配置OpenAI API(需提前设置环境变量)
os.environ["OPENAI_API_KEY"] = "sk-xxx" # 替换为您的API密钥# 初始化组件(假设vectorstore已提前创建)
vectorstore = ... # 您的向量存储实例# 创建自定义提示模板
template = """基于以下上下文(请严格依据给出内容):
{context}问题:{question}
回答要求:
1. 用中文回答,保持专业严谨
2. 每个观点标注来源编号(如[1])
3. 若上下文不相关,回答「该问题不在知识库范围内」"""
prompt = ChatPromptTemplate.from_template(template)# 构建问答链
qa_chain = RetrievalQA.from_chain_type(llm=ChatOpenAI(temperature=0.3, model="gpt-4-turbo"), # 控制生成稳定性chain_type="stuff",chain_type_kwargs={"prompt": prompt},retriever=vectorstore.as_retriever(search_kwargs={"k": 5, "score_threshold": 0.65} # #注意score_threshold的设置可能会过滤所有文档,应该进行测试以确定是否用该参数。),return_source_documents=True
)# ------------------- 提问与获取答案 ------------------- #
def ask_question(question: str):try:# 执行问答result = qa_chain.invoke({"query": question})# 解析结果print(f"\n=== 问题 ===\n{question}")print(f"\n=== 回答 ===\n{result['result']}")# 显示参考来源(前3个)print("\n=== 参考来源 ===")for i, doc in enumerate(result['source_documents'][:3], 1):print(f"[来源{i}] {doc.metadata.get('source', '未知文件')}")print(f"内容片段: {doc.page_content[:150]}...\n")except Exception as e:print(f"请求失败: {str(e)}")# 示例提问
if __name__ == "__main__":questions = ["LangChain的核心组件有哪些?", # 知识库相关问题"如何实现混合检索策略?", # 技术细节问题"2024年世界杯冠军是谁?" # 知识库范围外问题]for q in questions:ask_question(q)print("="*60)
2. 混合检索策略
原理:结合语义搜索(向量相似度)与关键词检索(BM25),提升召回率。
适用场景:处理专业术语或模糊查询时,兼顾语义和字面匹配。
代码示例:
from langchain.retrievers import BM25Retriever, EnsembleRetriever# 初始化混合检索器
bm25_retriever = BM25Retriever.from_documents(docs)
vector_retriever = vectorstore.as_retriever()
hybrid_retriever = EnsembleRetriever(retrievers=[bm25_retriever, vector_retriever],weights=[0.3, 0.7]
)
三、性能优化实现
1. 重排序(Re-ranking)
原理:对初筛结果用交叉编码器(如 Cohere Rerank)重新排序,提升精准度。
代码示例:
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CohereRerankcompressor = CohereRerank(cohere_api_key="YOUR_KEY", top_n=5)
compression_retriever = ContextualCompressionRetriever(base_retriever=vectorstore.as_retriever(search_kwargs={"k": 20}),base_compressor=compressor
)
2. 上下文压缩(Context Compression)
原理:提取检索文档中的关键片段,减少无关信息输入。
实现方式:
- 抽取式:用 LLM 提取与问题相关的句子
- 摘要式:生成文档摘要后检索
代码示例:
from langchain.chains import LLMChainExtractorextractor = LLMChainExtractor.from_llm(ChatOpenAI())
compression_retriever = ContextualCompressionRetriever(base_retriever=vectorstore.as_retriever(),base_compressor=extractor
)
四、扩展功能实现
1. 多模态 RAG
原理:支持图片、表格等非文本数据,需结合 OCR(如 Tesseract)和专用解析器(如 DeepDoc)。
代码示例:
# 图片处理流程示例
from langchain.document_loaders import UnstructuredImageLoader
from paddleocr import PaddleOCRloader = UnstructuredImageLoader("report.png", ocr_tool=PaddleOCR())
documents = loader.load()
2. 多步检索(Multi-hop Retrieval)
原理:通过迭代检索优化结果,例如先检索大纲再定位细节。
代码示例:
from langchain.agents import AgentExecutor, Toolretriever_tool = Tool(name="DocumentRetriever",func=vectorstore.as_retriever().invoke,description="检索技术文档"
)
agent = initialize_agent([retriever_tool], llm, agent="conversational")
result = agent.run("某功能的使用场景是什么?请分步骤说明。")
五、生产级实现(基于 LCEL)
1. 链式组合(LCEL Pipeline)
原理:利用 LangChain 表达式语言构建可扩展的流式处理管道,支持批处理和异步。
代码示例:
from langchain_core.runnables import RunnablePassthroughrag_chain = ({"context": retriever | format_docs, "question": RunnablePassthrough()}| prompt| llm| StrOutputParser()
)# 流式输出
for chunk in rag_chain.stream("最新技术趋势是什么?"):print(chunk, end="")
总结对比
实现方式 | 核心优势 | 适用场景 | 复杂度 |
---|---|---|---|
全自动索引 | 快速原型开发 | 技术验证、小规模数据 | 低 |
自定义Prompt | 控制生成风格 | 专业领域问答(法律、医疗) | 中 |
混合检索 | 提升召回率 | 模糊查询、多义词处理 | 高 |
LCEL 管道 | 支持流式/批处理 | 高并发生产环境 | 最高 |
建议选择路径:
- 快速验证 → VectorstoreIndexCreator 或 RetrievalQA
- 专业问答 → 自定义提示 + 重排序
- 生产部署 → LCEL 管道 + 混合检索
更多细节可参考 LangChain 官方文档及实践案例。