拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

RAG项目落地指南:从流水线到知识治理的六个分水岭

RAG项目落地指南:从流水线到知识治理的六个分水岭

1. 别急着说“烂大街”,先问自己有没有踩过这几个坑

前两天有个朋友发来一张截图,问我说:“现在是不是随便拽个 Dify 知识库流水线,拖几个节点就能做 RAG 了?网上一搜全是‘ollama + 简易本地 RAG 知识库【零基础可复制教程】’,这玩意是不是已经烂大街了?”

我说:能跑,和能解决问题,完全是两码事。

你拿 Dify 或者 LangChain 搭一个本地 RAG 知识库 demo,可能一下午就搞定了。加载文档、拆分段、向量化、建索引、检索、拼 prompt、调模型,一条流水线清清楚楚。但这跟“做一个靠谱的 RAG 项目”之间的距离,可能比你想的大得多。同一个检索增强生成流程,不同人搭出来的效果可以天差地别。烂大街的只是那条流水线模板,真正拉开差距的,是流水线外面那六处细节。

我这些年看过的 RAG 项目,上到企业知识库、下到个人笔记问答,最后效果好不好的,几乎都卡在这六个点上。这篇文章就把它们一个个拆开讲清楚,顺便把大家在群里经常问的 rag hit rate、agentic rag、ontology rag、rag graphrag llm wiki 本体 rag 这些概念,跟实操场景对起来。适合刚做完 demo、正准备把 RAG 放到真实场景里的同学,也适合已经维护知识库很久、但一直被答非所问困扰的团队。

2. 分水岭一:知识治理才是 RAG 的第一步,别急着灌向量库

2.1 为什么一上来就向量化,通常都会翻车

很多人拿到文档的第一反应是“走流程”:加载,切分,embedding,入库。这个顺序本身没错,错在默认了文档是干净、一致、可以直接用的。

真实世界的文档长什么样?一份内部制度文件里同时保留了三版修订记录,新条款和作废条款在一个 PDF 里并排躺着;一个产品说明书文件夹里,同一个型号有三个不同年份的版本;还有那种扫描件,图片转出来全是 OCR 错字。你把这些东西原样丢进 Dify 知识库流水线,或者自己写脚本灌进向量库,模型检索出来的可能是作废条款,也可能是夹杂着乱码的碎片。

这其实就是很多人说的“知识割裂”。它不是文档内容本身的问题,而是知识源没有被治理之前,必然会出现的结果。向量检索再强,也是建立在数据质量之上的。我记得有个企业知识库项目,问答效果怎么调都上不去,后来发现知识库里 30% 的内容是过时制度,模型答得倒是挺流畅,可惜依据是已经废除的版本。这不是模型问题,是数据问题。

2.2 入库前到底该做什么

我一般会把知识治理拆成四步,每一步都不复杂,但少了哪一步后面都会还债。

第一步,格式归一化。PDF、Word、HTML、Markdown、扫描件,先全部转成统一文本流。PDF 能用文本抽取就用文本抽取,扫描件就得走 OCR,PaddleOCR 和 Tesseract 都行。这一步别偷懒,后面切块、检索、引用的质量都建立在这里。

第二步,去重合并。按文档标题、修订版本、发布时间做主键,把多版本并成一份,保留生效版本,作废版本要么移除、要么单独打标。不要怕删数据,要怕的是删错了版本。

第三步,分类打标。按业务域给文档打标签,制度、产品、售后、流程之类。标签的价值在后面会体现出来——做权限过滤、做检索路由、做评估分析,它都能帮你精准定位。

第四步,补充标题和摘要。给每个切片保留“上一级标题 + 章节名”,甚至让 LLM 帮忙写一段文档摘要。这能让检索阶段用更丰富的信号去匹配,效果比裸的正文切片要好得多。

我当时做这套流程的时候,有三分之一的时间花在写数据清洗脚本上,不是在搞 prompt,也不是在调 embedding。后来习惯了才明白,RAG 项目真正比拼的是“把知识变成可检索、可信任的语料”的能力。

2.3 一个经验:先把知识目录画出来

还有一个很多人忽略的动作:入库之前,先画一张知识目录。

不用画得多正式,就是一张表格,列清楚“有哪些知识域、每个知识域下有哪几类文档、每类文档谁负责维护、更新频率是多少”。这张表画完,你自然就知道哪些数据该进重点知识库,哪些数据根本不值得向量化,哪些数据需要单独拉一个检索接口。知识治理不是一次性动作,它像整理房间,先规划好储物位置,再往里面放东西。

