ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RAG生产级落地:从固定流水线到六处关键分水岭的工程化实践

RAG生产级落地:从固定流水线到六处关键分水岭的工程化实践 做一个项目做久了你会发现一个特别有意思的现象每次技术社区一聊 RAG底下全是“烂大街了”“早就会了”的声音。但你再追问一句“你线上召回准确率多少、忠实度多少、多轮检索怎么解决冲突”十个人里有八个开始含糊其辞。我做了三年知识库 RAG从二十页的说明书到几千份的运维手册都折腾过越来越确定一件事烂大街的确实只是那条流水线——装个向量库、调个 embedding 接口、把文档切一切塞进去然后检索、拼接、生成三行代码就能跑通。但真正能把 RAG 做到生产可用、回答准确率稳定在高位的人掰着手指头数得过来。因为流水线只是入口真正的分水岭在这六处切分、召回、知识组织、智能编排、冲突消解和评估体系。这篇文章不聊 API 怎么调也不贴那种“30 分钟搭建知识库”的保姆教程我只想把这六处分水岭掰开揉碎讲清楚。无论你是底层用 LangChain 自己拼还是用 Dify、LangChain4j 这类框架搭这些坑一个都绕不过去。1. 先聊聊“烂大街”这个错觉从哪来的1.1 三行代码就能跑通的那个 RAG 长什么样很多人对 RAG 的认知来自一个非常标准的 demo把 PDF 按固定字数切成几百个 chunk调 embedding 接口把所有 chunk 转成向量灌进向量数据库用户提问的时候把问题也转成向量用余弦相似度召回 top_k拼进 prompt 扔给 LLM。这套流程用人话讲就是“先翻书找到候选段落再让大模型照着候选段落答题”。不管是 Python 脚本、LangChain还是 Dify、FastGPT底层都是这一套。这套东西跑通确实快半小时都不用。但问题也恰恰藏在“快”里。我见过太多项目停在这个阶段就号称“知识库上线了”结果领导一问“为什么这么简单的问题都答不对”整个团队就开始互相看。原因倒不复杂固定窗口切分把语义切碎了单路向量检索召不回精确内容上下文里塞了一堆无关片段LLM 又被这些片段带偏。每一步单看都“能跑”连起来就“跑不动”。1.2 流水线思维的两大致命伤第一个致命伤是把所有问题都映射成“向量检索 - 拼接 - 生成”这一个套路。实际上 RAG 的真实世界长满了例外有的查询是精确匹配“这个接口的报错码是多少”向量检索反而打不过关键词检索有的查询要跨章节综合“对比 A 和 B 两块模块的权限差异”单次检索压根凑不齐信息有的查询有时间属性“最新的版本是什么”不考虑时效就会把旧文档捞出来。固定流水线对这些场景几乎毫无还手之力。第二个致命伤是只关心流程“通不通”不关心质量“行不行”。很多人跑通 demo 之后唯一的验证方式是自己问两三个看得到的问题或者看一下 top_k 有没有把答案捞回来也就是所谓的 hit rate然后就收工了。但线上真实的用户问题千奇百怪没有一套评估指标和测试集你连“改了一版切分之后到底变好还是变差”都说不清楚更别提持续优化。RAG 不是搭完就结束的静态系统它是一条需要反复校准的链路。2. 分水岭一文本切分——从“按字数切”到“按结构切”2.1 固定窗口切分是第一个隐形坑很多新手不理解切分不就是把长文切成小块吗有什么好纠结的这么想的人大概率已经被固定窗口切分坑过。所谓固定窗口就是不看内容只管“每 500 个字切一刀”。这种做法的最大问题是会把一个完整的语义单元拦腰截断——表格被切开、代码块被切开、一个“第 3.2 节”的解释文字被切到下一个 chunk 里。检索的时候用户问“表格里第三列的含义”召回来的 chunk 里只有表头没有表体LLM 就只能靠猜。这就像切西瓜你要是不看纹路乱剁籽和汁水全散在案板上端上桌的每一块都像“卡住喉咙的半颗籽”。固定窗口就是这个切法你觉得“块块都一样大”实际上“块块都不完整”。我自己处理过一份带大量分节标题的制度文档按 512 字切完检索“报销审批需要几级签字”时召回的 chunk 总共四段题目和正文横跨了三个 chunk模型最后给出一个“推测大概是”的答案。把文档结构看清楚再切才把这个问题解决。2.2 顺着文档结构切先看标题再看语义改进方向其实很朴素先顺着文档原生结构找边界再用大小窗口兜底。以 Python 生态为例一个很实用的思路是如果文档本身是 Markdown 或者带标题的富文本优先按“标题层级树”切——把#、##、###当成天然的段落边界标题下面内容太少就向上合并太多就按二级边界继续拆。表格、列表、代码块这类整体性很强的元素要单独识别并保留完整性宁可让一个 chunk 是“纯表格”也不要让半个表格插进正文里再切一半。对完全没有结构的 PDF 或纯文本先做段落检测按连续换行、缩进、编号规律再做辅助切分。本地环境中做这一步工具其实不少。unstructured库可以抽取结构化元素langchain-text-splitters里也内置了MarkdownHeaderTextSplitter和RecursiveCharacterTextSplitter前者按标题切后者按字符列表递归回退。但要注意工具只是省劲关键是你得知道想保住什么——在我这儿的原则是“一个 chunk 内尽量只有一个完整的论点和它必要的上下文”。2.3 重叠、粒度与中文场景下的几个参数切分参数没有银弹但有几个经验值值得记下来。字符级chunk_size在中文场景下建议 400-800 字overlap按 10%-20% 设置也就是 50-100 字。overlap不是玄学它是为了弥合“上半段提到一个概念下半段才开始解释”这类场景。但这只是兜底不能指望 overlap 解决所有语义断裂——真正的兜底是前面的结构切分。另外要留个心眼很多框架的chunk_size是按 token 算的不是按字符算。中文一个汉字大概对应 1-1.5 个 token如果你按英文生态的 512 token 来切实际只有 300 多个汉字切得很碎。所以用tiktoken或你所用模型的分词器先数一下自己的语料再定参数别想当然。提示切分完之后一定要做一次“肉眼抽检”。随机抽 20 个 chunk看每个 chunk 读起来是不是通顺、是不是有完整语义。自动化指标再好也替代不了这一眼。3. 分水岭二召回策略——从“单路向量”到“混合检索重排”3.1 单路向量的天花板和两大致命弱点切分做好之后第二个分水岭是召回。很多人以为 embedding 模型是万能的给文档转成向量就完事。但单路向量检索有两个天生短板。第一它擅长语义模糊匹配不擅长精确关键字匹配。用户问“错误码 40207 在哪个类里定义”向量检索经常把“40207”和“40208”搞混因为向量空间里这两个 token 的语义分布太接近了。第二它受 embedding 模型本身质量限制极大。开源模型和顶级商业模型在复杂同义改写上的差距直接决定了召回上限。你换个更强的 embedding 模型hit rate 可能立刻提几个点。当然向量检索也有不可替代的优势它能理解“报销流程”和“费用审批流程”是同一个意思这是传统关键词检索做不到的。所以方向不是二选一而是把两种能力拼起来用混合检索打组合拳。3.2 混合检索与 RRF 融合朴素但可靠混合检索的标准配置是“BM25 关键词检索 向量语义检索”。BM25 负责精确命中、术语匹配向量负责语义扩展、同义改写。两路各自检索出 top 50然后用 RRFReciprocal Rank Fusion做融合排序。RRF 的核心公式非常朴素对同一个文档看它分别在两路结果里排第几名把1 / (k rank)加起来k 一般取 60。这个方案的优点是不需要做分数归一化——BM25 的分数和余弦相似度根本不是同一个量纲直接相加是耍流氓RRF 用 rank 规避了这个问题。实现也很简单五六十行代码就能写完。我在一个运维手册项目里做了一次实验单路向量召回 hit rate10 是 0.61加上 BM25 和 RRF 之后提到 0.78提升非常明显。3.3 查询改写与 HyDE让“问法”更贴近“答案”混合检索解决了一部分问题但还有一类情况它搞不定用户的问法本身就是模糊的。比如“这个能不能走报销”文档里根本不会有这句话但可能有“差旅费报销流程”“采购报销申请”之类的表述。这时候与其硬检索不如先让 LLM 把用户问题改写成几个更具体的子查询再去检索。这就是查询改写query rewriting通常用一个小模型加一条 prompt 就能实现。比查询改写更进阶一点的是HyDEHypothetical Document Embeddings核心思路是先让 LLM 根据问题凭空生成一个“假设性的标准答案”然后把这段假设性文本转成向量去召回再拿召回的真正文档片段去支撑最终回答。这个做法听起来有点绕但实测效果常常不错因为基于完整句子的向量表达比基于短问题的向量表达更接近库中文档的语义分布。代价是多一次 LLM 调用延迟多一点但召回质量往往值回票价。3.4 重排把“看起来像”变成“真的是”前面无论怎么混合召回阶段选出来的其实还是“候选池”。真正决定答案质量的是把 top 50 浓缩成 top 5 的那一下重排。重排器一般用交叉编码器cross-encoder把问题和文档片段拼在一起送入模型直接输出一个相关性分数比向量检索那种“分别编码再算距离”的方式精度高得多。在本地可落地的开源模型里bge-reranker-base或者bge-reranker-v2-m3是口碑不错的选择CPU 上也能跑一次推理大概几十毫秒到几百毫秒。实际用法是混合检索召回 top 50送进重排器重新打分保留 top 3-5 塞进 prompt 上下文。很多项目做完这一步回答质量和忠实度会肉眼可见地上升一个档位。注意重排不是把得分最高的问题丢进去就自动解决一切。如果切分阶段已经切碎了语义重排只是帮你在碎块里选相对不碎的本质还是治标不治本。所以顺序很重要先把切分做好再谈重排。4. 分水岭三知识组织——从“扁平库”到“本体/Graph”4.1 扁平向量库看不见的“关系”第三个分水岭藏得比较深也是我认为最能拉开长期差距的地方知识怎么组织。普通 RAG 是一个扁平向量库每份文档被切开的 chunk 是孤岛chunk 和 chunk 之间除了“都在一个库里”之外没有任何联系。但你仔细想想真实知识库它根本不是一个平坦的文本池子——它有实体有属性有类别还有关系。比如“离职率”和“员工满意度”不是两个不相干的词它们都挂在“人力资源”这个节点下面“A 产品依赖 B 模块”这种关系扁平库里根本表达不出来。这个缺点的官方叫法很贴切知识割裂。用户问“这个功能受哪些模块影响”如果库里有五份文档分别描述了五个模块单路召回往往只能捞出其中一两份答案必然残缺。你会觉得“这个 RAG 怎么这么笨”——它不是笨是它的知识组织形式压根没给“关系”留位置。4.2 本体 RAG先画 schema再装知识本体 RAGOntology RAG的思路是先定义领域里的概念、属性和关系形成一个 schema再往这个 schema 里填实体。用人话说就是先画一张“知识地图”再往地图上标地名。比如做制度问答schema 可以是“部门 - 流程 - 审批节点 - 材料清单”每一条制度文档都会被抽取成哪个部门、走什么流程、需要什么材料、有哪几个审批节点。好处是显而易见的用户问“采购流程需要几个节点”系统可以直接沿着流程类实体找而不是大海捞针用户问“和报销相关的事项有哪些”系统能根据“报销”这个节点把周边实体都拉出来。很多团队觉得自己知识库“结构化程度低”做不了本体其实不是——你只需要一套清晰的本体定义配合信息抽取 prompt就能把非结构化文档变成结构化事实。难点在于建 schema 需要懂业务的人深度参与这也是很多技术团队迟迟不推进的原因。4.3 GraphRAG很香但不是谁都能吃下除了本体另一个被频繁提到的是 GraphRAG。微软开源的 GraphRAG 能自动从文档里抽实体和关系建图谱再用社区检测总结“社区摘要”检索的时候既走原始文本又走摘要。这个方案对“跨文档综合类问题”的效果确实好我见过一个案例一个需要对比多个文档观点的问题普通 RAG 答得东拼西凑GraphRAG 能给你输出一个结构清晰的分点综述。但代价也很实在建图成本高、索引时间长、需要额外的图数据库和推理 token小团队和小项目很容易被这一步拖垮。GraphRAG 不是银弹它适合知识面广、关系密集、文档量大的项目。如果你的知识库只有 50 份文档用户问题也偏单一上 GraphRAG 大概率是给自己找麻烦。4.4 给普通团队的折中方案metadata 过滤 轻量图谱那不上 GraphRAG 是不是就没办法了也不是。比较务实的第一步是“metadata 过滤”——给每个 chunk 打标签部门、文档类型、版本号、业务线。检索时先用这些标签做粗过滤再做向量/混合检索。举个例子用户来自运维部门就先把检索范围限制到运维文档剩下 2000 个 chunk 里再召回精度会好看很多。如果 metadata 不够再上“轻量图谱”只抽重点实体和关系比如产品、模块、功能点之间的依赖关系单独存成一张小表。检索时先做实体链接找到相关实体再沿着关系扩展出关联文档的 ID 列表把这些 ID 加入到召回的过滤条件里。这套方案比 GraphRAG 轻得多却能解决相当一部分“跨文档关联”问题。5. 分水岭四Agentic RAG——从“固定流程”到“动态编排”5.1 固定流水线的盲区一切问题都走同一条路食话实说我一度对 Agentic RAG 持保留态度觉得“Agent”是被炒起来的词。但后来遇到几个真实场景让我改变了看法。固定流水线最大的盲区是它让“简单问题”和“复杂问题”付出了同样的代价但都没得到合适的处理。拿最简单的“路由器”举例用户问“密码忘了怎么办”这种问题根本不需要召回到 50 个 chunk再重排再生成它甚至可以直接走 FAQ 直达答案。但用户问“比较这三个方案在成本和维护上的差异”就需要多次检索、跨文档比对甚至要调外部工具。固定流水线对待这两种问题的策略是一样的结果就是简单的被过度处理复杂的没被充分处理。5.2 Router、多步检索与自我反思的落地思路Agentic RAG 的核心是把“检索几次、怎么检索”也交给 LLM 或规则去决策而不是写死成一条链。最常见的三个形态路由Router先判断问题类型——事实类、流程类、对比类、闲聊类不同类型走不同的检索策略。路由可以用一个小模型分类也可以用规则加关键词兜底。多步检索Multi-step Retrieval一个问题先查出一批文档从这些文档里再提取出下一步要查的关键词或实体继续查第二轮。适合“先定位文档、再看细节”的场景。自我反思Self-Reflective RAG生成答案之后再让模型回头检查“答案是否被检索内容支持”“检索内容是否足够”如果不够就重新检索、重新生成。这个 loop 虽然多耗几次模型调用但能显著压掉幻觉。如果你用的是 LangGraph 这类编排框架这些形态其实就是几个有条件的节点和循环边。在 Dify 里也可以用工作流画出来。关键是思维转变RAG 不再是一条直线而是一棵“先判断后走向不同分支”的路线树。5.3 别让“智能”变成失控不过我更要提醒的是成本问题和失控风险。Agentic RAG 的延迟和 token 消耗是固定流水线的数倍甚至一个数量级而且每一步“智能决策”都可能出错路由分错类、反思误判、多步检索越查越偏。这些问题在 demo 阶段不明显一上生产就会暴露。我的建议是分两层走先用规则实现 80% 的路由逻辑能用规则就不用模型再把真正需要模型判断的部分交给 LLM而且一定要设置“最大检索轮数”“最大重写次数”这类硬上限防止某个问题无限循环烧 token。简单问题求快复杂问题求全这是 Agentic RAG 的本质但“快”和“全”的边界要由业务规则而不是模型自由发挥来定。6. 分水岭五冲突消解——让答案内部先“打一架”6.1 冲突从哪来同一件事文档里居然有两种说法如果说前四层分水岭解决的是“找得到、找得准”那第五层解决的是“找回来的东西互相打架怎么办”。这个问题做知识库的人很容易遇到一份文档说“发票报销时限是 30 天”另一份说“当月发票必须当月报销”第三份说“时限 60 天”。单独召回任何一份答案都像是对的三份一起召回LLM 就开始精神分裂。这类冲突来源很典型版本更新新旧文档并存、口径不同财务和行政各说各话、适用场景不同日常报销和差旅报销规则本来就不一样。有意思的是这个问题的本质和 CPU 流水线里的“数据冲突、控制冲突”非常像——指令流水线里后一条指令依赖前一条的结果设计不好就会互相覆盖RAG 的上下文流水线里不同来源的段落也在“抢回答权”。CPU 解决冲突靠转发、乱序执行、分支预测RAG 解决冲突靠不上运气而靠元数据、优先级和 prompt 约束。6.2 从元数据到冲突消解规则第一步是给每个 chunk 带上充分的元数据文档标题、版本号、发布时间、来源部门、适用范围。没有这些信息冲突消解就是空谈。有了元数据之后可以设定几个简单的优先级规则版本优先同一主题取版本号或发布时间最新的。口径优先如果用户身份是财务人员优先取财务口径的文档。粒度优先具体场景的文档优先级高于通用文档。第二步是上下文组装层面做“冲突感知”。我常用的一种做法是检索回来的 top 文档如果来自不同版本或不同部门先把它们按“事实一致性”做个聚类同一个事实不同说法的放一起在 prompt 里给 LLM 这样一段指令——如果检索内容之间存在冲突请分别列出不同来源的说法并说明你采纳某一说的依据。这个思路比让 LLM 自己强行“和稀泥”要稳得多。6.3 让 LLM 学会说“不知道”和“不确定”冲突消解的底线是别让 LLM 假装没看见冲突。很多人觉得 LLM 给出的答案只要“看起来流畅”就行但知识库问答最忌讳的就是把互相矛盾的片段揉成一段“看起来都对的废话”。我在实践里会给系统加一个“忠实度检查”步骤把生成结果拆成若干断言逐条对照召回内容没被支持的断言就打回重写。这一步可以放在 LLM 生成答案之后用一次额外的模型调用完成。我更愿意把这一步称为“让 RAG 承认自己的边界”。一个知道自己什么时候不确定、并且能说“根据文档 A 是 X根据文档 B 是 Y两者存在差异”的系统远比一个假装什么都懂的聊天机器人可靠得多。7. 分水岭六评估体系——没有度量就没有分水岭7.1 hit rate 只是入场券不是成绩单前面说了五层分水岭每一层改造都需要验证改了切分之后到底有没有变好换了重排器之后值不值如果你只拿一两个问题自己试那永远得不到可靠结论。这也是为什么最后一个分水岭我认为是评估体系。很多人知道要测 hit rate——也就是“正确答案在不在召回的 top_k 里”但 hit rate 只衡量了“有没有捞到”没衡量“答案生成得好不好”。你可以召回率 100%但 LLM 还是答得稀烂也可以召回率 70%但每一条回答都忠实有据。所以真正可用的评估体系至少要分成两层检索层和生成层。检索层看召回率、MRR、NDCG 这类指标生成层看忠实度faithfulness、答案相关性answer relevance、上下文相关性context relevance。打个比方hit rate 相当于“候选人有没有被拉进面谈名单”忠实度相当于“入职之后说的话是不是都有实锤证据”。7.2 一套可落地的离线评估组合不考虑商业化产品的话最省钱的评估方式是“人工标注小测试集 LLM-as-Judge”。先手工构造 50-100 组问题标准答案涉及文档的三元组作为黄金测试集。然后每次改完系统跑一遍测试集得到一组指标。用 LLM 打分的时候要注意让评分模型只对比“标准答案”和“系统答案”的事实重合度不要比文风否则会被带偏。我自己常用的指标和达标线大致如下表给大家一个参考指标含义我常用的达标线说明Recall10真实答案是否在召回前 10 条中≥ 0.85检索层基础指标MRR真实答案排位越靠前越好≥ 0.7衡量排序质量忠实度生成内容是否被召回内容支持≥ 0.85生成层最重要指标答案相关性是否答非所问≥ 0.85防止跑题上下文相关性召回上下文是否干净≥ 0.6噪声控制这个表格不是标准答案但它给了我一个判断基线任何改动如果让忠实度跌了哪怕 hit rate 涨了我也会回滚。7.3 没有测试集的话先别谈优化很多项目做不好评估是因为压根没有测试集问“为什么改完没变化”也只能靠感觉。我的建议是测试集不贪大但要有代表性覆盖简单事实类、流程类、对比类、冲突类、跨文档类还要包括几个“库里根本没有答案”的问题——后者能测出系统会不会硬编幻觉。日常维护中每遇到一个线上答错的案例就沉淀进测试集半年下来这就是团队最值钱的资产。线上环境还要做采样监控。离线指标解决不了“真实用户问法千奇百怪”的问题所以我会定期从日志里抽取问题人工复查回答质量或者用评分模型批量打分把低分案例拿出来分析。没有评估前面所有“分水岭”都是空谈——你以为你跨了过去其实只是换了个姿势在同一个坑里躺着。8. 一次从流水线到分水岭的改造实录8.1 初始状态demo 能跑但业务不买账空谈这么多原则不如看一次具体改造。去年我经手一个内部运维知识库项目语料大概 3000 份文档包含制度、操作手册、FAQ 表格。初始版本就是标准的固定窗口切分加单路向量检索Dify 里拖一拖就上线了。业务方用了两周反馈非常集中技术问题能答个大概但流程类问题常常给错步骤制度类问题新旧版本混着答时间一长大家都不信它了。当时我们拉了一个问题清单大约 40 个高频错题。抽了三类典型问题分析一是制度类报销时限不一致、二是流程类申请权限要哪几步、三是精确类某个错误码对应的模块。这三个类型暴露了三个不同层级的缺陷正好对应前面讲的切分、召回和冲突处理。8.2 改造过程与关键参数第一步改切分。文档里有大量的标题和表格我们先用unstructured把表格单独抽出来正文按标题层级切再合并过短的段落。chunk_size从原来的 512 字符改为 700 字符overlap设 80。这一步做完肉眼抽检 chunk 完整度明显上升表格不再被切断。第二步改召回。本地部署了一个bge-m3向量模型加上 ES 或本地 FTS 做 BM25 关键词检索两路各取 top 50用 RRFk60融合然后再过bge-reranker-base重排取 top 5。代码大致长这样def hybrid_search(query, retriever_bm25, retriever_vec, top_k50, k60): hits_bm25 retriever_bm25.retrieve(query, top_k) hits_vec retriever_vec.retrieve(query, top_k) fused {} for rank, doc_id in enumerate(hits_bm25): fused[doc_id] fused.get(doc_id, 0) 1 / (k rank 1) for rank, doc_id in enumerate(hits_vec): fused[doc_id] fused.get(doc_id, 0) 1 / (k rank 1) ranked sorted(fused, keyfused.get, reverseTrue) return ranked[:50] def rerank(query, doc_ids, reranker, top_n5): pairs [(query, doc_map[i].text) for i in doc_ids] scores reranker.rerank(pairs) top_ids [doc_ids[i] for i in sorted(range(len(scores)), keylambda j: -scores[j])][:top_n] return top_ids第三步处理冲突。给所有入库存档打上版本号和生效日期检索阶段根据问题类型做版本过滤prompt 里明确要求“如果存在不同口径的答案不要强行合并要分列说明并标注来源”。这一步用到的召回 prompt 片段大概是如果检索到的文档之间存在冲突 1. 分别列出不同来源的说法并标注文档标题和版本。 2. 给出你的判断依据例如以最新版本为准或以XX口径为准。 3. 如果无法判断明确回答“存在冲突需人工确认”。第四步才上了一点轻量 Agentic 路由规则很简单FAQ 类问题直接查表制度类问题走混合检索加版本过滤对比类问题先做一次实体链接定位相关条款再二次检索。没有上复杂反思循环因为成本和延迟不划算。8.3 改造前后的效果对比用 60 条黄金测试集跑了一轮关键指标变化如下指标改造前改造后Recall100.610.82忠实度0.380.74答案相关性0.520.81平均回答耗时约 1.2s约 1.8s忠实度从 0.38 提到 0.74是这次改造最值得的地方。代价是耗时多了 0.6 秒换来的是回答终于“有据可依”。业务方的反馈也印证了变化原先高频错题里有 28 道被彻底解决另外 6 道表现为“系统能说明来源不一致”不再硬编一个错误答案。这个案例没有用到什么神秘技术全是前面讲的分水岭工程化实践。9. 高频问题排查与避坑清单9.1 常见问题速查表如果读者已经搭了自己的知识库正在为某些问题头疼我整理了一张高频问题排查表可以对着查现象可能原因优先排查动作答案答非所问召回噪声太多或路由错误看 top 5 召回内容是否与问题主题无关检查重排是否生效答案内容正确但细节缺失切分把细节切碎了检查 chunk 完整性看看是不是表格/列表被切断新旧版本混答没有版本过滤给 chunk 打版本号检索时过滤旧版本同一个问题两次回答不一样上下文不稳定或 prompt 随机性固定 prompt 模板降低 temperature检查召回是否稳定简单问题回答太慢路由不生效走了重链路加规则路由FAQ 直答数据库里明明有答案却查不到embedding 对精确词不友好加 BM25 关键词检索走混合召回回答“看起来对实际编造”忠实度检查缺失增加 faithfulness 校验或要求答案标注引用来源9.2 我踩过最深的三个坑第一个坑是过于信任 embedding 模型。早期我觉得换一个更强的 embedding 就能解决所有召回问题结果发现精确数字和代码错误码根本不吃这一套最后还是靠混合检索把短板补上了。第二个坑是盲目上 GraphRAG。看过一次 GraphRAG 演示之后我觉得自己也要搞一个图谱结果花了两周做实体抽取和调图库效果提升不到 10%还拖慢了索引速度。后来把它降级成“轻量实体关系表 metadata 过滤”性价比反而高得多。第三个坑是改完系统不看指标凭感觉调参。有一段时间我反复调top_k和overlap今天觉得 800 好用明天又觉得 600 好折腾一周毫无进展。后来逼着自己先搭测试集和评估脚本所有的调参都看指标说话才从“炼丹”变成“工程”。9.3 还想往上走的话可以往这几个方向扩展如果你把上面六处分水岭都跨过了下一步可以考虑几个延伸方向多模态知识库文档里带图表、截图怎么办那是一个全新的“切分”问题、增量更新与知识时效管理知识库不可能一次性建完如何低成本地持续更新、以及更细粒度的权限控制不同部门的人看到的知识范围不一样。这些话题如果大家感兴趣之后我可以再单独开一篇聊。但无论如何别急着追逐新概念先把切分、召回、冲突和评估这四件事做扎实你的 RAG 就已经甩开大多数“流水线选手”了。
返回列表