资讯动态

RAG落地三层架构:从拼乐高到可用系统的关键实践

发布时间:2026/10/17 8:37:40 来源:尧图企业网站定制
上个月在内部做了一次RAG系统的复盘用户问“我们报销流程的第二步是什么”系统给出了一段很像答案的答案但流程编号是旧的。翻日志检索阶段把“报销流程”召回到了另一份政策文件的相似段落上然后模型直接照着生成了。技术栈其实很完整向量库、embedding模型、大模型API、提示词模板全都有。但这套系统上线前大家都觉得RAG就是拼乐高——组件齐了接口对上就能回答问题。真上线才发现拼出来的东西只是“像RAG”不是“能用的RAG”。后来我们把整个项目重新拆了一层才意识到RAG落地的难点根本不在选哪个模型、接哪个库而在于知识工程本身要有一副骨架。这个骨架我习惯把它分成三层底座层、知识层、生成层。这篇文章就基于这个三层架构来写把每一层里我认为最关键的细节、最容易被忽视的坑以及我实测下来有效的做法一次讲清楚。适合谁看适合那些已经跑通了demo、正准备把RAG系统推向真实业务的开发者和技术负责人也适合刚接触RAG、想一次性建立整体认知的读者。1. RAG为什么会被做成“拼乐高”先别急着看组件先回答三个问题。第一检索的目标是什么很多人以为检索就是把相似文本捞出来但相似不等于能回答用户的问题。用户问“报销第二步怎么走”你需要找到的是能够推导出第二步的那个证据片段不是跟“报销”长得像的任何一段。这两年我用过的项目里至少一半的badcase在检索层就已经跑偏了后面再怎么调提示词都没有用。第二知识是如何被机器“理解”的文档进入系统之前先要切分、清洗、向量化。这一串流程做完原始文档的目录结构、章节树、表格关系大概率已经丢了。如果知识层的处理不保留足够的结构信息光靠向量去“理解”一篇几十页的制度文件结果就是语义断章取义。第三模型何时该回答、何时该拒绝RAG系统不是模型懂而是系统告诉模型“你只有这些材料这块区域你没资格说话”。这个边界必须在生成层显式定义否则它就是一个没有校对和引用的百科全书看起来什么都敢说但没人敢用。这三个问题分别对应了底座层、知识层、生成层的职责划分。很多团队把RAG做成拼乐高就是因为只盯着“有没有”某个组件答不上来“为什么要这个组件”以及“这一层到底在解决什么问题”。1.1 用图书馆的类比理解三层骨架用一个生活化的类比来理解这件事。一个真正能用的知识库是一座图书馆不是一堆书架。底座层相当于图书馆的建筑和基础设施。你得有房子、有电、有网络、有安保系统书架再多地基不稳书多了反而崩。放到RAG里就是向量数据库、索引结构、存储容量、并发能力、权限模型。这一层决定了系统能不能在真实流量下活下来。知识层相当于图书馆的编目和管理制度。书买回来不是直接堆在阅览室的要拆包、分类、编目、贴标签、定期盘点下架。放到RAG里就是文档解析、清洗、切分、向量化、元数据管理、知识更新。这一层决定了系统回答问题的上限。检索效果70%以上烂在知识层这是我实际拆过的结论不是凭空说的。生成层相当于图书馆的咨询服务台。馆员把资料拿给用户不是把整摞书扔过去而是告诉用户“你要的信息在第几页第几行依据是什么别的部分我们馆里没有。”对应到RAG里就是检索结果的整理、提示词编排、引用溯源、拒答策略。这一层决定了用户最终拿到的是“可用的答案”还是“像答案的文字”。所以RAG的骨架不是某一个大模型或者某个向量库而是这三层各司其职。你问“为什么落地这么难”答案通常是组件有了层没有。2. 底座层扛住“脏、慢、乱”的基础设施底座层第一个决定成败的是向量数据库。但很多团队的选型逻辑特别单一查到某个榜单评分高的文档全的就选它。这种选法在前两个月的demo阶段没问题一旦数据量上来、并发打过来问题就出来了。我在一个项目里见过这种情况。某团队选了一个评分靠前的向量库刚开始几千条文档检索很快后面数据量涨到几十万条分片不均匀部分分片的查询直接超时整体时延从几百毫秒飙到几秒。后来换成支持细粒度分片策略、且能查看分片分布的方案才把时延稳住。选型时我一般会看五个维度而不是只看榜单索引类型与内存占用。HNSW索引在数据量大时很吃内存同样数据量有的库要1倍内存有的要2倍差别不小。混合检索能力。原生支持关键词匹配和向量召回比较重要后面要讲的是业务中有大量精确匹配需求选库时别漏掉。过滤条件下的召回性能。元数据过滤比如只看某个部门、某个品类的文档时检索时间是否线性恶化。数据分片和弹性扩展。文档量增长是必然的能不能平滑加节点。权限隔离和审计。真实业务里知识库往往涉及多部门知识可见性必须分层底座不支持的话后面还要在业务层硬写很痛苦。所以我的建议是用真实数据和真实查询分布每个备选库各跑一版“召回质量时延内存”的基线测试再结合团队运维能力来定而不是用别人的基准测试替你做决定。2.1 索引与召回参数是“开箱即用”的陷阱选好了库下一步很多人会犯一个新错误直接把默认参数当标准答案。向量检索库的默认参数通常是面向通用场景调节的安全值不是为你的数据分布定制的。同一个库跑在新闻语料和跑在内部流程文档上最优的索引参数差很多。最容易踩的坑有三个。第一个坑是召回数量top-k。网上很多人建议top-k20甚至50但我在实际使用中踩过这个坑提示词窗口有限召回的段落太多模型反而容易被无关噪声带偏。常规的问答场景k4到8通常就能覆盖答案召回质量不好时应该先优化切分和检索而不是一味加大k来“碰运气”。第二个坑是HNSW的efSearch和M参数。efSearch越大召回越准但越慢。建索引时M值越大图越密集、内存越高召回路径可能更短。实测下来千万级以内、语义近邻类问答M16到32efSearch在64到128之间是一个比较均衡的区间。无脑拉到256查询延迟翻倍都看不到多少收益。我后面两三个项目都用这个区间效果相对稳定。第三个坑是相似度阈值。很多团队会设一个“低于0.7就算不相关”的规则。但不同embedding模型的得分分布差异特别大有的匹配分数普遍在0.6左右有的0.85才算是高相似。所以不要拿A模型的阈值去套B模型。最靠谱的做法是拿一批已知相关的正样本和已知不相关的负样本画出分数分布再决定阈值切在哪。这样可解释也不会误杀。2.2 混合检索是命中率的保险丝只靠向量检索的RAG在语义性问题上表现还行一到精确匹配就露馅。你们的业务里一定有这种场景用户问“企业版和专业版的定价差别”文档里对应的是“企业版XXXX元/年专业版XXX元/年”向量召回可能把“定价”这块捞出来也可能捞到一堆“版本对比”的模糊表达。但如果先用关键词锁定“企业版”和“专业版”命中概率就高很多。所以我在底座层一定会要求“混合检索”能力。用BM25或字面匹配召回的候选集跟向量召回的候选集合并再用一个简单但有效的融合策略排序。我自己常用的是RFFRank Fusion或者带权重的分数归一化权重一般从7:3到6:4之间调具体比例看业务里专名和短语的占比。这里提醒一句很多向量库接口里混合检索是“插件级”的运行时会带来额外时延和数据一致性负担。如果库的原生混合检索能力弱就需要在业务侧做一层路由查询含专名的走关键词通道其他走向量通道最后再merge。这个路由逻辑不复杂但能让命中率明显提升。3. 知识层决定RAG上限的“数据工程”底座层决定系统“能不能跑”知识层决定系统“答得好不好”。这部分我想多说一些因为实际落地的项目里至少80%的调优时间是在处理知识层的问题而不是模型问题。3.1 文档解析入口处埋着最多的坑很多团队把“解析”看成开箱可用的功能PDF拖进来转成文本搞定。真上了业务你会遇到扫描件PDF没文字层表格被切成一行行碎片页面拆页跑版掉行页眉页脚混进来当正文。印象最深的一次某客户的知识库里有大量带表格的文件解析出来的文本里表格数据全部连成一串检索出来根本没法看。后来我们把表格单独提取成结构化数据再以“表格标题字段值”等形式重新组织成检索片段才算能用。类似问题在真实知识库场景里非常普遍实际的解决方式是对不同类型的文件走不同的解析流程扫描件先做OCR表格文件单独解析网页文件则要清洗掉导航与页脚。解析的结果不能直接入库。我的习惯是保留一份“原始文本”和一份“清洗文本”还要保留层级信息。这样后面做切分、溯源、引用提取时才有依据。好多项目之所以最后答案给不出引用页码就是因为原始文档的段落位置信息在入库时丢了。3.2 切分策略要跟随问答粒度切分是知识层最典型、也最影响效果的环节。切小了上下文不全切大了检索时噪声多。而且不存在一套固定参数能适配所有场景必须根据用户问答的粒度调整。我见过最典型的失败案例是一个内部制度问答直接用固定长度900字符切分。制度里的“申请条件”“审批流程”“时限”通常分散在几页里固定切分把上下文切碎了。用户问“如果请假超过三天怎么审批”检索出来的片段只有“三天以上需部门负责人审批”后面“再报人事部门备案”的流程老被漏掉。之后的这类场景里我一般分成两种切法按结构切。把文档按章节、条款、段落先切开再对超长段落做二次切分。这种方式最大程度保留上下文结构。父子分块。对需要细粒度回答的场景给每个子块挂一个父级摘要。检索时先匹配子块再把父块上下文一起喂给模型。相当于“先在目录里找到页再把整页拿给回答者看”。固定长度切块不是不能用而是要用对地方。比如FAQ粒度比较统一、文档格式比较规整的语料固定长度反而是最简单稳定的做法。重点是切分粒度要和“用户想问什么”对齐不是和“文档长什么样”对齐。3.3 embedding模型的选型与微调时机embedding模型的选择很多人也会纠结但其实先想清楚一个问题就够了你的领域距离通用语义空间远不远通用领域、日常百科类的知识通用embedding模型基本够用。但如果你的语料里大量是专有名词、缩写、内部黑话、版本号比如“某平台V3.2的灰度切换逻辑”通用模型的向量空间很可能把“灰度”和“灰色”混为一个语义而它本来该跟“上线策略”更接近。什么情况下值得做微调不是“效果不好”就微调而是“检索结果里反复出现同类型的语义偏差且偏差可归纳”。比如你的语料里“核销”这个词总被检索成“销毁”的相似语义那就可以收集一批这类case做对比学习微调。微调前一定要准备一个小的检索评测集拿真实查询和标注好的相关片段跑一遍基线否则你连“改进了多少”都说不出来。顺带提醒一下很多团队会把embedding模型的向量维度当成越大约好但维度越高内存越大、检索越慢。如果你只有几百万条文档768维模型已经够用没必要上4096维。这个选择应该和数据规模、硬件预算一起看而不是单看模型排名。3.4 元数据知识层的“坐标系”切分和向量化做完每个片段可以入库了。但如果只入库不挂元数据后面很多事都做不了。我的做法是每一个知识块至少挂这些字段来源文档ID、所属章节路径、文档版本、生效时间以及可见范围。这四个字段的价值在检索和生成时都会体现。先说检索。有了章节路径和生效时间用户问“2025年的年假政策”时就可以直接过滤掉2024年的旧版本文档哪怕旧文本在向量空间里更相似。如果没有元数据过滤系统会把几年份混在一起答案必然乱套。再说生成。生成层要给出引用时每一处结论都必须能回溯到具体的知识块ID和源码位置。否则你引用的是一个“库里没有来源”的拼接文本等于给模型胡编乱造背书。最后一个容易被忽略的点是知识更新。文档改版后旧版本应该在向量库里标记“失效”而不是物理删除。因为有些历史问答场景还需要查旧版。我习惯给每个知识块加一个“状态”字段生成时只召回“生效”状态的块平时做审计和回溯时再查历史块。这个设计不复杂却能在后续运维里省掉无数扯皮。4. 生成层让模型“拿着材料说话”底座层把数据存好、检索快知识层把语料切好、召得准最后一切都是为了生成层。我见过很多团队在这一层做得特别粗糙把检索结果拼进提示词模型说什么就是什么。结果就是用户觉得这个系统“会说话但说话不靠谱”。4.1 上下文组织不是拼接提示词检索回来了好几个片段别直接按向量相似度顺序拼起来扔给模型。直接拼接的后果是模型容易把靠后但更权威的片段忽略掉或者被排在前面的噪声片段带偏。我一般会在这一步做四件事去重。多路召回容易重复重复段落挤压窗口模型还容易把它当成加权的证据重复出现的“支持点”会被过度强化。按证据强度重排。同类问题的历史咨询记录、明确写明“规定如下”的条款通常比泛泛而谈的段落权重高。重排的依据得是业务规则不能只看向量分数。压缩长段文本。单个片段超过模型窗口承受范围时要做摘要或截断处理把最关键的句子保留下来。标注来源。给每个片段按“【引用1】【引用2】”标记提示词里要求模型回答时在关键句后带上对应编号。这一套流程跑下来生成的效果提升很明显。我自己在一个巡检类项目里做过对比单纯拼接时正确率约61%做了去重和重排之后同样模型、同样语料正确率涨到78%左右。这个提升几乎不花算力。4.2 提示词模板的几条设计原则提示词模板这一层网上一搜一大把“万能模板”但我实际用下来真正能扛住业务的模板要有几个共性。第一使用“指令限定条件输出格式”三段结构。指令部分要细比如“只能根据提供的片段回答问题禁止使用片段之外的知识”。限定条件要显式包括“如果不能从片段中得到答案请回答不知道并给出原文档出处”。输出格式要固定比如“第一段给结论第二段给依据”。第二强制引用编号。在提示词里让模型在关键结论后面加引用的编号这一步无论如何都不能省。它既是让答案可信的关键也是之后自动化评估的基础。没有引用的AI回答等于没有出处的一句话用户根本没法信任。第三温度参数别乱调。越低的温度越保守在知识问答场景我一般定在0.1到0.3之间。超过0.5就会开始出现自由发挥式表达对于知识类问答完全没有必要。第四明确写出拒答句。比如“如果检索结果中没有任何片段能回答用户的问题请明确说‘抱歉当前文档中没有涉及该内容’不要编造。”很多模型会出于“不冷场”的本能强行生成必须把这句话写进模板里压住。4.3 引用、溯源与拒答边界引用这个东西看起来是把模型输出的文字后面加上编号做起来却不那么简单。编号必须对应到真实的检索片段编号而片段编号必须真实对应到文档源码路径。如果你在知识层没保留原始文本跟段落位置到生成层就追不回来了。这也是为什么我在第3章反复强调信息保真。拒答边界也得提前定义清楚。知识库里有答案的模型要答得明确、果断、给出依据。知识库里没有答案的要拒绝、要提示“不在当前知识库范围内”。知识库里没有、但模型预训练里有相关内容的这里是最难处理的模型往往会“凭感觉”补全。应对办法是把“只能使用片段内容”写成强约束同时设计好负面样本测试找一些故意不在库里的问题看模型会不会强行作答。我给团队讲的另一个思路是直接把知识库做成“可信范围”的概念。生成层允许发挥的范围仅限于知识库覆盖的范围。超出范围的一律转人工或提示“没有相关材料”。这比技术手段更能让业务方接受因为它的边界是清晰可解释的。5. 落地路线图与常见故障排查最后一章我从项目落地的角度把过程收拢一下顺便把排查方法写成一目了然的速查表。毕竟写了这么多理论落地时你会遇到的其实是几个反复出现的具体症状。5.1 从单体实验到三层加固我推荐三阶段推进的方式每一阶段都有明确的退出标准。第一阶段叫“最小可问答跑通”。选一小批代表业务的高质量知识语料大概几十篇到上百篇在底座上跑通入库、检索、生成、引用全链路。这一步主要验证数据结构、链路通断退出标准是“20条核心问题能答能引”。不用追求全面覆盖但得把骨架搭起来。第二阶段叫“分层加固”。底座调索引和混合检索知识层做切分策略调整和元数据补齐生成层把提示词、引用、拒答规则全部定下来。这一段的重点是用一个正式的评测集来回测量每一层的改进。退出标准是“评测集整体正确率达到可接受线且badcase有分类记录”。第三阶段叫“规模化与交互升级”。把全量文档灌进去做多轮对话优化、意图改写、Agent路由。这个阶段的目标已经不是“能不能答”而是“答得是不是像业务顾问、答错了是否能自省”。多数项目卡在第二阶段。原因是大家总想一步到位结果一个问题都定位不了。分阶段推进每步只动一层出问题时你才知道是哪层出的问题。5.2 三类高频故障速查表实际项目里最常遇到的故障我整理成一个速查表。遇到问题时先对着症状定位再按层排查。症状可能原因先查哪层典型处理用户问题检索不出任何片段切分过碎、embedding效果差、文档未入库知识层先确认文档解析成功再做“直接搜索关键词能不能命中”的单项试验检索出来了但排序不对答得牛头不对马嘴top-k太小、重排规则不对、片段归档混乱底座层生成层加大top-k看有没有正确答案检查重排依据确认元数据过滤条件是否误伤答案流畅但没有依据模型自由发挥、提示词没有强约束、引用没开启生成层温度降到0.1以下提示词增加“只能基于片段”的约束要求每个关键句挂引用编号同一个问题两次答案不一致召回有随机性、多个片段竞争知识层生成层固定检索的评分种子或调整HNSW参数对并列段落做优先级规则多轮对话里第二问失去上下文生成层没有做会话态管理生成层把历史问题改写成独立查询改写后再检索检索速度随着数据量增长明显下降索引参数不合理、分片不均、过滤条件使用不当底座层检查M和efSearch值分析慢查询必要时做分片调整这张表不是万能药但99%的“为什么回答不对”都能在大方向上归入其中某一层。5.3 效果评估先建一把“烂尺子”有一个讨论得很充分但落地依然普遍存在的问题做RAG的项目团队经常不建设评测集收尾时拿几条样例人肉看效果感觉“还行”就上线。这是拦路虎。我的建议是第一阶段就把评测集做出来宁可是个很简陋的“烂尺子”也好过没有尺子。具体做法整理30到50条高频业务问题标注每条问题的标准答案片段ID、期望答复的关键点。每周跑一遍回归用“回答能不能命中关键点”和“引用是否正确”两个维度打分。对badcase按“检索错误”“上下文错误”“生成错误”分类记录这样改进起来有的放矢。我在实际项目里吃过这个亏。有一段时间团队靠“提问几个例子看效果”调整参数调来调去觉得都变好了。后来有了评测集回去一跑发现只是把一条badcase挪到另一条badcase上整体正确率压根没动。建立评测集之后每一次改动才有衡量的准绳这才是整个RAG系统能不能持续迭代的基础。这套笨办法的成本不高但价值是真大。对创业团队和小团队尤其适用从第一天就把评测集当骨架的一部分来做后面会顺很多。关于RAG落地最后想说的是三个层不是三份文档而是排查问题时的一个坐标系。遇到任何badcase先问是哪一层出的问题再去动对应的模块。我见过很多团队时间花在反复调提示词上最后发现是知识层的切分粒度没对上提问粒度也见过团队花大力气换embedding模型最后发现是底座层的检索参数根本就没校准。把三层边界想清楚之后这些弯路其实都可以少走一大半。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