3. 分水岭二:文本拆解是技术活,别只会调 chunk_size

3.1 固定切块为什么经常“腰斩”语义

“chunk size 设成 512,overlap 设成 64”,这大概是 RAG 教程里出现频率最高的参数组合。但你要是照着这么切,很快就会遇到一个现象:某个问题的答案明明在文档里,可怎么检索都召不回。

原因很简单。固定字数切分是按 token 数硬切的,它不懂句子边界,也不懂段落语义。往往一段完整的说明在小节中间被拦腰截断,前半段在上一 chunk,后半段在下一 chunk,而这两块跟相邻的内容搅在一起,检索的时候两边都搜不到关键信息。打个比方,你把一篇文章按每 100 个字裁开,然后在第二段里找第一段的结论,能找到才怪。

那是不是 overlap 设大一点就行?也不行。overlap 只是缓解边界信息丢失的缓冲,它不会把一个被切碎的论点重新拼完整。

3.2 更合理的拆法:让每个 chunk 自带一个小论点

我实操下来比较靠谱的思路是:切块不以“长度”为主,而以“语义完整性”为主。

优先按文档结构拆。Markdown 文档按标题层级拆,HTML 按块级元素拆,PDF 只要能抽出来标题结构就按章节拆。每拆到一个标题,新开一个 chunk,内容包括标题和它下面的正文。这样做有两个好处:一是 chunk 本身自带上下文标题,检索时能借标题做更精准的匹配;二是切出来的每段都尽量是自包含的,不太会出现“说一半没下文”的情况。

其次,表格单独处理。很多 RAG 文本拆解工具默认把表格按纯文本切,结果一行行被拆得稀碎。表格的每一行通常是一条完整记录,一个表格拆成一个 chunk,或者一行一条记录,检索到一个片段就能拿到完整信息。不要小看这点,Dify 知识库流水线的默认分段方式经常切坏表格,导致回答漏列。

还有,代码块和命令行片段保留原始换行。代码的缩进和换行去掉之后,语义就变味了,检索出来的代码片段根本没法用。

3.3 参数怎么定:起点不是终点

那 chunk size 到底该设多少?我只能给一个经验起点:中文场景下,300 到 600 token 是一个比较常见的区间,overlap 50 到 100 token。但请记住,这只是一个起点,不是答案。每个知识库的文档情况不一样,技术手册、政策文件、问答记录,适合的切块策略各不相同。

正确做法是:先把文档结构摸清楚,再根据检索效果不断调。判断标准很简单,看“正确答案对应的文本是不是完整地出现在一个 chunk 里”。如果答案总是横跨两个 chunk,那就得放大切块粒度或者按结构切;如果 chunk 太大导致上下文窗口塞不下、检索噪声变多,那就调小。这里没有唯一解,只有“在你自己的数据上表现最好”的解。

4. 分水岭三:检索要“混搭”,但更要讲排序质量

4.1 单做向量检索,很容易漏掉精确信息

知识治理和数据拆解是数据侧的事,到检索这步,就开始碰真正的算法选型了。

现在很多 RAG 项目默认只用 embedding 做向量检索,方便是真方便,但盲区也大。向量检索擅长处理语义相近、表达方式不同的查询,比如用户问“耳机坏了能换吗”,它能检索到“售后换新政策”相关内容。可它对精确型号、编号、人名、法规条款号这类东西不太敏感。

举个例子,用户报一个“AK-2000-3”物料编码,向量检索可能会把它和“AK-2000-4”搞混,因为两者语义空间上太接近了。在真实业务里,这俩就是完全不同的两个东西,检索错了整个答案就废了。

解法是混合检索。BM25 这种稀疏检索负责精确匹配,“AK-2000-3”这种字符串贴上就逃不掉;向量检索负责语义扩展,“耳机坏了”能兜住“售后政策”这类描述。两路召回之后合并,再进重排阶段。

4.2 hit rate 不是万能的,但你不能不看

搜索热词里经常看到 rag hit rate,这确实是在 RAG 评估里被讨论最多的指标之一。hit rate 中文一般叫召回命中率,指的是“正确答案所在的 chunk 是否出现在召回列表里”。听起来很简单,但做检索优化的时候,它是第一个要盯的指标。

