ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

拆解六款主流开源RAG,提炼自研企业级知识库蓝图

拆解六款主流开源RAG,提炼自研企业级知识库蓝图 做 RAG 这行的人迟早都会面临一个选择直接用开源框架还是自研一套。我自己的答案比较折中——先把开源项目当成“免费的需求说明书”拆一遍再决定哪些复用开源、哪些自己写。最近我花了三周多时间把 LangChain(LangGraph)、LlamaIndex、Haystack、Dify、FastGPT、RAGFlow 这六款主流开源 RAG 项目的源码、文档、接口和产品交互全部过了一遍边拆边对比最后整理出了一张可以复用的自研 RAG 蓝图。这篇文章就是这次逆向工程的完整记录包括我怎么选型、拆了哪些层、提炼出什么共性结构以及落地时最容易踩的坑。如果你正在评估开源方案或者准备自建企业级 RAG 知识库这篇文章应该能让你少走不少弯路。我先把丑话说在前面开源 RAG 没有银弹任何项目都有明显的短板。但它们的架构却惊人地一致。把六款产品放在同一张表里对照你会发现真正拉开差距的不是有没有 RAG而是解析层做到什么深度、检索层有没有混索和重排、有没有可观测的评测面板。这三点恰恰是自研时最容易被砍掉、也最不该砍掉的部分。1. 为什么是这六款选型逻辑与分析方法1.1 六款产品的真实定位差异很多人一提到“开源 RAG”第一反应是“那不就是 LangChain 吗”这种印象其实会严重误导自研方向。LangChain 和 LlamaIndex 是编排框架给你的是积木Dify 和 FastGPT 是应用平台给你的是成品Haystack 和 RAGFlow 则更偏生产级组件。六款产品根本不在同一个抽象层但它们的核心组成几乎一一对应。我把这六款选进来就是想让“框架派”和“平台派”互相印证看看哪些模块是所有人都不敢省的。产品形态技术栈我最关注的部分LangChain / LangGraph编排框架Python / TSRetriever 抽象、Agent 编排、文档加载器LlamaIndex数据框架PythonNodeParser、Index 结构、Workflow 事件机制Haystack生产级框架PythonPipeline 可评测性、DocumentStore 抽象Dify应用平台Python / 前端知识库分段策略、召回测试面板、Agent 节点FastGPT应用平台TypeScript / Node父子分块、混合检索、工作流编排、分享知识库RAGFlow深度解析平台PythonDeepDoc 版面解析、表格抽取、模板问答我拆开源项目时有一个习惯动作先跑起来再按“输入一句话看它走完哪些环节”的方式去读源码。这种方式比从 README 开始读有效得多因为 README 告诉你的是作者想让你知道的而调用栈告诉你的是系统真正在做什么。1.2 逆向工程拆解清单我会给每个项目固定九个维度做分析文件接入层、内容解析层、分块策略、向量化模型、索引结构、召回方式、重排方式、LLM 调用与提示词模板、评测与可观测性。表格填完以后共性和差异自然浮出来。这个拆解清单不是拍脑袋定的它背后对应着 RAG 的一条完整数据流文件进来以后先要能读进来这是接入层读进来以后要能变成干净的文本或结构化内容这是解析层内容太长要切段这是分块层切完要转成向量这是向量化向量要存进去这是索引用户提问时要把相关片段捞出来这是召回捞出来可能有噪音要重新打分这是重排最后把片段和问题一起丢给大模型这是生成。六款产品无论包装得多花哨底层都是这条流水线。你把流水线每一个工位对应的代码模块找出来这个项目在你眼里就没秘密了。2. 六款产品拆出的通用架构骨架2.1 接入与解析Loader 不是玄学六款产品无一例外都有“Loader”的概念。LangChain 里叫 DocumentLoaderLlamaIndex 里叫 ReaderDify 和 FastGPT 是后端上传自动解析RAGFlow 则干脆把解析做成了独立的 DeepDoc 服务。虽然名字不同但职责一致把五花八门的文件格式统一成“文档 元数据”的内部结构。这里有一个很容易被忽视的结论解析层的深度决定了 RAG 效果的上限。我拿一份双栏 PDF 做过对照实验用简单文本抽取的方案正文和页脚完全混在一起检索出来的片段全是乱序文本用带版面分析的方案比如 RAGFlow 的 DeepDoc 思路先识别阅读顺序再按标题层级切块召回质量明显高了一个档次。原因不难理解——RAG 的检索单元是“块”如果块本身是从混乱文本里切出来的后面向量化、召回、生成全是沙地上盖楼。很多人问“RAG 知识库能存储图片吗”我的实测结论是能存但要看你怎么存。六款开源产品里没有一款是上传图片后“天然可搜”的。图片要进入 RAG 链路走的是两条路一是解析层把图片里的文字 OCR 出来、把图表用多模态模型描述成文本再当普通文本块处理二是图片单独做视觉向量索引用多模态 embedding 模型生成向量。前者是六款产品的主流做法后者还没有成熟到可以直接抄。所以如果你有大量图片知识库需求自研时要重点投入解析层的 OCR 和多模态描述能力而不是幻想用户直接搜图就能命中。2.2 分块策略决定 RAG 上限的一步解析完就能切块了。六款产品的分块策略看起来百花齐放实际归类后就四种固定长度切分、递归结构切分、语义聚合切分、父子块切分。固定长度切分最粗暴按字符数加 overlap 硬切LangChain 的split_text就是这么干的。优点是快、可控缺点是会把一段完整语义拦腰截断导致召回时拿到半截上下文。递归结构切分是先在段落、句子、标点等层级上逐级切能保留更多自然语义边界。LlamaIndex 的SentenceSplitter和 LangChain 的RecursiveCharacterTextSplitter本质上都是这个思路。语义聚合切分稍微进阶一点先把文本切成句子用 embedding 算相邻句子的相似度低于阈值就断块。这个方案我用下来效果确实好但计算成本也高适合离线建库场景。父子分块是我个人最推荐的一套设计也是 FastGPT 的默认风格父块是完整章节负责提供上下文子块是更小片段负责进入向量索引做召回。检索时先命中子块再回溯到父块喂给 LLM。这样既保证查得着又保证答得全。关于“本地的 RAG 文本拆解工具”如果你想在自研链路里快速补上这块能力不需要自己从头写。Unstructured、textract、tika 这类开源解析库都能做本地拆解PDF 版面恢复可以优先看 RAGFlow 的 DeepDoc 思路纯文本按 Markdown 标题层级切块则可以参考 LlamaIndex 的 MarkdownNodeParser。我的建议是分块逻辑一定要做配置化别写死在代码里因为你永远不知道下一批文档长什么样。2.3 索引与存储metadata 才是灵魂分块完成以后文本块要进入索引。六款产品的索引结构同样有共性没有哪款只用纯向量索引。纯向量索引的问题是关键词命中能力弱比如用户问“2024 年报里的利润率”向量检索很可能会找出“2023 年报里的利润率”因为语义太接近。所以开源项目普遍加了 BM25 或全文索引把向量召回和关键词召回的结果融合起来。融合方式最常见的是 RRFReciprocal Rank Fusion倒数排名融合把两个检索结果各自的排名倒数加起来重新排序。实现只有十几行效果提升却非常明显。Dify 和 FastGPT 都做了混索的开关默认推荐开启就是这个原因。存储层面我要强调一个从六款产品里反复验证的经验metadata 比向量本身更重要。你存进向量库的不该只有文本和向量还应该有来源文件、页码、章节标题、段落层级路径、标签、权限范围等字段。这样检索结果返回时你能告诉用户“这段话来自某个文档的第三节”LLM 生成时也能带着来源引用降低幻觉风险。自研时metadata 的 schema 设计一定要在项目第一天就定好不然后面迁移比写代码还痛苦。说到这里绕不开 GraphRAG 和 Ontology RAG 这些衍生路线。LlamaIndex 里有PropertyGraphIndexLangChain 生态也有 GraphVectorStore本质是在文档实体之间建关系边再配合向量检索做多跳扩展。它们解决的正是“知识割裂”问题当答案分散在多个文档、需要跨文档推理时纯向量召回很难串起来而图结构天然擅长多跳关联。但代价也很大实体抽取的精度、图构建的成本、查询链路的时延全都是坑。我的态度是如果你的场景是“一个知识库内查明确答案”先不要上 GraphRAG如果你的场景是“跨多文档写综述、做关系推理”再认真考虑。2.4 检索与重排从 TopK 到 Hit Rate 的优化链路检索环节六款产品的标配是两级第一级召回第二级重排。第一级召回用 embedding 模型算相似度配合关键词搜索先从向量库里捞出 TopK 候选。这里有个非常常见的工程误区TopK 设得太小比如默认 3 或者 5很可能正确答案根本不在候选集里重排再强也救不回来。我在对照实验中把 TopK 从 10 提到 20Hit Rate 提升了将近 8 个百分点。第二级重排用一个更强的模型对候选集重新打分。开源里常用的是bge-reranker系列效果好、部署成本低自研时优先考虑。重排的作用很直观向量相似度高的片段未必是用户真正想要的而 cross-encoder 模型能同时看问题和片段做更精细的匹配判断。Dify 的召回测试面板里会显示每段内容的命中得分FastGPT 也有搜索测试页面这些设计自研时都值得抄。评测指标我建议大家少盯着“准确率”多盯三个数字Hit Rate检索结果中包含正确答案的比例、MRR正确答案在检索结果中的排名倒数均值、幻觉率生成内容与检索内容不一致的比例。Hit Rate 衡量底线MRR 衡量排序质量幻觉率衡量最终输出可靠性。自研评测脚本时这三项最容易自动化也最能反映一次改动到底是变好还是变坏。2.5 Agent 化检索不是所有场景都要上 AgentAgentic RAG 是最近的热词但我拆完六款产品后得到一个很务实的结论Agent 只是检索流程的一种编排方式不是必选项。LangGraph 把检索流程变成可条件跳转的图LlamaIndex 用 Workflow 事件机制控制异步步骤Dify 和 FastGPT 提供专门的 Agent 节点RAGFlow 也可以把知识库检索当作工具交给 Agent 调用。它们的共同思路是让模型自己决定“先查哪个库、要不要再查一次、要不要调用外部工具”。这套设计在解决开放式、多跳、跨库问题时确实比固定链路易用得多。但我实测下来Agent 化的代价非常具体延迟普遍翻倍token 消耗大概增加 30%~50%且输出不稳定。很多企业场景根本不需要完整 Agent一个“查询改写模块”就够了——用户的问题进来以后先用一个小模型判断这是简单查询还是复杂查询复杂查询就拆解成子查询然后再走常规检索链路。这个思路已经被 Dify 的多路召回和 LlamaIndex 的 Query Pipeline 验证过了。所以自研蓝图上我给 Agent 的位置是“可选增强层”而不是“核心必选层”。3. 可复用的自研蓝图模块、数据模型与关键参数3.1 自研 RAG 的七个核心模块基于六款产品的共性我给自研 RAG 画了一张最小完备蓝图一共七个模块。模块职责输入输出对应开源参考接入模块接收并校验文件文件流 → 标准化文档对象LangChain Loader 的抽象思路解析模块提取文本、版面、表格、OCR原始文件 → 结构化正文RAGFlow DeepDoc切分模块按策略生成父子块正文 → Chunk 列表FastGPT 父子分块向量化模块文本转向量Chunk → EmbeddingLlamaIndex 的 embedding 抽象索引存储模块向量 全文 metadata 存储向量 → 可检索索引Haystack DocumentStore检索模块召回 融合 重排查询 → 排序后的候选块Dify 混索 RRF生成与引用模块组装 Prompt、生成、校验引用候选块 问题 → 答案和引用各家 Prompt 模板这七个模块里前四个是离线建库链路后三个是在线查询链路中间靠“知识库数据”衔接。自研时最容易犯的错误是把建库和查询混在一起改蓝图上建议把它们拆成两个独立服务至少也要拆成两个独立模块否则后面做增量更新、做知识库版本管理会非常痛苦。3.2 数据模型设计数据模型是自研蓝图最容易被忽略、又最影响长期迭代的部分。我参考 LlamaIndex 的 Node 结构和 Haystack 的 DocumentStore 抽象整理了一套精简表结构实际项目里可以直接用也可以按业务字段扩展。documents表记录原始文档包括doc_id、file_name、file_type、file_url、status待解析/解析中/已完成、parse_result、created_at。chunks表记录切分后的文本块包括chunk_id、doc_id、parent_id父块 ID没有则为空、content、content_with_format保留 Markdown 或表格结构、token_count、metaJSON 字段存页码、标题路径、标签、embedding_id。chunk_vectors表记录向量如果直接用向量库管理这张表就对应向量 collection字段包括chunk_id、vector、model_name、dimension。注意向量和文本块尽量分开存放因为 embedding 模型升级后往往只需要重算向量不需要重切文档。检索日志表也一定要有query_id、query_text、rewritten_query、hit_chunks、final_answer、hit_rate、latency_ms。没有这张表你后面调参就是在盲调。我在三个自研项目里都吃过没有检索日志的亏后来补日志表的时候才发现很多坏结果根本没法回溯。3.3 技术选型建议技术选型是自研蓝图落地的关键。我的建议是“最简优先按规模逐步替换”。环节起步选择生产环境升级方向向量库FAISS单机实验Milvus / Qdrant / pgvector按并发和数据量选全文索引SQLite FTS5 / PostgreSQL FTSElasticsearch / OpenSearchEmbedding 模型bge-small-zhbge-m3 / 商业向量模型重排模型bge-reranker-basebge-reranker-large / 自训重排LLM通用大模型 API私有化部署 领域微调向量库的选择我多说一句如果团队本来就熟 PostgreSQL直接用 pgvector 是最划算的起步少维护一个中间件。等到数据量过了百万级、查询 QPS 上来了再迁移到 Milvus 或 Qdrant 不迟。全文索引同理Elasticsearch 很好但对一个知识库场景来说常常是杀鸡用牛刀SQLite FTS5 能撑住大部分早期场景。3.4 影响 RAG 效果的关键参数从六款产品里我把影响效果的参数收敛成了七个。每个参数都对标着开源项目里实际可调的配置并且我给出了经过多组跑分验证的起始参考值。参数起始建议影响说明chunk_size400~800 字符中文太小上下文不足太大检索噪音多chunk_overlap50~100 字符避免关键句正好落在切缝上TopK召回数20 以上太小会直接拉低 Hit Rate重排后截断数3~5喂给 LLM 的上下文越精炼答案越稳混合检索权重RRF 或 0.7 向量 0.3 关键词关键词召回兜底向量召回保语义重排分数阈值按实际跑分定宁高勿低滤掉低质量片段减少幻觉LLM 温度0.1~0.3知识问答要确定性不要创造性这些参数没有一个能靠拍脑袋定。我每次调参都会先用 200 条真实问答做一次 Hit Rate 和 MRR 跑分再人工抽 20 条答案看生成质量两轮之后参数基本就能收敛到一个合理范围。参数优化没有一次到位的但它是最确定性的投入每调一版都比玄学调 Prompt 有价值。4. 从逆向到落地实操步骤与问题排查4.1 如何用六款产品做对照实验逆向工程到最后一定要落到对照组实验。我的做法是准备一份“魔鬼文档包”里面包含一份双栏 PDF、一份带表格的 Excel、一个网页另存为的 HTML、一张带文字的截图、一份 Markdown 技术手册然后在六款开源产品里分别建库用同一批 50 条问题发问。我很建议你复刻这个做法因为只有同数据、同问题、不同产品跑一遍才能直观看到每个项目在解析层、分块层和检索层的真实水平差异。记下每个产品建库耗时、解析失败率、平均首字延迟、Hit Rate 和 MRR这组数字本身就是自研蓝图里最关键的验收基线。4.2 三组关键指标怎么算自研时评测脚本不用写得多复杂核心是三个公式。Hit Rate对每个问题检查重排后返回的 TopK 片段中是否包含人工标注的“标准答案片段”。包含记 1不包含记 0除以问题总数。它反映的是“检索链路有没有把答案捞出来”。MRR对每个问题找到标准答案片段在返回列表里的排名 position取 1/position。多条问题取平均。它反映的是“正确答案排得够不够靠前”。幻觉率抽检生成答案判断其中是否存在检索片段里没有的事实。人工抽 50~100 条统计含幻觉的比例。这个指标比前两个更难自动化但对企业场景最重要。我带过一个新人他优化了一周向量模型看准确率涨了两个点结果人工一查发现答案里全是编的内容原因是他只顾着提高检索命中没检查生成环节是否忠实于检索片段。所以三个指标要一起看缺一个都会失真。4.3 常见问题排查表拆完六款产品又把这些实践搬到自研项目里以后我把最容易踩的坑整理成了排查表。遇到问题先按表自查大部分都能定位到具体环节。症状可能原因处理建议图片上传了但搜不到解析层没做 OCR图片被当空文本接入 OCR 或多模态描述模型PDF 检索内容顺序错乱版面解析没还原阅读顺序升级版面解析模型看齐 DeepDoc关键词查不到但语义相近能查到纯向量索引缺少关键词召回加 BM25 或全文索引混索后融合检索返回一堆高相似但无意义片段TopK 太大或重排阈值太低调高重排分数阈值调低 TopK重排后答案反而变差重排模型太小或训练域不匹配换大一号重排模型或做领域数据微调Agent 多轮检索后上下文超长每轮检索片段都拼进上下文限制多轮检索轮数片段合并时做去重生成答案引用了检索外的内容提示词约束弱或温度过高温度降到 0.1提示词里强制“只依据给定片段回答”增量更新后旧数据搜不到只更新了新文档旧索引未重建建库链路做全量重建或按 doc_id 增量覆盖4.4 自研最小闭环的迭代路径最后给一条务实的迭代路径也是我拆完六款产品以后如果从零开始会走的顺序。第一步先做“接入 固定切分 向量检索 LLM 生成”的最小闭环用 pgvector 加 bge-small 起步跑通数据流。第二步加上混索和 RRF把 Hit Rate 提上来。第三步加解析层的深度优化比如版面分析和 OCR解决魔鬼文档。第四步加重排模型把 MRR 和最终答案质量提上去。第五步再做增量更新、权限过滤、可观测面板。最后一步才是 Agent 化或 GraphRAG 这类增强能力。这个顺序的核心逻辑是先保证链路通再保证检索准再保证输出稳最后才做花活。我见过太多团队一上来就研究 Agent 编排结果连基础的 PDF 解析都没做好这个顺序能帮你避开同样的坑。在整个逆向过程中我最深的体会是开源 RAG 项目最大的价值不是代码本身而是它们用产品形态验证了一个共同的心智模型——RAG 的成败 60% 在离线链路解析、分块、索引30% 在检索质量混索、重排、评测只有 10% 在生成环节。很多人自研时把精力全投在改 Prompt 和选大模型上方向都错了。所以每次有人问我要不要自研我都会反问一句你先把解析层做到 RAGFlow 的水平、检索评测做到 Dify 的水平了吗如果没有老老实实先抄开源再谈超越。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进