免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Retriever Chain in LangChain 完整深度解读

Retriever  Chain in LangChain 完整深度解读 Retriever Chain in LangChain 完整深度解读适配 LangChain 0.1 新版 API区分 legacyRetrievalQA与现代 LCEL 写法 核心定位RAG 的两大基础组件 ——Retriever检索器负责找文档Chain链路负责把检索结果 问题喂给大模型生成答案一、基础概念划分1. Retriever 检索器接口基类BaseRetriever职责接收字符串 query → 返回相关文档列表List[Document]python运行class BaseRetriever: def get_relevant_documents(self, query: str) - List[Document]: ... async def aget_relevant_documents(self, query: str) - List[Document]: ...常见实现VectorStoreRetriever最常用向量数据库包装器相似度检索FAISS/Chroma/PineconeMultiQueryRetriever扩写多条 query 做多路检索召回ParentDocumentRetriever小块检索、返回大块原文SelfQueryRetriever让 LLM 解析过滤条件带元数据筛选EnsembleRetriever多路检索结果融合BM25 向量混合检索ContextCompressionRetriever检索后压缩无用片段关键点Retriever只负责召回文档不调用 LLM不生成答案。2. Chain链路LangChain Chain 本质可执行的调用单元输入字典 → 输出字典旧版Chain基类 新版推荐LCEL — LangChain Expression Language|管道语法所有组件Prompt、LLM、Retriever、Parser统一实现Runnable接口。RAG 核心目标plaintext用户问题 → Retriever召回文档 → 组装Prompt(问题上下文) → LLM生成回答二、经典两种实现方案对比方案 A遗留风格 — RetrievalQA Chain不推荐新项目python运行from langchain.chains import RetrievalQA qa_chain RetrievalQA.from_chain_type( llmllm, chain_typestuff, # 四种文档拼接策略重点 retrievervectorstore.as_retriever(), return_source_documentsTrue )chain_type 四种模式核心考点stuff塞满模式所有检索文档一次性全部塞进 Prompt ✅ 简单、只调用一次 LLM ❌ 上下文窗口有限文档多时触发超限map_reducemap每份文档单独调用 LLM 摘要 reduce把所有摘要汇总再生成最终答案 ✅ 支持超长文档集合 ❌ LLM 调用量大成本高、速度慢map_rerank每份文档独立打分挑选最高分文档生成答案 适合 “只有一份文档包含答案” 场景refine先拿第一篇文档生成答案再依次传入剩余文档迭代优化答案 ✅ 上下文连续性好 ❌ 串行执行速度极慢⚠️ LangChain 官方建议新项目不要用RetrievalQA优先 LCEL。方案 B现代标准 — LCEL RAG Chain【生产首选】标准管道公式plaintext{question} | retriever # 输出 List[Document] | (把文档question灌入prompt模板) | llm | output_parser完整可运行最简模板python运行from langchain.vectorstores import Chroma from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough # 1. 初始化向量库 Retriever vectorstore Chroma.from_texts(..., embeddingOpenAIEmbeddings()) retriever vectorstore.as_retriever(search_kwargs{k: 4}) # 2. Prompt prompt ChatPromptTemplate.from_template( 基于下面上下文回答问题如果找不到答案如实说不知道。 上下文 {context} 问题{question} ) llm ChatOpenAI(modelgpt-3.5-turbo) # 工具函数Document列表拼接成字符串 def format_docs(docs): return \n\n.join(doc.page_content for doc in docs) # 3. LCEL 组装RAG链 rag_chain ( {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | llm | StrOutputParser() ) # 调用 resp rag_chain.invoke(你的问题) print(resp)管道拆解解释{context: retriever | format_docs, question: RunnablePassthrough()}输入字符串 questionquestion直接透传给 prompt 变量question 送入 retriever 拿到文档列表 → format_docs 转为文本上下文字典传入 prompt 模板填充变量送入 LLMStrOutputParser 把 AI 消息转为纯文本优势高度透明每一步可单独调试支持流式.stream()、异步.ainvoke()易于插入中间日志、缓存、重试、过滤器方便改造添加重排序、查询改写、自我检查三、Retriever 进阶核心机制1.search_kwargs参数VectorStoreRetrieverpython运行retriever vectorstore.as_retriever( search_typesimilarity, # 相似度检索 # search_typemmr, # MMR最大边际相关性去冗余 # search_typesimilarity_score_threshold # 阈值过滤 search_kwargs{ k: 4, # 返回top-k文档 score_threshold: 0.6, # 相似度阈值 filter: {source: doc1.pdf} # 元数据过滤 } )similarity单纯距离排序默认MMR召回同时保证相关性 多样性减少重复片段阈值检索低于阈值直接丢弃减少噪声2. 高级 Retriever 组合实战(1) MultiQueryRetriever 查询改写利用 LLM 把原始问题生成多条不同表述 query多路检索提升召回覆盖面python运行from langchain.retrievers.multi_query import MultiQueryRetriever mq_retriever MultiQueryRetriever.from_llm(retrieverbase_retriever, llmllm)(2) ContextCompressionRetriever 上下文压缩检索到文档后用 LLM 过滤掉无关段落减少 Prompt 占用 tokenpython运行from langchain.retrievers import ContextualCompressionRetriever from langchain.retrievers.document_compressors import LLMChainExtractor compressor LLMChainExtractor.from_llm(llm) compress_retriever ContextualCompressionRetriever(base_retrieverretriever, base_compressorcompressor)(3) EnsembleRetriever 混合检索向量 BM25稀疏检索 (BM25) 稠密向量检索融合大幅提升冷召回效果工业界标配python运行from langchain.retrievers import EnsembleRetriever ensemble_retriever EnsembleRetriever( retrievers[bm25_retriever, vector_retriever], weights[0.5, 0.5] )四、RAG 常见扩展 Chain 链路LCEL 扩展1. 带源文档返回LCEL 原生不像 RetrievalQA 自动返回 source_docs需要手动封装python运行from langchain_core.runnables import RunnableParallel rag_chain_with_source RunnableParallel( {context: retriever, question: RunnablePassthrough()} ).assign( answer (lambda x: {context: format_docs(x[context]), question: x[question]}) | prompt | llm | StrOutputParser() ) out rag_chain_with_source.invoke(问题) # out[context] → List[Document] # out[answer] → 回答文本2. 自校验 RAGSelf-RAG 思路简化版链路检索 → 判断文档是否相关 → 不相关则重新检索 / 直接拒绝回答3. 路由 Retriever多个知识库分流plaintext用户问题 → LLM路由判断属于哪个知识库 → 调用对应Retriever五、关键误区澄清❌ 混淆 Retriever ≠ VectorStore VectorStore存储 向量相似度计算 Retriever封装 VectorStore统一的检索接口一个 VectorStore 可以实例多个不同参数 Retriever❌ RetrievalQA RAG 标准实现 ✅ RetrievalQA 只是早期封装灵活性差LCEL 是官方现代标准❌ retriever 直接接收结构化对象 ✅ BaseRetriever 输入永远是字符串 query不能直接传复杂对象❌ stuff 模式能无限塞文档 ✅ 超出模型上下文窗口会报错 / 截断必须配合文档压缩、map_reduce 或者切分优化六、完整数据流全景图plaintextUser Query(str) ↓ 【Runnable字典分发】 ├─ question → 直接透传 └─ query → Retriever向量库/BM25等 ↓ List[Document] → format_docs → 上下文文本 ↓ PromptTemplate填充 {context} {question} ↓ ChatLLM ↓ OutputParser → 最终答案七、调试手段开发必备单独测试 Retriever先确认召回文档质量python运行docs retriever.get_relevant_documents(测试问题) for d in docs: print(d.page_content, d.metadata)RAG 效果差 70% 问题出在检索召回而不是 LLM 生成打印送入 LLM 完整 Prompt排查是否拼接错误使用.bind()设置温度、流式输出python运行rag_chain.stream(问题)八、生产优化方向调整k、MMR、相似度阈值平衡召回数量与噪声接入重排序器CrossEncoderReranker检索后精排增加查询改写、拼写纠错增加缓存相同 query 避免重复向量检索增加文档去重、长度过滤
返回列表