
1. 先别急着写代码我为什么花两周做开源RAG的逆向工程上个月我们团队接了个任务给公司做一套内部知识库问答系统要求数据不出内网、能对接十几个业务系统的文档、还要按组织权限过滤答案。我最初的想法和大多数人一样——找个开源RAG框架部署起来两三天出demo。结果demo是真出了效果也是真惨PDF解析丢掉表格结构、召回内容张冠李戴、同一个问题换个说法就答不上来。后来我做了个让组里同事觉得纯浪费时间的决定先不开工花两周时间把主流开源RAG产品拆了个遍从架构到代码逻辑、从分块策略到重排接入全部逆向梳理一遍再动笔设计自研方案。事实证明那两周比我后面两个月的开发产出还要值钱。这篇内容就是我那份逆向工程笔记的整理版。我从RAGFlow、QAnything、FastGPT、Dify、LlamaIndex、Haystack这六款开源产品里提炼出一套可以复用的自研RAG蓝图包括模块划分、技术选型、参数参考、验收指标和避坑清单。它对标的场景很明确你正在做企业知识库或者准备自研RAG但又不想把坑都踩一遍。接下来每一节讲的都是我从开源产品里看到了什么设计逻辑映射到自研应该怎么做不堆概念只讲能落地的细节。1.1 demo能跑通不等于你的业务能跑通先说说我最初那版demo为什么翻车。当时我用的是最常见的教科书RAGPDF文本抽取、按500字符固定切块、注入向量库、TopK召回、拼进Prompt让大模型回答。跑通之后给业务同事演示他们随手丢进来三份真实材料一份带多级标题的招标文件、一份带合并单元格的产品报价表、一份扫描版的合同。结果招投标问题答串了章节报价表算数的时候引用了错误行扫描合同直接查不到内容。这个经历让我意识到Notebook教程和真实系统之间至少隔着四个断层文档形态断层——真实文档有版面、表格、图片、扫描件纯文本抽取等于把信息先丢一半检索效果断层——固定切块在语义相似度上会切碎完整句子和业务实体溯源要求断层——企业内部问答必须能点到原文位置而不是给一段脱离来源的生成结果评估方式断层——用三五个测试问题判断效果根本撑不起上线决策。出现这些断层的时候任何开源RAG框架都救不了你因为问题不在框架而在管线设计。要设计好管线最好的老师恰恰是那些解决过同类问题的开源产品。1.2 六款拆解对象清单我选它们各自图什么逆向工程的第一步是选对象。我没有盲目地把所有热门RAG项目都拉下来跑一遍而是按覆盖完整RAG生命周期的标准选了六款每款负责解决一个关键环节的问题产品开源协议以拆解时仓库LICENSE为准一句话定位我拆解它的目的RAGFlowApache-2.0深度文档理解驱动的RAG引擎文档解析、分块范式、知识图谱增强QAnythingApache-2.0两阶段检索RAG问答系统粗排精排工程实现、跨语言检索FastGPT早期Apache-2.0新版需核对仓库可视化知识库AI工作流编排复杂业务编排、对话记忆、工具调用Dify历史Apache-2.0新版为受限开源协议LLMOps应用开发平台知识库召回测试、迭代闭环设计LlamaIndexMIT数据框架与索引/查询引擎节点抽象、索引类型、查询变换HaystackApache-2.0组件化NLP/RAG流水线框架组件化、可测试性、评估管线这里有个很重要的提醒开源协议是会变的我今天写的是我拆解时看到的版本不代表永远不变。你自己拉代码的时候一定以仓库里那一刻的LICENSE文件为准后面第六节我专门讲协议边界。选这六款的原因也顺便说一下。RAGFlow解决文档进来之前的问题QAnything解决怎么找得准的问题FastGPT解决多个能力怎么串成业务的问题Dify解决上线以后怎么持续迭代的问题LlamaIndex解决索引和查询类型怎么设计才完整的问题Haystack解决系统怎么拆才能测、能换的问题。六款串起来正好覆盖一条完整的自研RAG闭环。1.3 逆向工程的正确姿势从输出反推输入而不是逐行读源码很多同学拿到开源项目就一头扎进源码从main函数开始跟着调用链走结果往往是看三天代码、记了三页笔记、最后啥也没干。我的做法是反过来的分成四步第一步先看文档和README里的设计目标。每个优秀的开源项目都会在文档里写我为了解决什么问题而生这是最值钱的信息。例如RAGFlow明确说自己的重点是深度文档理解QAnything强调两阶段检索看到这两句话你就知道它们的代码里一定有对应的核心模块。第二步跑起来给真实文档打断点。我会用docker-compose把项目拉起来喂进去一份带表格、带多级标题的真实业务文档然后盯着日志和数据库观察文档被解析成了什么结构、分块后每块长什么样、召回时检索词做了什么变换、最后进入Prompt的上下文是哪些块。第三步只读关键模块。不需要通读全仓库重点看三块分块/解析相关的代码、检索链路query怎么变换、召回什么、怎么重排、以及知识库与对话之间的接口。其他部分比如前端、用户系统直接用结论跳过。第四步做对照实验。我会把开源的默认参数改掉比如把分块方式从固定长度改成按标题层级跑同一批测试问题对比召回率变化。这一步最能理解设计者为什么当初选了这个方案。这套方法的本质是先用输出反推输入再用实验验证假设。两周下来我对RAG的整套设计取舍有了自己的判断而不是停留在会用某个框架的层面。2. 逐款拆解六款产品各自帮我解决的最后一公里问题2.1 RAGFlow文档解析和分块本质是还原版面的语义结构RAGFlow是我第一个拆的也是收获最大的一款。它的核心卖点是深度文档理解实际体验下来确实不是营销话术。它对PDF的处理不是简单调一个pypdf抽文本而是用版面分析模型把页面划分成标题区、段落区、表格区、图片区再做OCR和表格结构还原。这一步做完PDF里的多级标题、合并单元格、脚注都被识别成带结构的块而不是一锅乱炖的字符串。对我冲击最大的是它的模板分块设计。你可以不按固定字数切而是按文档语义结构定义切分规则按一级标题切、按二级标题切、按表格切、按问题-答案对切。每个chunk还带着它在原始文档中的位置引用问答时可以回跳到原文页面。这直接戳中了我前面说的溯源要求断层。自研我怎么抄这个设计一句话把载入解析从管线里的一个小步骤提升为一级基础设施。具体来说自研管线里必须有一个独立的解析层PDF统一走版面分析OCR表格识别输出统一的中间格式我用的是带块类型标签的Markdown而不是一把文本丢给分块器。业务文档里大量信息藏在版式里解析这步做到位后面所有步骤都能变简单。2.2 QAnything两阶段召回精排是把找得到变成找得准QAnything来自网易有道主打中文场景的企业文档问答。它最核心的设计是两阶段检索第一阶段用双编码器模型embedding做粗召回把候选从百万级压到一百条左右第二阶段再用交互式重排模型cross-encoder做精排把语义相关性真正算准从一百条里挑出最相关的三五条进入生成。为什么要两段因为embedding向量相似度本质上是压缩后的语义距离它擅长表达大概相关但会对同义词、否定词、数字细节非常不敏感。而重排模型是把查询和候选文本拼接起来一起过模型能捕捉到字词级别的精细交互。前者保证广度后者保证精度缺一不可。我实际验证过这个设计在相同测试集上只用向量召回Top5的命中率Hit5大约在62%加了一百取五的精排之后命中率能拉到85%以上。这个收益不来自更换embedding模型纯粹是管线结构带来的。自研直接借鉴召回阶段宁可多召回也要把候选池放大到50到100条然后交给重排模型收敛到5条。后面第五节的成本控制我还会细说。2.3 FastGPT把RAG编排成工作流才谈得上复杂业务FastGPT让我换个角度看RAG它本质上不是一个检索生成的函数而是一个可以被编排的工作流。它提供了可视化的编排界面知识库检索是一个节点问题理解是一个节点条件判断是一个节点AI对话是一个节点你甚至可以在流程里插HTTP请求、代码执行、多轮对话记录模块。过去我认为RAG的架构就是召回再生成一条线走完看完FastGPT我意识到真实业务场景里从来没有这么简单。企业内部的知识库问答至少要面对三类变体有些问题要先判断属于哪个知识库再检索有些问题需要先做术语归一化再查询有些问题要给不同权限的用户返回不同范围的上下文。这些问题靠一条线性管线解决不了必须引入编排层。自研蓝图里我把这个经验落地为节点化设计检索、重排、上下文压缩、生成、记忆管理都做成独立节点外部用一套可配置的工作流把它们串起来。第一版甚至可以简陋到用配置文件描述流程顺序但架构上绝不能把逻辑写死在一个process函数里。等业务复杂了你自然会有把流程可视化、可拖拽的那一天而节点化设计让你不必返工。2.4 Dify召回测试和迭代闭环是知识库能落地的方向盘Dify严格说是一个LLMOps平台不只做RAG。但它的知识库模块有一个细节我特别服气——内置了召回测试。你在Dify里创建一个数据集、导入文档、设置分块和检索模式之后可以在调试界面输入任意query立刻看到命中了哪些chunk、每个chunk的相似度打分是多少还可以切换向量检索/全文检索/混合检索做对比。这一步看似不起眼实际上是把RAG调优从玄学变成科学。拆Dify之前我调优RAG的方式是改参数、跑几个问题、用眼睛看答案好不好。这种方式的致命问题是你永远不知道是分块出了问题、embedding出了问题、还是重排阈值出了问题。Dify逼着我建立了一套迭代闭环先测召回再评估生成最后才改Prompt。自研的时候我抄了这个设计专门做了一个检索调试台内部工具输入query左侧显示向量召回结果右侧显示全文召回结果中间显示混合融合后的排序每个chunk标注来源文档和得分。团队后来调优全靠这个工具效率完全不一样。这个经验我放到第四节的蓝图里属于必做项而不是加分项。2.5 LlamaIndex索引类型和节点粒度决定RAG的能力上限LlamaIndex是一个数据框架不是开箱即用的产品但它把RAG底层的数据抽象做得极其完整。它的核心概念是Node节点一个chunk不是孤立的文本片段而是文本元数据节点关系的三元组。元数据可以存文档ID、章节路径、页码、文档类型节点关系可以记录这个句子属于哪个段落这个段落属于哪个章节。基于这套节点抽象LlamaIndex提供了一堆索引类型向量索引适合语义查找、关键词表索引适合精确匹配、知识图谱索引适合多跳关系查询、结构化表索引适合属性过滤。查询的时候还有一堆变换手段MultiQuery把用户问题改写成多个变体再查、HyDE先让大模型生成一个假设答案再拿去检索、QueryRewrite基于历史对话重写问题。让我最受益的是句子窗口检索这个模式检索的单元是细粒度的句子召回命中句子节点的同时把它的父级段落一起捞出来送给大模型。这样既保证了召回的精确性又保证了上下文完整性。自研蓝图里我直接把父子节点机制定为标准底层存细粒度子节点用于召回上层保留粗粒度父节点用于生成上下文。这种设计让召回准和上下文全不再互斥。2.6 Haystack组件化流水线让RAG可测试、可替换、可灰度最后一个拆的是Haystack。它对RAG最大的贡献是把整条链路变成了一套有类型约束的组件化流水线每个组件声明自己的输入输出类型组件之间按DAG连接框架负责调度的同时保证每个组件可以被单独替换和单独测试。这个可测试性到底多重要你可以想象一个场景把embedding模型从旧版换到新版如果整个链路是耦合在一起的你根本分不清指标变化是embedding的原因还是重排器的原因。Haystack的组件隔离让我把每一个环节都变成了独立变量retriever单独测、reranker单独测、prompt builder单独测。任何改动都可以回归任何线上问题都可以定位到具体环节。自研架构里我借了它的三样东西第一每个核心环节必须有标准输入输出接口例如召回节点的输出永远是一个带统一字段的chunk列表第二每个环节必须可以被单独运行和记录日志第三整条链路必须支持管线复制做灰度——线上稳定版本和新版本并行跑流量比例可调对比效果后再全量切换。这三点让RAG系统从一个会跑的程序变成一个可以长期维护的服务。3. 六款产品收敛出的四个共性也就是一切自研RAG的地基拆完六款产品我发现虽然它们的外壳差异很大——有做平台的、有做框架的、有做知识库应用的——但底层设计收敛度极高。把共性抽出来就是自研不该走弯路的四根地基。3.1 五段式管线是共识解析、分块、索引、召回、生成任何RAG系统不管文档怎么吹最终都能映射到这条链路上载入解析 → 分块净化 → 索引入库 → 召回过滤 → 生成溯源差异只在于每一级做得深不深。RAGFlow把所有精力投入到前两段解析深度拉满QAnything把精力压在第四段用两阶段检索做精细召回Dify在第五段前后加了测试和迭代工具FastGPT在管线之外加了编排层LlamaIndex把第二段和第三段的抽象做得最完整Haystack则确保每一段都可插拔。这条五段管线对自研最大的意义不是让你照着画架构图而是统一团队的讨论语言。每次业务反馈效果不好第一件事不是改Prompt而是先问问题出在第几段是文档没解析出来第一段还是分块切碎了表达第二段还是召回没捞到正确答案第四段还是大模型没按提供资料回答第五段。这个定位习惯养成之后优化效率是天壤之别。3.2 元数据不是附加项是权限和溯源的命脉六款产品里凡是做得成熟的都对chunk的元数据极其较真。RAGFlow每个chunk带了文档位置引用Dify把文档ID、数据集ID贯穿全程LlamaIndex更是把元数据设计成了Node的核心属性。我自己的踩坑经历也印证了这一点。第一版自研系统里chunk只存了文本和向量上线之后产品经理提了两个需求直接把我打懵了第一搜索结果能不能按部门权限过滤比如销售部看不到法务部的文档第二答案里能不能附上原文链接方便用户点过去核对。这两个需求本质都需要同一件东西——每个chunk上带着足够丰富的元数据。所以自研蓝图里我把元数据定义为chunk的强制字段最少包含doc_id、page_no、section_path章节路径、title、chunk_type段落/表格/列表/公式、source_uri原文地址、hash内容哈希用于增量更新、acl_tags访问控制标签。有了这组字段权限过滤、溯源展示、增量更新、按章节精确召回全都能实现。3.3 纯向量检索终究只是基线混合检索重排是标配拆完六款产品我发现一个让人惊讶的事实没有一款生产级的开源RAG敢只依赖纯向量检索。至少是向量全文/关键词双路召回再往上就是加知识图谱和重排。为什么纯向量不够我举一个很典型的例子企业文档里有大量产品型号和编号比如BS-2000A型传感器向量相似度想找到它并不难但如果你要查二零零零A型的防水等级常规向量模型很可能把二零零零A型当成一个整体编码而全文检索可以直接命中2000A这个子串。反过来向量检索擅长处理同义改写问题比如设备坏了怎么报修可以检索到故障报修流程这是关键词检索做不到的。两者是互补关系不是替代关系。自研标配我定为向量召回 BM25/全文召回 RRF融合 重排模型精排。融合算法最省事的就用RRF倒数排名融合不依赖分数绝对值只依赖排序位置稳定且不容易被各路的分数尺度带偏。重排模型再在融合结果上做最终精排保证进入LLM的上下文是真正相关的Top5。3.4 库的粒度学问RAG知识库、向量库、KG知识库、结构知识库各管一段拆开源产品的过程里我还顺带整理清楚了一个被很多人绕晕的问题RAG知识库、向量库、知识图谱KG知识库、结构化知识库到底什么区别、各自用在什么场景。这个区分直接影响自研蓝图的存储层设计。类型数据形态建立成本擅长解决的问题典型短板RAG知识库非结构化文档Word/PDF/HTML较低文档问答、客服、制度查询数值精确性和多跳关系较弱向量库文本向量化后的稠密向量低语义相似度检索是RAG的底层存储只存向量理解不了业务关系KG知识库实体与关系的图结构高多跳关系、组织机构知识、实体关系构建维护成本高稀疏时召回率低结构化知识库表格、SQL、Excel指标中精确指标、参数查询、统计口径语义自然语言难直接查询把这四类库区分清楚之后蓝图才真正成形不能用一套向量库解决所有问题。文档问答走RAG知识库精确指标查询走结构化库实体关系走知识图谱向量库只是RAG知识库的底层组件。设计时还要注意很多自研团队一上来就买一张大知识图谱结果构建成本爆表、问答效果却不升反降——这个坑我在5.4节专门讲。4. 可复用的自研蓝图一套从MVP到生产级的三级演进方案接下来是全文最实操的部分。我把逆向工程得到的设计落成了一套可以照着搭的三级演进方案。每一级都能独立上线不要想着一步到位。4.1 第一级一个月跑通的最小可用RAG第一级的目标不是效果好而是让整条链路完整落地、有接口、有日志、有基本的溯源能力。这个阶段我建议的组件选型如下文档解析文本型PDF用pypdf或pdfplumber抽文本扫描PDF先接PaddleOCR做OCRWord用python-docx转纯文本HTML用BeautifulSoup抽正文。所有解析结果统一归一化成Markdown风格再进入下一级。分块先用按段落标题切分替代固定长度切分段落太长的再按句子边界二次切开块大小控制在512个token左右重叠10%~15%。嵌入中文场景先选开源的bge-large-zh-v1.5或bge-m3这两个模型对中文业务文档的泛化能力经过大量验证。向量存储最省事的方案是PostgreSQL的pgvector插件不引入额外组件复用已有数据库。检索先做纯向量TopK召回K设20。生成把Top20重排或直接取前5条塞进Prompt要求模型只依据提供的chunk回答并标注引用序号引用指向chunk元数据里的source_uri。这个阶段必须要做对的一件事是每个chunk的元数据从第一天就填完整。后面所有权限、溯源、增量更新都依赖它补课的成本远高于第一次就做好。做完这一级你已经有了一套能回答简单文档问题、且答案能溯源到原文的知识库系统。4.2 第二级生产可用的混合检索RAG第二级解决的是召回质量问题这是从demo走向生产最难啃的一关。引入全文检索用Elasticsearch或者PostgreSQL自带的tsvector全文索引做BM25召回。对中文记得配好中文分词器企业场景里搜型号、编号、法条引用靠的都是全文检索。引入RRF融合同一路query分别在向量检索和全文检索里各拿50条候选用RRF合并排序再取Top50进入重排。引入重排加一个cross-encoder模型我用的是bge-reranker-large。重排输入是query候选chunk的拼接对输出相关性分数取Top5进生成。这一步的效果我在2.2节量化过值得上。引入query改写在企业场景里同一个实体往往有多种表述。可以在检索前加一个可选的改写节点用小模型把用户问句改写出2到3个变体比如补充同义词、展开缩写每个变体单独召回再融合。引入父子节点细粒度子节点用于召回命中后把对应的父级段落展开进上下文避免召回准但上下文碎。做完这一级系统的召回链路变成了改写→双路召回→RRF→重排→父子展开→生成这是我认为生产级RAG的通用标准形态。它不会让你的RAG在每个场景都完美但它能保证大部分情况下“找得到、找得准、答得全”。4.3 第三级面向领域深水区的知识图谱增强RAG第三级不是必选项只有当你发现文档问答里大量出现多跳关系和术语一致性问题时才需要上。它的核心是引入KG知识库和ontology机制对应最近讨论比较多的ontology RAG方向。知识图谱的构建路径选一个高价值的小领域起步比如设备维修或合同条款关系统。用规则抽取LLM抽取双轨做实体和关系抽取规则负责抽固定字段合同编号、人名、日期LLM负责抽开放关系。图谱存储用Neo4j查询时先做实体识别命中实体后走图查询拿到关联路径把路径转成自然语言文本作为检索上下文补充。ontology的作用比图谱本身更值得优先做企业里有大量术语别名问题——设备机器装置可能指同一个对象验收标准和验收条件是一条东西。ontology机制建议做成一个术语归一化前置节点维护一张规范术语表每个规范词挂一堆别名query进来先用这个表做归一化对齐再进入检索链路。这一步成本极低、收益极高在很多垂直场景的命中率提升比换embedding模型更明显。路由策略第三级不要把所有知识源混在一起全量召回而是设计一个简单的query路由器先判意图涉及精确指标走结构化库涉及实体关系走图谱涉及开放问题走文档向量库多个意图命中时分支召回再汇总。这个路由可以是规则也可以让小模型做分类关键是不要让图谱查询拖慢普通问题。4.4 每个阶段的验收指标没有评估集就没资格谈优化我可以负责任地说大部分RAG系统做不好不是因为技术选型错了而是因为从头到尾没有建立评估集。没有评估集你改任何参数都无法判断是变好还是变坏最后只能靠感觉靠感觉必然返工。自研蓝图明确要求第一天就建评估集。评估集建议包含三类数据检索评估集——50到200条真实用户问题每条标注一个或多个正确答案对应的chunk/文档生成评估集——同样的问题配上标准答案和关键得分点边界问题集——故意放进去的问法歧义问题、多跳问题、无相关问题用来测系统的拒绝能力和兜底能力。核心指标我固定用这几个并且写进了CI指标定义建议目标Hit5正确答案是否出现在召回Top5≥85%MRR第一个正确答案在排序中的倒数排名≥0.75忠实度生成答案是否完全基于召回内容≥90%人工抽样引用覆盖率答案是否带可溯源的引用标记≥95%拒答率无答案问题是否正确拒答边界测试集≥80%有了这套指标后面每次参数调整都跑一遍回归两周一次的迭代节奏跑起来RAG效果是能看得到地在变好的。没有这套机制再先进的蓝图也是空谈。5. 落地过程中我踩过的五个深坑和保下来的经验蓝图归蓝图真正落地的时候坑比预想的多。挑五个最影响结果的分享出来都是我拿真实数据撞出来的。5.1 分块参数不是拍脑袋是召回率和上下文窗口的函数网上教程普遍告诉你分块500字、重叠50字这个数值在很多场景能跑但离最优解很远。我的实测经验是分块大小和文档类型强相关。操作手册类文档切成512 token效果最好因为每个步骤相对独立长合同和招标文件按标题层级切块并保留章节路径效果最好固定长度反而会切断条款之间的引用代码文档和配置说明要切成小粒度的128~256 token配合父子节点展开。重叠比例我也做过对照实验10%~15%是甜点区太高的重叠率会带来大量冗余候选重排负担变大收益却很小。真正决定分块质量的不是参数而是切分边界是否符合语义边界——一句话拆两半、一个表格被拦腰截断再调参数也救不回来。所以我的口诀是优先按语义结构切语义结构不清晰的再按句号、换行符兜底最后才退到纯长度切分。5.2 Embedding模型的选择权重大于向量库别本末倒置很多人选型时纠结用Milvus还是用Qdrant却随手用一个embedding模型。这是本末倒置。向量库只影响查询速度和海量数据的扩展能力embedding模型才真正决定语义理解能力也就是你能不能把怎么报修和故障申报流程关联起来。索引再快embedding理解不了语义召回结果就是垃圾进垃圾出。我的建议是先用自己领域的数据做一个小的embedding模型评测而不是直接用公开榜单的结果。做法很简单——拿50个真实query每个标注正确的chunk把候选模型各自跑一遍召回看Hit5。中文企业文档场景里bge-m3、bge-large-zh-v1.5是我实测综合表现稳定的第一梯队m3e在短文本场景也不错。评测的时候记得看两个容易被忽略的点一是领域专有词型号、人名、系统名的处理能力二是长文本超过512 token时会不会信息坍缩。向量库方面起步用pgvector向量规模到千万级别再考虑迁到Milvus或Qdrant不要在早期过度基建。5.3 重排要控成本先精排Top50而不是全量精排cross-encoder重排模型效果好但它是把query和每个候选拼接起来过一遍完整模型计算成本比embedding检索高一个数量级。如果你有100万条文档每次都全量精排GPU都扛不住。业界通用的解法就是我在第二级里写的级联先靠廉价的双路召回把候选压到50条只对这50条做精排。这样既拿到了重排的精度红利又把成本控制在一个可接受的范围。控制成本的另一个技巧是缓存同一query在窗口期内的重排结果直接复用。企业内部很多问题是高频重复的缓存命中率往往不低。如果QPS压力还大再退一步把重排池从50降到20或者换小尺寸重排模型直到满足延迟预算。另外切记一点重排只能调整顺序不能找回被粗排阶段丢掉的内容。所以粗排的TopK宁可大一点别为了省事把候选池压到10条以下那样重排模型再强也救不回来。5.4 知识图谱别为了时髦而上只有这三种场景值得我见过很多团队看到RAG知识图谱很热门就立项上图谱结果构建半年、成本几十万、问答效果还变差了。对照我拆的RAGFlow等产品的做法知识图谱只在三种场景下真正值得第一种是多跳关系查询。比如哪些供应商同时供应了A项目的原料和B项目的包装这类问题靠文档向量检索几乎答不了因为答案分散在多个文档里需要靠实体关系串联起来。第二种是术语一致性场景。企业文档里同一个对象叫法五花八门建立实体图谱天然就是把别名映射到规范实体的过程配合ontology术语归一化能明显提升召回稳定性。第三种是高价值长尾实体检索。比如大量产品型号、人员姓名、合同编号关键实体在图谱里有精确索引查询时可以走实体精确匹配不再依赖模糊的向量相似度。如果不是这三个场景老老实实做混合检索就够了。就算要上图谱也按4.3节说的先选一个小领域做试点用数据验证收益再扩展。千万别一上来就全量文档抽图那是自找项目延期。5.5 多模态问题RAG知识库到底能不能存图片有网友问RAG知识库能存储图片吗这个问题我在自研时也遇到过。答案是能但要分两层理解。第一层是把图片作为一个带说明的节点存进知识库。实际操作是图片内容先用VLM视觉语言模型或OCR转成文字描述这段描述作为chunk的正文图片路径放进元数据的attachments字段。检索命中这个chunk返回答案时可以附带展示图片。这套方案实现成本低适合“教程文档里有截图”“产品说明书里有示意图”这类大多数场景。第二层才是真正的图片语义检索也就是用户输入自然语言直接匹配图片内容本身比如给我找一张有红色警报标识的结构图。这需要多模态embedding模型类似CLIP把图片和文本投射到同一个向量空间。正经的企业自研场景我建议先做第一层见效快、模型选择多、GPU压力小。多模态向量模型目前的中文业务文档效果还不够稳定盲目上全图检索大概率会让召回方差变大。特殊格式也提一句Excel多sheet文档不要整体切块按sheet名称表头数据行区域拆每块单独存元数据语音和视频先转写文本再进RAG转写结果和原始时间戳一起存方便溯源。6. 开源与自研的边界什么该借、什么必须自己写最后聊一个很现实的问题。既然开源RAG产品已经这么优秀为什么还要自研又要怎么处理和开源代码的关系6.1 许可证是红线也是自研合法性的来源拆解开源产品没问题但在自研里使用它们的代码必须先弄清许可证边界。我拆解时看到的情况是LlamaIndex是MIT协议RAGFlow和QAnything是Apache-2.0Haystack是Apache-2.0这三类协议对商用和修改都很友好保留版权声明即可。Dify的新版本改成了受限开源协议FastGPT的版本协议也需要逐个核对部分版本对以多租户形式提供同类服务有限制。务必以你拉取代码那一刻的LICENSE文件为准。这里有一个实操细节如果只是参考了设计思路比如我也要做两阶段检索我也要建父子节点这属于思想层面的借鉴不涉及代码版权放心做。如果直接复制或翻译了开源代码段就要遵守对应协议Apache/MIT项目要在代码注释里保留原版权声明。我自研时的做法是分块、重排、融合这类通用逻辑自己写OCR、表格识别这类底层能力直接以库依赖的方式引入PaddleOCR这类开源库本就是为被集成设计的两不越界。6.2 该借的解析思路、分块策略、提示词模板、网关封装自研RAG不是一个从零发明的东西它的每个环节业界都有成熟解法。该借的我列了一份清单文档解析思路版面分析、OCR、表格结构识别这套思路直接参考RAGFlow的DeepDoc模式工具直接用开源库不要自己造轮子。分块策略按语义结构切块、父子节点、句子窗口检索这些设计直接采用LlamaIndex验证过的范式。两阶段检索粗召回精排的管线结构直接从QAnything抄方案。召回测试台Dify内置的检索调试交互自研时照搬产品思路做内部工具。RRF融合与query改写混合检索的标准件直接用成熟实现不值得自己发明。这一部分借用的是标准答案价值在于让你少走弯路。它们的共同特点是通用、无领域属性、造轮子没有额外收益。6.3 必须自研的领域Schema、权限模型、评估逻辑、业务编排真正的护城河在下面四块开源产品不会替你解决也解决不了领域Schema。你的组织架构、术语表、文档分类体系、指标口径这些必须自己建模。比如我做的项目里文档要按制度-流程-模板三层结构组织查询时要先判断属于哪一层这是任何开源框架都没法开箱即用的。权限模型和合规要求。数据不出内网意味着所有组件都必须在私有环境部署embedding模型和重排模型也必须选可私有化版本。chunk级权限过滤的tag体系需要跟公司统一身份系统对接这是自研RAG一个很大的隐性成本也是不能外包的部分。评估逻辑。通用开源评估比如faithfulness只能当辅助参考真正有效的评估集必须从你的业务问题里来标注也必须是懂业务的人来做。这个工作开源社区做不了它本质上是业务知识的数字化。业务编排和体验。把RAG嵌入到具体业务流——比如工单系统里自动带出历史相似工单、审批系统里自动引用相关制度条款——这些都是系统集成工作开源项目提供的通用API只能当底座上层逻辑必然自研。6.4 自研的开局脚手架目录结构和第一周节奏最后给一份我留下的脚手架目录结构你可以直接当模板用rag-core/ loader/ # 文档解析PDF/Word/HTML/Excel → 规范化文本 chunker/ # 分块语义分块、父子节点、表格分块 embed/ # 向量化模型封装、批处理、维度管理 store/ # 存储pgvector/Milvus/Elasticsearch 抽象层 retriever/ # 召回向量全文RRF融合query改写 rerank/ # 重排cross-encoder封装、成本控制 generator/ # 生成Prompt模板、引用溯源、上下文压缩 orchestrator/ # 编排节点化工作流、状态管理 evaluator/ # 评估检索指标、忠实度、回归测试节奏上我建议三周一个里程碑第一周做loader和chunker用一批真实文档跑出结构化的中间产物先不开向量库第二周做retriever和rerank用检索评估集验证Hit5是否达标第三周接generator和evaluator把生成和评估闭环跑通。记住一开始就把评估集建起来这比任何组件都重要。自研RAG这件事我现在的体会是它并不是重复造轮子而是把轮子每个受力点摸清楚以后再按自己的车轴去造。开源产品是绝佳的教材但企业落地时真正决定成败的永远是领域数据、权限体系和评估闭环这三件事。希望这份逆向工程笔记能让你少走我走过的弯路。