问题是,hit rate 只看“有没有出现”,不看“排在哪儿”。正确答案召回了,但排在第十位,生成阶段上下文窗口一截断,模型根本看不到。所以还要配合 MRR(第一个正确答案的排名)或者 NDCG(排序质量)来看。如果 hit rate 90%,但 MRR 很低,说明召回能拿到正确内容,但排序不行,优先优化重排;如果 hit rate 本身就低,问题多半出在召回策略或者切块粒度上。

4.3 两路召回之后,别省掉 rerank

在 RAG 流程里,检索结果直接拼进 prompt 的做法,在小 demo 里常见,在生产环境里几乎不可取。因为召回出来的候选多,相关性没保证,噪声很容易把生成带偏。

我的建议是:召回 50 条左右做候选,然后用一个 cross-encoder 重排模型压到 5 到 10 条。重排阶段常用的模型像 bge-reranker-v2-m3 这类,效果明显,成本也可控。

如果召回的是那种“字面完全一致才有意义”的内容,比如合同编号、订单号、法规条款号,最优解不是向量检索,而是“关键词精确匹配 + 限定范围”的字段检索。把这些高频精确标识符单独建一个索引,命中直接走精确路径,速度和准确率都比 embedding 高。

4.4 embedding 选型:别凭感觉,拿评测集说话

还有一点,中文场景下的 embedding 模型选型,网上说法五花八门。我自己的经验是,别迷信榜单,也别只看名气,拿你自己的数据做评测集,跑一轮 hit rate 和 MRR,再用几个真实 badcase 看看效果。

像 BAAI 的 bge 系列、m3e、text2vec 这些本地可部署的模型,我都在不同项目上用过,各有优劣。后来还有一些更新的小模型也不错,但判断标准永远是同一个:它在你真实的文档和真实的问题上表现如何。这个评测集,最好在项目第一天就建起来,后面所有调整都有据可依。

5. 分水岭四:从平铺文档到结构化知识,图谱和本体不是噱头

5.1 平铺 chunk 的天花板:多跳和关系型问题

所有 RAG 项目做到一定程度,都会撞上一个瓶颈:跨文档、多跳、关系型问题答不了。

比如用户问:“A 项目的报销上限是多少?B 项目呢?哪个更高?”如果知识库是一堆平铺切块的文档,每个 chunk 都记录了某个项目的报销规则,但模型需要自己去两个 chunk 里捞数据再比较。这还只是难一点,换一种问法更致命:“我这个月报销走哪个项目?”它需要先知道“我”属于哪个团队,团队关联了哪些项目,项目之间是什么关系,才能给出答案。这不是“多检索几个 chunk”能解决的,这是知识结构问题。

最近看到不少搜索热词都在往这个方向跑:rag graphrag llm wiki 本体 rag。说明很多人都意识到,知识库不仅要有内容,还要有“关系”。

5.2 GraphRAG、Ontology RAG、Wiki 各自解决什么问题

先说微软 GraphRAG 的思路。它先让 LLM 从文档里抽取实体和关系,构建一张知识图谱,然后基于图谱的社区摘要和查询结构来做检索。好处是跨文档关系能直接被利用起来,比如“A 项目”和“B 项目”都被抽取成实体,它们的关系(预算大小、所属团队)都在图谱里。查询“哪个项目预算更高”就可以走图谱路径,不用靠运气检索段落。

Ontology RAG 则更强调用 OWL/RDF 这种显式的本体模型来定义概念、属性和关系。它比 GraphRAG 更“重”,也更严谨。适合那些知识结构相对固定、关系边界清晰的领域,比如医疗分诊、法律条款、设备资产运维。它的核心价值在于:让模型在回答之前,先理解“什么东西是什么”这个层次的问题。

Wiki 则是另一条路。它用词条 + 超链接的方式来组织知识,靠页面之间的链接关系表达关联。比较适合文档本身就是百科全书式的知识库,比如产品文档库、内部 wiki。你可以把 wiki 的链接结构当成一种手工维护的图谱,每个词条是一张卡,每个链接是一条边。

说了这么多,我的态度是:别被名词吓住,也别盲目上重武器。如果 80% 的问题都是“文档里直接能找到答案”的,普通 chunk 检索就够用了;如果频繁出现“某些对象有哪些属性”“事件之间有依赖关系”“A 和 B 是否相关”这类问题,再考虑加图谱层。

