做知识库和RAG冲刺期的朋友,很多都卡在同一个地方:文档能建库了,Demo能跑通了,但一旦换到真实业务数据,效果就变得很飘,召回不准、引用错乱、知识更新不动,最后只能加班调Prompt,越调越玄。我今年一直在带几个To B项目落地RAG,顺手把团队内部的迭代过程整理了一套体系,干脆策划成了《RAG进阶实战》专栏,这篇就来交代一下专栏的整体构思,以及在打磨过程中被问得最多的几个关键技术问题。
这个专栏的目标很直接:解决RAG从“入门可用”到“生产可用”之间的那段真空地带。适合已经有基础概念、但被实际问题折磨过的算法工程师、后端开发,以及负责知识库平台建设的技术负责人读。后面涉及的内容,我不打算按教科书顺序写,而是按项目里真实踩坑的顺序来,比如知识库怎么选型、混合检索怎么做、Mac上怎么快速搭一套能跑的Demo用于验证思路、图片这类非结构化内容到底能不能进RAG系统,这些都会被拆开讲。
1. 专栏定位与整体设计思路
1.1 这个专栏到底想解决什么问题
市场上有关RAG的入门资料已经多到溢出了,随便一搜就是“十分钟搭建RAG知识库”“基于LangChain的QA机器人”这种教程。但此类资料有个共同特点:只负责把流程跑通,根本不对结果质量负责。等到你换一批真实的行业数据,就会发现分词乱、分块碎、检索出来的都是相似但不对的片段,模型把几个文档的内容缝在一起生成一段话,最后你还要对着引用来源一条条肉眼校验。
《RAG进阶实战》的出发点不是教你怎么调用接口,而是把“一条指令之下”的那些决定成败的环节讲透。我在构思的时候问了自己一个问题:如果团队里来了一个新人,需要多久才能独立完成一个中等复杂度知识库的交付?答案通常不是“三天”,而是“要看文档质量、业务场景、评估标准是否全都明晰”。这正是专栏要解决的短板——把看不见的努力变成可复用的方法。
所以,整份策划案暗含的核心主线只有一个:除了连接大模型之外,RAG系统还有什么工作需要当回事。沿着这个主线,我会把流程拆成“知识入库、检索召回、结果生成、评测反馈”四段,每一段再对应一到两个核心决策点。最终读者拿到的不是一个脚本,而是一套可以迁移到不同业务里的决策框架。
1.2 目标读者与内容层次的取舍
确定读者范围的时候,我刻意做了约束。初级读者,至少要知道Chunking和Embedding是什么意思;高级读者,不能只用一句“多路召回很好”带过,而要能聊清楚各路召回的代价和落地条件。这是一个两难:写浅了对进阶的人没帮助,写深了新人又容易跟丢。
我的处理方式是把每篇内容分成两层。第一层是“现象与结论”,哪怕你经验不多,也能照着步骤复现结果;第二层是“代价与权衡”,需要你具备一定的系统设计意识才能消化。比如讲到向量检索时,我会先给出一套可以直接使用的分块策略,再补一段关于分块在语义边界上的偏差分析,激发读者思考其背后的原理。这种结构迫使我在策划时每一篇都要准备两套素材,但实际回报是:专栏的口径既能照顾初学者,也能给老手提供有效信息。
还有一个被反复讨论的点:到底要不要在专栏里讲如何使用LangChain、LlamaIndex这类框架。我的回答是“要讲,但不以框架为主轴”。原因很简单,框架更新太快,今天写透彻的API明天可能就变了。我更倾向于讲清楚抽象的链路,然后用具体框架演示“以上原理在这类框架里落在哪个抽象层”,这样即使框架迭代,读者也能自己推断新版本里的接法。
1.3 选题主线和专栏目录规划
整体策划一开始是发散成两页A4纸的,后来收敛成了七个关键词:知识库选型、文本切分、向量化与重排、混合检索、生成压缩、评测迭代、系统部署。每一篇在目录里都对应一环,环环相扣,但又可以单独抽出来当作独立参考。
我给专栏起名叫《RAG进阶实战》,其实是有意避开“高级技巧”“深度解析”这类词。真实项目里的进阶根本不是靠什么花哨魔法,而是靠老老实实把每个环节的失败模式摸清楚。目录里的每一篇,都会附带至少一个可复现的失败案例,再给一套排查步骤。这个设计比较管用,因为读者看到“为什么这么选”之前,先看到“不这么选会死得多惨”,才更容易记住结论。
目录规划最终需要平衡“热度”和“难度”。比如“知识库能否存储图片”这类问题搜索量很大,单独成篇又会显得单薄,我便把它并入“非结构化数据入库”主题。这样既回应了高频疑问,又能把问题讲深一层,不至于变成一篇答疑短文。
2. 知识库选型:向量库、知识图谱与结构化知识库怎么分工
2.1 向量知识库与结构化知识库的核心差异
很多人把“RAG知识库”默认理解为“向量数据库”,这个先入为主的印象其实掩盖了大量边界问题。向量知识库擅长做“语义相似召回”,也就是你能描述大概意思,但记不住精确条件。通俗地讲,它更像一个印象派记忆体,看到“上个月华东区的退货率”这类说法,能联想到入库文档里的相关段落,但这联想本身不具备可推导性。
结构化知识库则完全相反,它强调规则、约束、准确性。典型代表是关系型数据库中的维表,甚至是经过整理的CSV文件。处理“查一下单价高于5000元的SKU有多少个”这类带明确过滤条件的请求,结构化查询比向量检索可靠得多,并且结果可复现、可审计。
实际项目里最常犯的错误是混用两者的场景。要么用向量库跑强约束查询,结果返回一堆相近但答非所问的内容;要么把结构化数据硬塞进文档,让模型在一个长篇文本里靠注意力去“找”整数值,导致回答忽灵忽不灵。专栏里我专门写了规则,有一个很管用的判断维度:如果问题里存在精确的过滤条件、聚合条件或多表关联,优先交给结构化方案;如果问题是“找一段相关描述”,向量方案性价比更高。
2.2 Ontology在RAG里的真实含义
热词里出现了Ontology相关话题,我在知识库选型部分也特意准备了篇幅。Ontology可以理解为对某个领域内概念与关系的显式定义。一份标准的产品本体,会明确说明“手机”是一种“电子产品”,“手机”内有“电池”“屏幕”等多个部件,“屏幕”跟“供应商”之间存在供应关系。这些定义本身就是一张图,也就是知识图谱的基础骨架。
Ontology驱动的RAG方案,通常用于解决多跳问题。比如用户问“用B公司屏幕的手机里,续航超过5000毫安的有哪些”,如果纯靠文档切块,系统可能先召回一堆“屏幕参数”的段落,再召回一堆“续航评测”的段落,但两者之间的实体关系没有被建立。若在图里补充了“手机-使用-屏幕”和“手机-电池容量”两条边,这个问题就变成一个简单的遍历操作,准确性瞬间上升。
但Ontology也有成本。它需要人工定义概念、属性、关系,跟业务专家反复对齐,且维护周期较长。我的经验是:别一上来就上图谱,先评估问题集里有没有稳定的关系查询需求;如果没有,先跑普通RAG,等检索结果暴露出“跨文档关联”这个瓶颈时,再引入图谱补强,是一种比较稳妥的实施顺序。
2.3 混合知识库的落地路线
现实中一个业务系统很少只用单种知识库,更多是“多库协同”的状态。我归纳出一条落地路线,姑且称为“按需求分层”:第一层,用全文检索和向量检索解决“找得到相关资料”的问题;第二层,按业务文档中频繁出现的枚举类型、状态类型,把它们抽取成结构化字段,比如客户状态是“已签约/未签约”,这些字段进属性库;第三层,当实体之间的关系查询成为主要瓶颈时,再考虑上知识图谱或Ontology。
这三步并不需要一次性到位。最稳妥的做法是先快速搭建向量库,把从“能找到”到“目标准确”的成本看清,再逐个补齐结构化和图谱能力。这样资金和技术方面的投入都能被分摊开。整个方案在专栏里被提炼成一章,标题就叫“RAG知识库与结构化知识库的边界与融合”,核心观点是:二者不是你死我活,而是面与点的关系,先想清楚主导路径,再进行补充建设。
3. 核心链路拆解与实操要点
3.1 分块策略为什么是第一个拦路虎
文本切分是几乎所有RAG项目里第一个让人头疼的环节。很多教程简单粗暴:按固定token数硬切,比如每512个token切一块,似乎就可以进行后续操作了。但实际业务文档里,一个完整知识点往往横跨好几个表格、列表,或恰好卡在段落中间,硬切之后,问题与答案会被拆到不同的块里,无论用多少召回路数都找不回已被拆散的那段“语境”。
我实践中使用的判断标准是:尽量以语义边界为优先,固定长度作为兜底上限。比如通用文本先用Markdown标题或段落边界切分;遇到表格数据,尽量把表格连同表头和上下文说明一起保留;对于PDF扫描件等复杂格式,先做版面分析,再考虑是否合并段落。图文混排内容还要考虑图注与正文的关联关系,避免图片说明落到隔壁块中导致语义错位。
关于分块粒度,有人说越小越准,有人说越大越全,其实还是要回到下游能力的匹配问题。如果嵌入模型擅长短文本语义匹配,就适当切小;如果生成模型上下文窗口大,且需要参考跨段信息,则保留较大的块。一个可参考的起点:一般文本每个块500~800字,重叠区间控制在10%~15%,再结合评测调整。这里没有任何魔法值,一切以反映业务诉求的评测集为准。
3.2 Embedding模型与重排序模型的配合逻辑
做RAG进阶,最值回票价的投资基本有两样:Embedding模型和重排序模型。Embedding负责第一轮粗召回,把候选集从全库缩小到百条量级;CrossEncoder式的重排序模型再逐对精算查询与候选文本的匹配度,从百条里挑出最相关的前三条到五条。这个两步走的结构无比常见,也无比实用,因为只靠向量相似度排序时,语义相近但并非当前问题答案的文本,极容易排在前面。
模型选型时,我建议关注的是中文场景的表现,而非单纯关注榜单分数。如果业务文档文体特殊,最好用业务样本做小样本评测。至于重排序模型,它的输入输出自由度比Embedding大不少,部署时还要考虑推理速度和并发响应,若承载小规模场景,CPU跑一个小型号通常勉强可用,但查询量上来了,还是建议单独起GPU推理服务。
在专栏设计里,这两类模型的选型与部署分开写。因为更换一个Embedding模型涉及的入库脚本影响面更大,而更换重排序模型只是在线链路上的服务替换。两者的回滚成本和验证方式并不一样,把它们混在一起讲容易让人以为“换模型就是调参数”,忽略了整套适配流程的存在。
3.3 生成环节:不止是“把检索结果丢进提示词”
很多人以为检索做好,生成就是写一段Prompt的事,实际上并非如此。RAG的生成环节最大的问题有两个:一是幻觉,即模型生成的内容超出检索片段的范围;二是“缝合”,即把多个片段里互斥的信息拼进同一个回答,在表达上看着通顺,但结论没有依据。
针对幻觉,我会建议在系统层面加入“引用可溯源”的约束。具体做法是让模型在回答时标注引用块ID,再在后端做校验:若某段陈述没有对应引用,就强制拒绝生成或降级为“无答案”。这并非万无一失,但能大幅减少“高置信度胡说”的情况。
针对缝合问题,一个行之有效的方法是限制生成时引用的片段数量。很多演示Demo喜欢塞8至10个块给模型,指望它能自己综合,然而模型并不真正具备复杂的综合推理能力,它会挑选看起来最连贯的一些片段,于是出现了张冠李戴的现象。配置文件里把候选片段限制在3到5个,并强制规定每个片段必须有明确上下文才算可用,整体回答质量通常会有明显改善。这些实操经验,听起来并不高端,但确实是决定生产系统能否上线的那道分水岭。
4. 在Mac上搭一套可用的RAG知识库
4.1 为什么拿Mac当搭建环境
“怎么在Mac上搭建RAG知识库”这个热搜词说明了一个现象:大量技术人最先拿到的开发机就是MacBook。我自己也是。Mac上搭RAG知识库有一个很现实的痛点:很多主流组件默认依赖Linux的编译环境,跑到macOS上会遇到安装失败或编译报错。但换个角度想,Mac的Unix底层和统一内存架构,对本地跑小模型又很友好,其实是一个不错的实验环境。
我规划专栏时,把Mac作为第一实操平台——先讲清楚怎么在Mac上跑通一个最小Demo,再讲怎么把这个流程迁移到Linux服务器。Apple Silicon的机器跑大模型,内存大小是一个关键变量。16GB内存的机器用7B级别量化模型,约30到35GB内存的机器可以跑13B甚至更大参数量,但这只是粗略估计,具体还是要看量化位数和上下文长度。
4.2 环境准备与框架选型明细
在Mac上搭建RAG知识库,第一步是准备基础环境。用Anaconda或Miniconda创建独立Python环境,是一个稳当的起点,避免依赖之间互相干扰。可写入正文的典型命令如下:
conda create -n rag-lab python=3.11 -y conda activate rag-lab pip install langchain chromadb pypdf sentence-transformers这里建议使用文本嵌入模型,资料库类的需求不需要大模型参与,MiniLM系列和多语言的Multilingual-E5系列都很合适做初步验证。生成环节,可以借助Ollama在本地跑通,也可以调用云端的API。我的建议是先用云端API验证链路,等确认检索质量达到预期之后,再考虑本地部署模型——搜索链路做得烂,换多大的模型都没有意义。
框架方面,LangChain和LlamaIndex是绕不开的两个选项。如果业务逻辑简单,LangChain足够直白;如果需要丰富的索引和查询形式,LlamaIndex更顺手。两者不是二选一的死结,也可以混合着用,但我的经验是新手尽量选一个先跑通,再考虑更深层的定制化来避免过度设计。
4.3 多模态与图片内容是不是RAG的禁区
“RAG知识库能存储图片吗”这个问题在网络上非常高频。回答是“能,但要看你对‘能’的定义是什么”。如果你希望做的是“用户上传流程图,系统直接根据图上的文字和结构回答问题”,那传统RAG的确不直接支持——视觉理解需要走多模态模型引擎。如果把图片作为“可检索知识”的一部分,则完全是另一回事。
落地时有三种主流方案。第一种,对图片先做OCR,提取其中的文字,再将文字纳入知识库索引,这种方式最常见,适用于PPT截图、扫描合同等带关键文本的内容,但图片内的非文字语义(例如曲线走势、饼图比例)会丢失;第二种,为每张图片生成一段描述性的自然语言,把描述作为该图的替代内容入库,适合文章配图、产品示意图;第三种,使用多模态Embedding模型,将图像和文本映射到同一向量空间,实现文字搜图或图搜图,但部署成本相对较高,对硬件资源也有要求。
在Mac实验环境中,最务实的做法是从第一种和第二种入手。把图片变成文本补进知识库,绕开视觉模型的复杂依赖,但Prompt阶段要预设“该信息来自图片OCR”等上下文,避免模型把类似“截图文字”的信息当成普通段落泛泛理解。专栏会安排一节“RAG知识库的非结构化内容扩展”,讲清楚不同类型图片分别为入库流程带来的干扰和应对方式。
5. 常见瓶颈与排查实录
5.1 召回质量不理想时,先分清楚病根
热词“rag瓶颈”触及到了项目中最容易产生挫败感的部分。当系统回答不好或漏检时,很多人的第一反应是“换个大模型”,但这个方法往往治标不治本。在专栏设计里,为这类问题梳理出了一张很直接的排查顺序表,核心思路是把瓶颈定位到链路中的具体模块,而不是盲目替换组件。
先看召回质量,把查询和命中的块直接打印出来,人工判断“命中内容是否与问题语义相关”。若命中内容明显不相关,问题基本在Embedding或之前的分块阶段,可考虑换模型或调整分块策略;若命中内容本身是相关的,但最终答案不佳,瓶颈很可能在排序或生成阶段,例如正确答案排在候选列表之外,或上下文窗口里被无关内容占据。可以做一个小样本来区隔:用一个强模型把候选块重新排序,如果答案质量提升,就说明重排序阶段需要加强。
排查时建议给每个环节加上日志埋点:记录查询、候选片段的ID、得分、最终引用块和最终回答。最初几天可能觉得繁琐,但在真实场景里这套日志是救命的。不求一次到位,但至少要把定位成本降下来。
5.2 幻觉与引用错误并不是模型单方面的问题
判断“幻觉”时不要急着去怪模型,很多时候源头在检索链路上。如果知识块本身就互相冲突,比如A文档说方案已上线,B文档说方案仍在测试,模型生成哪一种表述都算“忠于原文”,但用户视角看就是一条错误信息。这里需要引入一致性消歧逻辑:在入库阶段对文档来源进行分级和时效性标注,在生成阶段优先引用更可信、更新的来源。
引用错误的另一个原因是片段切得不够完整。模型引用到了一个只有半句话的块,自然无从判断这段文字到底想表达什么。与其在Prompt里反复要求“只能基于上下文回答”,不如从入库阶段就消除残缺的上下文片段。我通常用一个不讨喜的标准来衡量:能不能把被引用的那段单独拿给一个不了解业务的人看,对方是否也能理解它在说什么。达不到标准,就要返回去重切,这是最常见的间接责任,也是“进阶”这两个字最实在的体现。
5.3 性能与成本的平衡经验
进阶系统必然要考虑成本。首当其冲的是向量化与重排序带来的推理开销。文本数量在百万级以内时,用GPU跑Embedding是可行的;超过这个规模,建议优先考虑分批入库、增量更新,而不是每次全量重算。另一个被忽视的点是Rerank的调用频率,不少团队在每轮查询里都做一次全量重排序,计算量很大,效果未必有显著提升;可以先用向量召回Top 50,再用重排序模型截断到Top 5,能达到一个比较理想的平衡。
表的出现本身就是知识库体检:只看指标,太敏感容易盲目调参;不看指标,则根本无法衡量迭代是否有效。我建议至少维护一个包含50至100条真实历史问题的评测集,每次改动都跑一遍,把“命中率”和“完整率”两个数字盯住,逐步逼近最终上线标准。
6. 选题与交付:复盘“专栏”这套做法本身
6.1 每个主题必须留一个可复现的切入点
这套专栏策划除了分享技术知识,还是一份内容产品化方法论的记录。做技术分享的人经常写“万金油”文章,却发现读者很难实际应用。这次我做了一个不同以往的决定:每一篇都必须包含一个“从零能跑”的最小项目,无论讲解的主题多复杂,都给出相应的实现线索,读者缺的既不是高深理论,而是一个足够小的入口。
比喻来说,做菜教程如果只讲火候原理,不讲今天该放几克盐、几分钟翻面,读者看完照样不会动手。我不需要保证你复现的结果一定出色,但至少要保证路径更完整。哪怕读者从头到尾只用我给的方案跑通了一个特别小的问答场景,也比看了十篇“高级架构剖析”更有意义。
6.2 失败案例比炫技更值得写
写进阶内容很难避开“惊艳效果”的诱惑。展示酷炫技术当然能带来流量,但给读者的参考价值反而不高。解决这个问题的办法,是把“失败案例”作为一个主要素材池,对自己做技术优化时踩过的坑进行存档。很老套但很有效的办法是随手记录:版本升级带来的行为变化,某个参数异常导致的持续性失败,某类文档反复导致的分块偏差,这些积累起来就是专栏里最受欢迎的部分。
我在内部复盘时发现,分享“撤销某个策略后指标下跌的过程”往往比单纯分享策略本身更能帮助读者举一反三。因为失败中通常包含统计信息,也让读者知道“不能只看一个成功案例就下结论”。这个认知贯穿了专栏的整体基调,大大减少了“照抄即所得”的错误预期。
6.3 把专栏当作评测集来迭代
技术本身在快速变化,专栏内容如果是一次性写作,很快会过时。所以我会像维护一个知识库评测集一样维护这个专栏:每个主题发布后,记录读者的反馈、提问和项目复现情况,再回到目录规划里调整下一篇的重点。比如“Mac上搭建”这篇如果收到大量“安装依赖报错”的反馈,下一篇就必须补上环境排查专题。
同样,读者提问也能反向暴露文稿本身表述不清或隐藏前提漏洞的问题。把专栏当产品做,脚下就有了支撑,不会越写越偏;写技术文章如果只想表达自己,很容易越写越像个人秀,无法解决别人真实的问题。保持这种循环,既是个人知识体系的迭带,也是一个合格内容项目的日常运营状态。