retrieve和generate必须拆成两个独立步骤,因为rag需先锁定上下文再生成答案,混用会导致缓存失效、调试困难、输入不可控;retrieve只做结构化召回并校验,generate仅基于其输出严格引用生成。

为什么 retrieve 和 generate 必须拆成两个独立步骤
因为 RAG 不是“边搜边聊”,而是先锁定上下文再生成答案——混在一起会导致缓存失效、调试困难、模型输入不可控。比如你用 llm.generate() 直接喂入原始 query + 检索结果,一旦检索出错,根本分不清是 retrieve 漏了关键文档,还是 generate 被噪声干扰了。
实操建议:
立即学习“Python免费学习笔记(深入)”;
-
retrieve阶段只做向量相似度匹配或关键词召回,输出必须是带score和content的结构化列表(如[{"content": "...", "score": 0.82, "source": "doc_123"}]),不碰 LLM -
generate阶段只接收这个列表,拼成 prompt 后调用llm.invoke();严禁在retrieve里调llm做重排序或摘要 - 中间加一层
retriever.validate()校验:若 top-3 的score全低于0.35,直接返回“未找到相关信息”,别硬塞给 LLM
如何让 retrieve 不漏掉关键片段
常见错误是把整篇 PDF 当作一个 chunk 丢进向量库,结果 query 是“合同第 4.2 条违约金怎么算”,而 chunk 里混着 12 条条款,向量表示模糊,retrieve 直接跳过。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 切 chunk 时优先按语义边界:用
nltk.sent_tokenize或spacy分句,再合并成 200–400 字的段落,每段带原文位置标记(如"page: 7, para: 3") - 对法律/技术文档,额外跑一次规则提取:用正则识别“第 X 条”“附件 Y”“详见第 Z 节”,把这些锚点单独建索引,和向量库并行查询
- 避免用
text-embedding-ada-002处理中文长文本——它对中文 chunk 的区分度弱,text2vec-large-chinese或bge-m3实测召回率高 22%+
generate 阶段怎么防止幻觉和引用错乱
典型现象:LLM 把检索结果 A 的内容说成来自 B,或者编造没出现过的条款编号。这不是模型能力问题,是 prompt 设计和后处理缺失。
华锐行业电子商务系统2.0采用微软最新的.net3.5(c#)+mssql架构,代码进行全面重整及优化,清除冗余及垃圾代码,运行速度更快、郊率更高。全站生成静态、会员二级域名、竞价排名、企业会员有多套模板可供选择;在界面方面采用DIV+CSS进行设计,实现程序和界面分离,方便修改适合自己的个性界面,在用户体验方面,大量使用ajax技术,更加易用。程序特点:一、采用微软最新.net3.5+MSSQL
实操建议:
立即学习“Python免费学习笔记(深入)”;
- prompt 里明确约束格式:
"请严格基于以下【参考资料】回答,不得添加外部知识。每处结论必须标注来源,如‘根据【参考资料-2】第3段’" - 生成后强制校验:用
re.findall(r"【参考资料-(\d+)】", response)提取所有引用编号,检查是否全在输入的检索列表索引范围内(即0 ) - 禁用 temperature > 0.3——生成阶段不是要创意,是要准确复述+归纳;
top_p=0.9已足够应对多数歧义
Python 里怎么串起这两个模块又不耦合
很多人写成一个大函数,rag_pipeline(query) 里嵌套 vector_db.similarity_search() 和 llm.invoke(),结果换 Embedding 模型就得改全部逻辑。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 定义两个协议类:
RetrieverProtocol(必须有search(self, query: str) -> List[Dict])和GeneratorProtocol(必须有generate(self, context: List[Dict], query: str) -> str) - 用依赖注入传实例:
RAGPipeline(retriever=MyElasticSearchRetriever(), generator=MyChatGLMGenerator()),替换任意一环都不动另一环 - 加一层
cache_key = hash((query, tuple(sorted(retriever_kwargs.items())))),缓存retrieve结果——相同 query+参数组合绝不重复查库
最易被忽略的是检索结果的元数据一致性:如果 retrieve 返回的 content 字段在不同 retriever 实现里有的带换行有的不带,generate 的 prompt 拼接就会错位。务必在协议层强制约定字段名、类型和清洗规则。