5.3 小团队可以先试“实体路由”,完整图谱没那么急

很多人一听 GraphRAG 就头大,觉得要配 Neo4j、要写抽取流程、要跑社区聚类,工作量大得离谱。其实小团队有一个性价比很高的过渡方案:对每个 chunk,用 LLM 抽取出关键实体,人名、机构、产品、法规、项目名,把这些实体存在元数据字段里。用户问题命中某个实体时,就优先在该实体相关的 chunk 集合里检索。

这个动作比完整图谱轻量得多,但已经能解决相当一部分“跨章节、关系型”问题。等到实体路由出现明显不足时,再考虑上真正的图谱层不迟。

还有一点提醒:抽取实体关系后,把“置信度”和“证据片段”一起存下来。图谱错了,后面所有基于图谱的检索都会错,而且错得毫无痕迹,排查起来非常痛苦。

6. 分水岭五:Agentic RAG,让“检索”变成一个有决策能力的行为

6.1 普通 RAG 和 RAG 智能体的区别

普通 RAG 的流程是固定的:用户提问,检索,拼上下文,生成答案。这个流程没有决策能力。用户问“我耳机坏了怎么办”,它老老实实去知识库里检索,不管这个问题里其实混着售后政策、维修指引、线下网点三个不同需求。

RAG 智能体就不一样,它多了一层规划。先判断这个问题要不要查知识库、查哪个知识库、要不要追问用户信息、要不要调外部接口。这就是热词里“agentic rag”和“rag智能体”的真正价值。它不是简单把工具调用加进提示词,而是把“检索这个动作是否执行、何时执行、执行到什么程度”的决定权交给模型。

6.2 Agentic 的四种常见编排

我见过比较实用的 Agentic RAG 编排,大概有四类。

第一类是路由。根据问题类型,把问题分发到不同索引、不同知识库或不同 API。比如“售后政策”走售后库,“技术参数”走产品库,“订单状态”走接口查询。这一层如果做好了,比任何检索优化都管用,因为从源头就隔离了噪声。

第二类是重写。向量检索之前,先把用户的表达改写成更适合检索的句子。用户说“耳机坏了能换吗”,改写成“耳机售后政策 换新条件”,检索命中率会高很多。很多情况下,问题表达不精准,不是模型不行,而是检索入口太窄。

第三类是工具调用。通过 function calling 调 CRM、订单系统、资产系统,用返回的实时数据补全上下文。比如“我的订单到哪了”,知识库里不会有这个答案,必须让 Agent 调订单接口。

第四类是多轮追问。用户问题模糊时,先反问而不是直接检索。比如“耳机坏了怎么办”,Agent 可以先问“是在保修期内损坏的吗?”,拿到答案后再检索对应路径,比瞎检索知识库靠谱得多。

6.3 实施路径:不用一上来就全 Agent 化

很多团队一听到 Agent 就兴奋,恨不得把整条 pipeline 全改成 Agent。我建议稳妥一点。

第一步,先做“检索前改写”。如果在 Dify 知识库流水线上,可以加一个前置节点:对问题做改写,生成一个“检索语句 + 过滤条件”。第二步,做“二次检索”。如果第一次检索的最高得分低于某个阈值,就认为没有抓到关键信息,改写后重新检索一次。第三步,才考虑“工具调用”。等前两步稳定了,再让 Agent 接入外部接口,把实时数据作为附加上下文。

用 Java 技术栈的团队可能用过 langchain4j easy rag,这套流程本质是一样的:把 Retriever 换成带路由和重写的 AgentRetriever。关键不是用哪个框架,而是你有没有设计“决策逻辑”。没有决策逻辑的 Agent,只是披着 Agent 外衣的固定流水线。

7. 分水岭六:每一轮都在“评估”,而不是发布前测一次

7.1 没有评测集的 RAG 项目,很容易自嗨

RAG 项目特别容易陷入“自嗨”。做 demo 的时候,问两三个精心设计的问题,模型回答得漂亮,就以为大功告成。等上线之后用户随便问一句,立刻露馅。

我做过好几个 RAG 项目后的体会是:判断一个知识库好不好用,不能靠感觉,要有一套可重复的评测集。评测集里至少包含四类问题:明显可从文档回答的事实问题;需要跨章节、多跳才能答出的问题;需要做否定性判断的问题,也就是文档里没有相关内容,模型必须敢说“不知道”;还有边界模糊、容易被误导的问题。

