资讯详情

从六个开源RAG项目逆向出的自研架构蓝图

📅 2026/10/13 5:19:01 | 华诺云谱 👁 阅读
从六个开源RAG项目逆向出的自研架构蓝图
我一直在想一个挺反直觉的问题为什么很多做RAG的人明明代码写得也还行最后做出来的系统却总感觉差口气不是检索模型不够好不是大模型不够聪明而是整体设计根本没有把“检索增强”当成一个系统工程来做。为了弄明白这个问题我在准备自研RAG方案时没有急着选型或写代码而是挑了一批有代表性的开源RAG项目逐个跑通、拆代码、看架构最后从里面逆向出一套可以直接拿来自研的蓝图。这篇文章就是把那次拆解和落地的过程做个复盘。先说清楚我的目的不是让你去抄某个开源项目的代码而是搞清楚这些项目为什么这样设计哪些模块必须自己写哪些可以借现成的以及自研RAG时真正值得花钱花精力的地方在哪里。如果你是刚开始搭RAG、正在纠结架构的工程师或者已经在用开源框架但想收回来自己做更可控的团队这篇内容应该能帮上忙。1. 为什么非要把开源项目逐个拆开看我见过太多团队做RAG的方式了先选一个框架连上向量数据库丢几篇文档进去demo跑通了就觉得完事了。结果等到面对真实业务数据时问题一个接一个冒出来表格内容被切得乱七八糟、多轮对话总是翻旧账、员工问了一个语料里没有的问题导致幻觉、某些敏感文档居然被别的部门的人检索到了。这些问题都不是单点技术能解决的而是架构层面的问题。所以我采用了一种比较笨但有效的办法找六个有代表性的开源RAG项目把它们当成“参考实现”来逆向工程看每个项目在数据链路的不同环节是怎么做决策的然后把这些决策综合成一张可用蓝图。1.1 逆向工程不是在逆向代码而是在逆向决策我对每个项目只问四组问题不追求把每一行代码都读懂。第一数据是怎么进来的接入层支持哪些文档格式有没有权限模型图片表格怎么处理第二数据是怎么被索引的索引层切分策略是什么嵌入了哪些元数据用了几个索引第三检索和生成是怎么衔接的编排层是简单把检索结果拼进Prompt还是做了查询改写、多轮记忆、上下文压缩第四项目怎么证明自己有效评测层有没有内置评测集有没有可观测指标还是纯靠人工看效果这四个问题恰恰是大多数自研RAG忽略掉的部分。大多数人只关心“嵌入模型选哪个”“向量库用什么”但开放源代码里真正拉开差距的往往是文档解析、元数据管理、检索后的重排、以及一套能反复跑的评测集合。1.2 六款样本到底怎么选出来的我选样本的标准有三个一是能独立跑起来不依赖某个特定平台二是代码量跨度要大既要有适合学习的小型项目也要有接近企业级的完整平台三是功能定位要有差异最好能覆盖RAG的不同侧重点。最终我选了六款匿名称作A到F避免广告嫌疑也避免先入为主。产品A一个偏轻量的检索增强方案核心是“向量检索 大模型生成”代码量很小适合理解RAG最简链路。产品B一个通用编排框架把文档解析、检索、记忆、生成拆成可插拔组件扩展性很强。产品C一个面向企业级场景的知识库平台开箱即用自带权限、多用户和完整的问答界面。产品D一个以评测和回归测试为卖点的项目重点关注答案质量、命中率和回归对比。产品E一个把知识图谱和向量检索结合的方案强调多跳推理和实体关系。产品F一个偏全栈多模态的解决方案文档里包含复杂表格、图片、版面信息强调结构化抽取。这六个放在一起基本覆盖了RAG的各个流派单路检索、多路混合、图谱增强、企业级平台、评测优先、多模态复杂文档。把它们放在一起拆比单独研究某一个成熟框架能看到更完整的全局。2. 横向解剖后发现的三层关键差异看完六个项目的目录结构和核心代码后我可以明确说一句RAG的难点根本不在大模型调用而在数据侧和评测侧。大多数项目的核心代码里LLM调用只是薄薄的一层真正厚重的部分是文档处理、索引管理、检索路由和评测工具。2.1 文档接入与解析层占了四成以上的代码量产品C和F在这块投入最重。产品C把PDF、Word、Markdown、HTML、扫描件都做了适配器每个类型有独立的解析流程。产品F干脆把版面分析、表格识别、阅读顺序还原做成了独立模块对扫描件还会先走一遍OCR再加布局识别。最让我意外的是哪怕是产品A这种极简项目也没敢把PDF直接塞进向量库而是先转成Markdown再切块。这个细节特别关键因为很多自研RAG翻车就翻在这里直接把PDF文本抽出来一切表格被拆得四分五裂标题层级全丢了检索出来的内容虽然看起来相关但句子断得前言不搭后语。真正好用的做法是保留文档结构把标题、段落、表格、列表的层级关系作为元数据存下来这样切块的时候可以让一个块尽量落在同一个语义单元里。这不是什么高深技术就是老老实实把解析层做厚。我在自研方案里直接照搬了这个思路先用解析器把文档转成带结构标记的中间格式再做切块。2.2 索引与检索层单路到多路的进化路线产品A代表的是最朴素的单路方案文档切块向量化存入向量库检索时做相似度搜索取Top-K。跑demo没问题但一到真实数据就会暴露一个尴尬的事实——有些高频词和精确匹配的查询向量召回的效果反而不如传统的关键词检索。产品E走的是另一条路。它在向量索引之外又维护了一个知识图谱文档里的实体和实体之间的关系会被抽取出来存成三元组。检索时同时发出去两路查询一路走向量一路走图谱再合并结果排序。产品B做法更具启发性它不限制你只能用一个检索器而是把检索做成一个可插拔的“路由层”你可以同时挂上向量检索、全文检索和外部API检索由上层逻辑决定各自的结果怎么合并。从这几个项目身上可以总结出自研RAG只要数据量超过几千篇文档就不能只押注向量索引一种路线至少要考虑“向量 关键词”的双通道方案。2.3 生成与状态管理谁在做多轮对话的脏活累活如果你只用RAG做单轮问答生成部分很简单把检索到的文本块拼接到Prompt里丢给大模型就算完事。但一旦涉及多轮对话问题就来了用户上一轮提到的指代词“它的价格是多少”“那个方案可行吗”如果没有上下文记忆模型根本不知道“它”和“那个”指代什么。产品B内部做了一套对话状态管理把历史对话压缩成摘要再结合当前问题做一个“查询改写”把包含指代关系的原始问题改写成一个完整的、可单独检索的句子然后再去索引里查询。产品C更彻底直接为用户会话维护了一个短期记忆库最近几轮的关键信息会被存下来回答时先做记忆检索再走RAG主链路。这个把“查询改写”放在检索之前的设计是自研RAG最容易漏掉但收益很大的环节。我在自己的方案里也复刻了这个机制多轮场景下先用模型把当前问题结合历史改写成一个无指代的问题再进入检索环节。3. 从六款产品倒推出来的七层自研蓝图拆完这些项目之后我脑子里逐渐形成了一张自研RAG的蓝图。它不是某一个产品的复制而是把六款产品里各自做得好的模块挑出来重新组合成一个适合自己业务的分层结构。3.1 蓝图长什么样整个自研RAG系统可以拆成七层每层只关心一件事层与层之间通过清晰的接口对接。这样最大的好处是每一层都能独立替换、独立测试也方便定位问题。层职责关键输入关键输出灵感来源接入层对接各类数据源文件、网页、数据库、API标准化文档对象产品C解析层解析格式并保留结构PDF、Word、扫描件等带结构标记的中间格式产品F切分与增强层切块并补充元数据中间格式文档块 元数据产品A、E索引与检索层建立多路索引并提供统一检索接口文档块多路召回结果产品B、E精排与过滤层重排、去重、权限过滤多路召回结果最终进入Prompt的文本产品D生成与记忆层组装上下文、多轮对话精排结果 历史对话答案与引用来源产品B、C评测与迭代层离线评测与线上反馈收集黄金问答集指标报表、回归结果产品D这个七层结构看着有点重但对自研项目来说每一层都可以先用最朴素的实现再逐步迭代不需要一开始就全部做厚。3.2 为什么越不起眼的层越能决定成败大多数团队自研RAG时把注意力放在第二层到第四层之间觉得有了向量索引、接上大模型系统就建成了一半。但我在拆完这六款产品后反而觉得最关键的其实是第一层、第五层和第七层。第一层接入层决定了你能不能把数据“无损”地送进来如果接入层没做好后面所有步骤都是在垃圾上加工第五层精排和过滤决定了进入大模型的信息质量很多幻觉其实不是模型产生的而是检索出的坏文本块带进去的第七层评测决定了你改完一个模块后怎么知道自己改好了还是改坏了。没有评测层RAG系统就无法持续演进。产品D给了一个很好的参考它内置了一套黄金问答集每次跑完都会输出命中率、正确率和无效回答率三个指标。我在自研时也模仿了这个做法用业务部门提供的典型问题建了一套两百条的评测集每次改动都会跑一遍看分数变化。4. 四个关键决策从拆解到复用的核心细节光有分层架构还不够实际写代码的时候有几个决策点会反复出现。这四个决策的认知基本决定了一个RAG项目是“能用”还是“好用”。4.1 分块策略固定窗口是最偷懒也最危险的选择把文档切块的方式直接决定检索质量。很多人图省事直接按固定token数量切比如每512个token一块。这种做法对付纯文本短文勉强能行但一碰到带结构的文档就很容易切出“语义残废块”表格被从中间截断标题和正文被拆到两个块的末尾和开头代码块中间被切断甚至一句话被分成两半导致检索时文本块的语义不完整。我综合六个项目后总结出的最优策略是“结构优先语义兜底”先把文档解析成结构化的中间格式优先按标题层级切块切不下去的地方再按段落切段落还太长就按句边界切并带上少量重叠。实测下来这种切法比固定窗口的检索命中率明显要好尤其是在企业知识库这种标题层级比较清晰的场景下。重叠窗口也有讲究。过度重叠会让索引体积膨胀、检索结果重复完全不重叠又会把跨段落的语义切断。我的经验是重叠一两句话就够了目的是保持上下文的连贯性而不是让同一个信息出现在几十个块里。4.2 混合检索向量不是唯一答案BM25依然能打向量检索擅长语义相似但它有一个明显的软肋对精确匹配不敏感。比如产品编号“P-1002-X”用户输入“P1002X”向量检索可能把它当成完全不同的东西但传统的BM25检索可以基于词面重合轻松匹配到正确文档。代码片段、型号、缩写、人名这些场景字面检索往往更可靠。产品E率先做了混合检索的示范产品B则进一步把混合逻辑抽象成了可配置策略。我自研时参考了它们的做法采用双通道方案向量索引负责找“意思相近”的块全文索引负责找“字面匹配”的块然后用一个合并函数把两边的分数归一化后再排序。这里有个容易踩的坑两种检索方式的分数区间不同不能直接相加。必须各自做归一化处理比如先转换成排名分或百分位分再做加权融合。权重怎么调呢我的经验是先跑一批评测集用网格搜索试几组权重取评测指标最优的那组。4.3 重排到底是不是必需环节在拆解时我注意到一个很有意思的现象产品A和产品E把检索结果直接拼给大模型产品B和产品D则留了重排接口其中产品D内置了轻量重排逻辑。重排的价值在于第一轮粗召回往往带回来几十个块如果全部放进Prompt一是超出上下文窗口二是数量太多会让模型注意力分散。先粗召回再精排可以把最相关的三到五个块选出来信息密度会高很多。但重排不是免费的。用大模型做重排成本太高不适合高频调用用专门的排序模型需要额外部署一个模型服务。我的建议是前期先用“向量分数 关键词分数加权”做轻量排序等评测数据积累到一定程度发现真的存在“信息相关但排序靠后”的问题时再引入重排模型。一上来就上重排常常是杀鸡用牛刀。4.4 知识组织元数据比图谱更早该到位产品E的图谱方案很炫但我在真正落地时发现图谱不是每个场景都需要。对企业内部文档来说更紧迫的是做好基础元数据管理文件来源、部门、作者、更新时间、阅读权限、文档类型、章节路径。这些元数据被存在每个文本块上检索时可以做结构化过滤比如“只查某个部门的文档”“只看最近三个月的资料”“排除敏感级别过高的内容”。图谱有价值的地方在于处理“多跳问题”比如“哪个项目经理负责我们采购的那套系统”这需要把项目、采购记录、负责人三条信息关联起来。如果你的业务场景经常出现这类跨文档串联式提问那可以在元数据稳定之后再渐进式引入实体抽取和图谱存储。我的建议是基础元数据永远先做。因为有了文档级别的过滤至少能解决权限问题和范围收敛问题这是图谱无法替代的。5. 真正落到生产环境后才暴露的坑分层结构和检索策略都是纸面设计真正让我把这些原则内化成本能的是跑数据时撞上的那些坑。下面四个问题基本是每个自研RAG都会遇到的。5.1 权限隔离不做好检索就是一场事故很多时候我们搭的RAG是面向内部多人使用的。不同部门、不同职级能看到的数据范围不同。如果不做权限隔离就会出现很尴尬的情况一个普通员工问“我们公司今年核心项目的预算是多少”系统从只允许高管访问的文档里检索出了答案然后光明正大地回答了出来。处理办法其实不复杂在索引阶段就给每个文本块打上权限标签在检索阶段先根据当前用户的权限集合做过滤再进入向量检索。如果权限集合很多还可以用位图或组ID的方式避免在千万级向量的集合上做逐条权限判断。权限字段的过滤必须在向量相似度计算之前完成否则效率会非常差。5.2 增量更新和删除开源项目里最少被写清楚的部分这些项目里做一次性索引的很多但把增量更新做扎实的很少。真实企业场景里文档每天都在变有新增的有被修改的还有被删除的。如果不处理增量就会出现系统回答里引用了已经无效的旧版本内容这是非常影响信任感的。我参考某几个项目的文档管理模块后做了一个文件状态记录表记录每个源文件的哈希值、文件路径、解析后的文本块ID列表。每次更新任务跑起来先扫描源目录对比哈希值发现文件变化就删除旧的文本块记录重新解析、重新索引。删除文件时则直接级联删除关联的文本块。这套机制不复杂但增量更新能力是RAG从演示走向生产的硬门槛。5.3 评测集是唯一能救你于水火的东西没有评测集RAG就是一台没有仪表盘的飞机。你改了一个切分参数、换了一个检索模型靠人工试问几个问题根本看不出优劣。产品D启发我最深的一点就是把“跑测试”做进代码流程里。我也建了一套评测集大概两百条带标准答案的问题分成了四类可以精确回答的、需要多文档综合的、语料里没有的用来测幻觉、以及多轮对话的。每次改动就跑一遍评测脚本对比前后两轮的指标变化而不是靠感觉。没有评测集你根本不知道自己是在改进还是在开倒车。5.4 成本控制嵌入计算不是一次性消费很多人忽略掉一个隐性成本嵌入计算。一个五十万字的文档库切成几万块每块都要调一次嵌入服务量一上来费用和等待时间都不小。自研RAG必须考虑增量嵌入调度新文档来的时候直接为新增的块算嵌入老文档没变就不重复算。还可以在离线低峰期批量跑嵌入任务避免挤占在线资源。另外一个常见的浪费是文档没有任何改动却因为程序重启导致所有文本块重新嵌入了一遍。加上文件哈希对比机制这种浪费就能避免。成本控制的核心思路就八个字能复用就复用能离线就离线。6. 一套可落地的自研最小实现路线最后我把拆解得到的东西收敛成一条实际可走的路线给已经被各种概念搞得眼花缭乱的人一个具体参考。6.1 技术选型的最小组合自研RAG并不需要一开始就上一套重型分布式系统。我的建议是文档解析和切分用Python写一个管道中间格式用Markdown或JSON方便调试。向量索引用一个支持元数据过滤并有Python客户端的开源向量库就够了。全文索引直接用带BM25能力的全文检索引擎专门承接字面匹配场景。元数据存储一个关系型数据库就行记录文件状态、文本块归属、权限标签。大模型服务调用通用模型API初期不必自己在GPU上调模型。评测和流水线用一套评测脚本加定时任务的调度方式把离线评测跑起来。这套组合的好处是每一层都可以独立替换。今天用的向量库不合适换一个不需要动其他代码今天想换嵌入模型只需要重新跑一遍离线嵌入。6.2 分阶段推进的时间表我倾向用四个阶段来推进每个阶段都有明确的验收标准否则很容易在“不断换新模型”这个坑里出不来。第一阶段跑通最简链路。用文档解析、结构切分、向量索引、Top-K检索加生成回答能对二三十篇文档做单轮问答就算成功。这个阶段的目的不是优化而是让整条链路完整可见。第二阶段建立评测集和增量更新。写两百条评测问题跑出第一版指标加入文件状态哈希对比让新增和修改的文档能自动同步。这个阶段结束后系统才具备了持续演进的地基。第三阶段做检索引擎升级。加入全文检索引擎做混合检索加上分数归一化和权限过滤这会让系统在真实业务数据面前变得可用。第四阶段做多轮对话和重排。引入查询改写逻辑再根据此前积累的评测数据决定是否加一个重排层。这一刻你会发现最初从开源项目里逆向出来的那张蓝图已经被你自己走完了一遍。6.3 我最后想分享的一点体会做了这么多拆解和落地后我最大的感受是自研RAG最关键的能力不是写代码而是判断哪一层需要自己写、哪一层可以借现成的。没有哪个开源项目能直接满足所有业务但它们的架构思路和模块边界才是真正值得逆向的东西。如果你的瓶颈是数据权限和格式那就重点借鉴企业级平台的设计如果你被多轮对话的指代问题困扰那就优先把查询改写和记忆层补上。照着这张蓝图做一遍之后你会发现RAG真正考验的是把每一个细节都打磨到位解析得更结构化、切分得更语义完整、检索得更精准、权限过滤得更严格。这些细节才是自研RAG和demo级RAG之间的分水岭。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