四类问题各有各的价值。事实问题测基础检索,多跳问题测知识结构,否定性问题测幻觉,边界问题测纠偏能力。没有这个评测集,你调了 prompt、换了 embedding、调了切块参数,也不知道到底有没有变好。

7.2 常用指标怎么选,别被术语绕晕

RAG 评测里指标很多,rag hit rate、MRR、faithfulness、answer relevancy、context precision、context recall……全堆在一起很容易晕。我的建议是,初期只看两个:hit rate 和 faithfulness。

hit rate 管的是召回,答案所在的 chunk 有没有被检索出来;faithfulness 管的是生成,答案是否严格建立在检索到的证据之上,有没有在“编”。这两个一个管上游,一个管下游,串起来就是 RAG 的核心链路。

排序阶段可以加一个 MRR,看正确 chunk 排在第几位。等上线运营了,再加 answer relevancy 和 context precision。不要一开始就追求全指标,你没那么多人力去维护。

7.3 上线不是终点,是评估的起点

真正用过 RAG 人才知道,上线之后才是评估的开始。用户点“没用”的反馈、答非所问的记录、被反复问却答不好的问题,这些都是最真实、最宝贵的 badcase 来源。

我当时维护一个知识库时,每周做一次 badcase 回流。把上周用户反馈里“答非所问”的记录整理出来,放进评测集,跑一遍全流程,看哪里断了。结果发现,有一半问题不是模型不行,而是知识库少了对应的文档,还有三分之一是检索召回排序不对。改了之后,下一轮的 hit rate 和 faithfulness 都有明显提升。

在 RAG 项目里,评估不是最后一件事,而是贯穿始终的一件日常事。这也是我认为“烂大街的流水线”和“真正可落地的 RAG”之间最本质的区别:前者是做完即止,后者是持续优化。

8. 常见问题与排查技巧实录

不同场景最容易踩的坑,整理成下表,对照着查会快很多。

症状可能原因处理手段
常见问题答非所问知识库缺对应文档,或语句被切块截断先查召回原文,再按标题层级/段落边界重切
问“A 和 B 相比怎样”答不出属于多跳问题,平铺 chunk 缺少跨文档关系短期加实体路由,长期引入图谱层
精确编码查不到embedding 对短代码、编号不敏感加 BM25/精确匹配字段,或建精确标识符索引
答案读起来合理,实际是错的faithfulness 不足,模型在编降低 temperature、加强证据约束、要求“无依据时必须答不知道”
检索有命中,但回答没用上正确答案排序靠后,或上下文窗口截断加重排层,将返回条数压到 5~10 条
Dify 知识库回答漏表格列默认分段把表格切碎了入库前把表格转成 Markdown 并单独成段

除此之外还有几个实操心得。

第一,生产环境的 temperature 不要设成 0。就算设成 0,模型也可能有随机性。真正关键的是在 prompt 里写清楚,“如果检索到的证据不足,你要回答‘没有找到依据’”,而不是强行生成一个答案。

第二,本地 RAG 项目也一样,API key 别硬编码在代码里。用 Ollama 跑本地模型很好,但环境变量、密钥管理、日志脱敏这些基础工作不能省。

第三,上线前专门跑一遍“不相关知识问题”。比如问知识库完全没覆盖的内容,看它敢不敢说“我不知道”。如果一个模型对什么问题都硬答,那它在真实场景里一定会惹麻烦。

9. 我在实际踩坑后的一点经验

从零搭过本地 RAG 知识库,也用过 Dify、LangChain、还有图谱方案,折腾这么多年,我最大的体会是:RAG 真正的分水岭,从来不是模型多新、框架多花哨,而是数据和评估这两件事做到什么程度。

烂大街的只是模板,不是问题本身。把文档扔进向量库、调几个参数、接一个大模型,这套流程谁都会。但要把“知识割裂”的数据整理成可靠语料,要在多跳问题上答得准,要让模型敢说不知道,这些功夫都在流水线之外。

最后分享一个小技巧。如果你准备上一个 RAG 项目,第一件事不是搭环境,而是把“用户最常问的 50 个问题”找出来,逐个确认知识库里有没有对应的答案源。这 50 个问题都能答对,你的 RAG 已经比市面上大半的 demo 强了。先解决“检索不到”和“乱答”这两个核心痛点,后面所有的优化才有意义。

返回列表