早几年做大模型应用最尴尬的一件事不是模型答错而是模型太会“一本正经地胡说八道”。问一个内部知识库的问题只要语料里没有它就能现场编一个答案给你还编得逻辑完备、细节丰富。所以当基于RAG基础技术的问答方案开始在圈子里面传开时我的感觉是这才是把大模型拉回现实世界干活的正路。所谓RAG基础简单说就是检索增强生成让模型在回答问题之前先从外部知识库里把相关内容捞出来再结合这些内容组织语言。它解决的核心问题就是模型的知识截止时间、幻觉问题、以及私有知识无法入库的问题。这篇文章想把RAG的底子掰开揉碎讲透适合刚接触大模型应用、团队准备做知识库问答、或者想搞懂检索和生成怎么配合的人看完你应该能自己搭一条完整链路。我最早接触RAG基础这套东西是从一次业务痛点开始的。当时要给某公司内部做一套制度问答系统整个部门最担心的就是模型胡说八道。法规条文这东西错一个字都不行。后来查了不少材料发现大家普遍的做法就是RAG基础四件套切分、向量化、检索、增强生成。听起来不复杂但真正把这个链路做到稳定可用中间踩的坑比想象中多得多。1. 内容整体设计与思路拆解1.1 为什么需要RAG而不是微调很多初次接触RAG基础的人第一个问题都是既然模型知识不够为什么不直接微调这个问题其实决定了两条完全不同的技术路线我简单把两件事的差异讲透。微调本质上是修改模型的权重让模型在训练过程中记住你的数据。它的优势是模型能够真正内化某些能力风格比如让模型学会你的文档格式、回答口吻、某种特殊任务的操作逻辑。但微调有两个很现实的问题第一成本高每一次数据更新都要重新训练训练还需要GPU资源和高质量标注数据第二它不擅长处理“经常变化”的知识比如公司制度、产品文档、价格表这些随时会改的东西你不大可能每隔几天就重新训练一次。RAG基础走的是另一条路不改变模型本身的参数而是把知识外置到数据库里问答时先做一次检索把检索到的相关内容拼进提示词再让模型基于这些拼接的上下文去生成。它的最大优势是知识更新几乎实时替换数据库里的内容就完成了一次“知识更新”还不用动模型。此外检索到的内容还能附上来源用户可以直接核验答案这一点在合规场景下特别重要微调做不到。用生活里的类比说微调像是把菜谱背进脑子里以后做菜全靠记忆RAG基础像是做菜时手边放着菜谱每做一步就翻一下。背书容易记错翻书虽然慢一点但准确率高得多。所以现在绝大多数知识库问答系统首选方案都是RAG基础微调只用来调模型调性两者不是互斥的但启动时优先做一个简单的RAG基础方案一定是性价比最高的。1.2 理解RAG四条核心链路RAG基础有一条主链路拆开看就是四个环节知识源处理、向量化索引、检索召回、生成增强。知识源处理把原始文档切成合适大小的文本块这一步决定了后面检索召回的上限。切大了噪音多切不中关键信息切小了信息碎片化上下文不够。向量化索引把每个文本块用嵌入模型转换成向量存进向量数据库。这条链路的核心是选择一个能准确表达语义的embedding模型让相近语义的文本在向量空间里距离相近。检索召回用户提问时把问题也向量化然后在向量库里找最相似的一批文本块这一步是所有RAG基础效果好坏的分水岭。生成增强把召回的文本块和用户问题组装成提示词交给大模型生成最终答案这一步同时要做提示词工程告诉模型“只依据给定材料回答不要自己编”。这四个环节环环相扣前一个环节的下限决定了后一个环节的上限。我见过很多团队在生成环节拼命调提示词但检索回来了一堆不相关的内容怎么调提示词都没用。所以推进RAG基础项目时一定要按照“先搞定知识源处理再验证检索质量最后调整生成”的顺序来不要跳过中间环节直接追求最终答案的炫酷效果。1.3 这套方案帮我们解决了哪些场景问题把RAG基础落到具体业务里它的应用场景比想象中广泛。我能想到的至少包括这几类。第一类是内部知识库问答。员工拿着制度文档、技术手册来问传统搜索只能返回翻了的文档链接而RAG基础可以直接给出一个精准的答案段落。第二类是客服机器人。把商品介绍、退换货政策、常见问题做成知识库机器人就能回答大部分用户问题还有引用来源客服压力能大幅减轻。第三类是软件文档助手。开发者问接口怎么调、配置项是什么意思助手可以直接从最新版本的文档中检索并给出答案这比让开发者自己翻几百页文档效率高太多。第四类是工单分析辅助。历史工单里有大量解决方案的记录把工单文本做成知识库新问题来了先检索相似旧工单给客服提供参考处理建议。用一个实际经历来说明这个方案的合理性。某公司想把过去五年积累的项目复盘文档变成可查询的资产文档类型五花八门的有Word、Markdown、PPT里的文字、还有扫描版的PDF。直接让大模型对着所有文档全文生成答案根本不可能上下文长度有限不说模型还会被无关信息干扰。做成RAG基础方案之后文档统一切分入库每个回答都能准确溯源到具体的复盘文档流程才真正跑通。2. 核心细节解析与实操要点2.1 文档解析这块很多人都会低估RAG基础链路第一件事就是要干净地拿到文档里的文字。这块听着简单实际操作里反而是翻车率最高的环节。PDF那种扫描版的文件直接用常规的文本提取工具出来全是乱码必须用带OCR功能的解析工具。公司里日常流转的文档大部分又是Word或者WPS里排版出来的里面带着页眉页脚、目录、表格处理不好切分时就会把无关信息切进文本块。我养成的习惯是把所有文档先统一转成纯文本或者Markdown格式再做清洗。清洗的阶段至少要做这几件事去页眉页脚、去重复标题、识别表格并且把表格转成行列结构体的文本、去掉图片占位符。常见的一个误区是图像里的文字转成文本之后OCR识别出的顺序是乱的。这时候需要在清洗阶段按规则重新排序别看这种问题小它直接影响后面切分的连贯性。我在某个项目里遇到过一次情况——一份产品手册里的操作步骤是图文混排的OCR把图里的字全抽出来了顺序完全不是阅读顺序最后检索落库的内容根本不能看。另外一个容易踩的坑是文档版本。很多公司的知识库里同一份制度有多个历史版本不做版本管理就都丢进索引用户问一个问题检索回来三个版本互相矛盾的答案。这个问题的根治办法是在知识源处理阶段就把“生效版本标志”一起切进文本块并且在上层搜索时按版本号过滤。虽然这属于业务规则层面的改动但RAG基础的知识源处理阶段就应该留出这个意识。2.2 切分的粒度有讲究切分决定了单元文本块的大小和重叠度这是RAG基础里最有“经验”味道的一个环节。切分方式大概可以分成三类各有各的场景。第一种是固定长度切分。不管内容是啥就按一定字数切再带上一个重叠窗口比如512个字切一块、隔128个字重叠一次。这么做的好处是简单、规则统一、代码量少适合通用型的知识库缺点是很容易把一句话从中间切开把一个完整的事实拆成两半检索时语义容易断。第二种是分隔符切分。按换行、句号、章节标题来切尽量保持段落和句子的完整性。这种做法的召回连贯性比固定长度切分好很多是目前最常用的方案。实现的时候可以按九个字符左右的长度估算优先以标题层级作为边界再按段落切最后处理超长段落。第三种是语义切分交给模型或者机器学习算法来判断哪里是语义边界。质量是三种里面最高的但成本也最高处理大语料时更贵更慢。我自己的折中方案是先用分隔符切成较小的自然段落然后用嵌入模型给相邻段落算相似度相似度低的地方就作为切分边界。这样既能保持语义相对完整又不用花全量语义切分的钱。切分粒度还需要跟最终要回答的问题形态相匹配。如果你的问题是“这个产品的退货政策是怎么样的”那答案可能分散在好几个段落里切太小编码不了得配合检索多个文本块合并上下文来用如果你的问题定位很细比如“某个按钮的作用”那大段落反而检索不精确。所以最稳妥的做法是把文档按尽量小的语义单元切成块检索时多召回几块拼起来让生成模型自己判断怎么组织。2.3 嵌入模型和向量库的选型心得嵌入模型embedding model的质量很大程度上决定了检索的天花板。这里有个基本结论不要随便用普通文本相似度的标准去选嵌入模型中文场景建议用面向中文语料训练的嵌入模型或者重点关注在中文检索评测集上得分高的开源模型。选模型的时候我会建议至少做两样测试相似句子召回测试和主题混淆测试。相似句子召回测试是拿一批语料里相近但不同的句子看看模型能不能区分它们主题混淆测试是把常识性强的话题和高相似度但不同含义的文本放一起看检索能不能精准召回想要的。向量数据库的选择本质上是个工程权衡。如果你处于学习或者原型验证阶段用支持本地文件模式的轻量向量库就够了零部署成本往Python工程里一扔就能跑。如果是生产环境并且数据量到了百万级向量以上再考虑走服务化向量数据库或者云上的向量检索服务分布式搜索性能和扩展性都更稳。我在原型阶段吃过亏一开始就上了重型服务配置半天分布式参数结果发现几十万条数据用轻量方案几分钟就导入完。先原型后生产别在开头就过度设计。向量库选型的另一个关键指标是混合检索能力。只做向量检索应对不了“关键词精确匹配”的场景比如用户搜了一个产品型号“XK-2024”这串内容在向量空间里不一定能得到最好的相关度但用关键词检索能精确命中。成熟的RAG基础方案现在普遍做混合搜索向量检索叠加全文关键词检索再用结果融合算法把两路结果合并起来。你在选型时注意留这个能力的接口。2.4 提示词增强的写法原则RAG基础最后一步是生成这一步拼的就是提示词工程。同一个检索结果提示词写得好不好回答质量天差地别。我总结了一套基本的增强提示词结构可以按这个底子去改。基本要点有三个一是明确告诉模型“只依据下面提供的资料回答”这是抑制幻觉的关键指令二是告诉模型“如果资料中没有相关信息直接说不知道”这一条比前面那条还重要却最容易被人忽略三是要求输出时附带引用片段或者来源标记方便使用者核验。实际生产时我还会再加几条细节规定回答的语言风格比如“面向普通用户回答要简练”或者“面向技术开发人员回答要给出代码示例”规定回答的边界比如“不回答与产品无关的问题”还有一点容易被忽略的——把用户问的问题与检索文本之间出现的矛盾单独拿出来提醒“如果给定资料之间有冲突请指出冲突之处并给出你的判断”。提示词不是写一次就完了每次调整检索逻辑都可能需要重新审视提示词。我见过一个团队召回了完全靠谱的上下文但提示词里忘记加“不知道就说不知道”的规则模型依旧兴致勃勃地补完全部细节。这条规则单独占一行直接写清楚别混在金句里。3. 实操过程与核心环节实现3.1 环境搭建与工具准备做RAG基础原型环境其实不需要特别重型的装备。一台开发机器装好基本的运行环境就行。整个链路主要依赖四类东西文档处理库、嵌入模型、向量存储、大模型推理接口。我先列一个我能直接上手的环境清单给你做个参考开发语言Python生态最全。数据预处理文档解析用编辑器或者文本解析库OCR识别用扫描件识别库表格抽取识别文本结构后再手动规整。嵌入模型选择开源中文嵌入模型下载到本地用加速工具跑推理。向量存储原型阶段用轻量向量数据库生产再切换服务化方案。大模型可以接本地部署的对话模型也可以接云端推理接口看你的隐私要求和成本预算。安装这些依赖本身不花多少时间真正花时间的是下载模型和调试文档解析流程。我建议第一次跑通全程不要追求完美先用一个小知识库几十条文档就行跑通检索再逐一环节优化。3.2 先做最小闭环再逐步优化第一次做RAG基础的时候最忌讳一上来就搭一个大而全的平台。我习惯的做法是先做一个最小闭环也就是把“读文档-切分-向量化-检索-生成”全链路用最简单的代码跑起来哪怕效果很粗糙至少眼见为实。具体做法是先把十几份文档切分成文本块存放在本地文件列表里直接调用嵌入模型的接口逐个转成向量再把向量和文本一起存进向量数据库。在提问侧把用户问题同样做向量化然后去库里查询TopK个最相似结果拼进提示词调用大模型回答。这个过程其实就几十行代码的核心逻辑但能完全验证链路是否通。验证通过后再引入文档解析增强、重排序、混合检索、提示词优化这些进阶模块。每一步加进去以后都要用同一批评测问题来对比效果不要凭感觉觉得“好像变好了”。我自己维护了一个固定的评测集三十个问题覆盖“简单问答”“复杂多跳问答”“文档中不存在答案的提问”“需引用的提问”四类每次改链路都跑一遍用答案准确率、召回率、错误引用率三个指标做记录。这算是RAG基础工程里最实用的小习惯。3.3 一个具体实现示例从文档切分到生成回复下面给出一段从文档加载到检索生成回复的伪代码流程不依赖特定框架方便你看清楚核心逻辑。# 1. 加载并清理文档文本 with open(knowledge.txt, r, encodingutf-8) as f: content f.read() # 2. 基础清理去多余空行、页眉页脚标记 content clean_text(content) # 3. 按自然段落固定阈值切分 chunks split_by_paragraph_and_size(content, max_len500, overlap80) # 4. 嵌入模型加载伪代码示意 embedder load_embedding_model(local-chinese-embedding-model) # 5. 逐块向量化并入库伪代码示意 vector_store init_vector_store() for index, chunk in enumerate(chunks): vector embedder.embed(chunk) vector_store.add(idindex, vectorvector, textchunk) # 6. 用户问题检索 question 退货政策中的包装要求是什么 question_vec embedder.embed(question) top_k_results vector_store.search(question_vec, top_k5) # 7. 组装长文本上下文 context \n---\n.join([item.text for item in top_k_results]) # 8. 生成提示词并调用大模型 prompt f 请根据以下资料回答问题。资料中找不到答案时请直接说“资料中未提及”。 资料内容 {context} 用户问题 {question} # 9. 将prompt发送给大模型并输出内容 reply llm_complete(prompt) print(reply)这个流程看着很简单但请千万别小看它。生产级的RAG基础系统所有复杂功能都是在这个基础上长出来的比如增加重排序模型对召回结果二次打分、增加引用溯源标注、增加多路召回融合本质上都是在这一套主流程里增加处理环节。我还会多说一句切分结果要不要存成缓存如果你用的是本地文件或者能保存的向量库建议把切分好的文本块和向量都持久化不然每次改一个文档参数全量重新向量化很浪费时间。这个看起来小的优化能给你迭代开发省下大量时间。3.4 用重排序把质量再抬高一段重排序是我在所有RAG基础项目中都强烈建议加进去的模块也是从“能跑”迈向“好用”的关键一步。基本思路是向量检索阶段为了确保召回率会尽量多捞一些结果上来比如Top20但这些结果里可能有一半是勉强相关。这时用一个重排序模型把20条候选重新按相关度打分只保留Top5给大模型。为什么这能起作用因为向量检索和重排序模型的目标不一样向量检索负责把“语义相似”的找出来重排序模型负责精排“与用户问题最匹配”的。有些文本块跟问题角度看过去相关实际内容完全不解决问题这种方式就能滤掉。实际参数上面我从经验出发给一个配置参考检索召回Top20-30重排序后保留Top5-8重排序模型的运行比嵌入模型贵很多所以让它精排数量较少的候选集正合适。引入重排序的性能提升在评测集上的准确率往往有10到20个百分点左右的变化这个提升幅度远比你换一个更大的大模型来得明显而且成本低得多。3.5 评测知识库问答质量的三个维度做RAG基础要是不评测你就是每天都在盲人摸象。我给自己定了一套最简单的评测维度供你参考答案是准确性引用是有无依据拒绝是合理沉默。很多团队做演示的时候模型答得头头是道一测真实场景就露馅核心就是没有评测闭环。怎么建评测集把业务里真实高频的问答沉淀出来先找客服或者运营要历史记录挑出三十到五十条代表性的问题再手动写好标准答案。每周跑一轮评测记录每个问题的回答是否存在幻觉、是否缺失关键知识点、拒绝类问题是否真的拒绝。评测这事不玄妙关键在坚持。4. 常见问题与排查技巧实录4.1 检索啥也搜不到的三种原因检索是RAG基础中最容易出问题的地方而且症状非常单一搜出来的内容跟问题完全不搭边。大部分情况可以按下面三种原因逐一排查。第一种是嵌入模型跟文本语言或者领域不匹配。比如你做的中文垂直领域知识库选的却是以英文语料为主的嵌入模型它根本表达不好中文的语义或者你选了通用模型但你的语料里全是专业术语和代码模型没见过这些词向量表示就会很诡异。解决办法是换模型然后跑一组相似问题测试比对后再定。第二种是切分粒度不当。切出来的块太碎每个块只包含半句话根本表达不了完整信息。比如制度条文里的“但书条款”跑到下一个文本块里了检索自然搜不出正确内容。解决办法是检查切分结果直接在控制台把文本块打印出来看一遍肉眼就能看出切得是否合理。第三种是查询问题本身太长或者太模糊。向量检索本质上用向量距离度量相似度问句“你能跟我说说相关的事情吗”这种没有任何关键实体的模糊问题它不知道要匹配什么。解决办法是对用户输入做关键词抽取或问题改写用重写后的查询去检索。这一步在生产系统里很有价值人的提问习惯实在太随意了。4.2 模型还是胡说八道的三个排查方向加了RAG基础之后模型还胡说八道这种情况十有八九是上下文里混进了错误信息。你排查时按下面这三个方向走比反复改提示词更有用。方向一检索到的高排位文本块本身不相关。向量召回不是百分之百准确它不仅会召回高相关的结果也会带一些“语义相似但文不对题”的噪声块。如果这些噪声块排在前面大模型就会结合它们联想去回答。这个问题的解法是引入重排序模型把噪声块过滤掉一些。方向二切分文本块里混入了相互矛盾的内容。比如制度有两个版本都进了库一个问题检索出了新旧两个版本的对应段落模型不知道听谁的就会自己做一个“折中解释”这个行为就是幻觉。解法是在文本块里加版本上下文信息或者在提示词里明确要求“资料冲突时优先采纳日期更新的一条并说明”。方向三上下文里虽然相关但缺少关键数字或者细节。比如用户问“每周保养几次”检索到的文本只说了“保养频率视设备状态而定”没有具体数字。这种情况下模型容易根据常识补一个数字。解法是优化切分粒度确保关键信息密度高的文本能被完整切进来或者提示词中严格限制不补充未提及信息。4.3 对话变长之后效果下降的问题对话场景中的RAG基础还有一个常见问题多轮对话累积上下文之后模型越答越偏离检索到的资料。原因是多轮历史里包含了之前用户的各种提问和回答模型在生成新回答时注意力被历史分散了。我常用的解法是给足充分的上下文但只保留与当前问题最相关的历史轮次。具体做法是对每一轮历史对话做向量化召回与当前问题相似的对话片段拼在当前问题之前。这种方法在效果上的提升是明显的尤其适合客服对话场景。另一个切入角度是精简历史只取最近一两轮对话或者对历史做摘要保留意图摘要和结论丢掉细节。RAG基础的知识检索是在开环里进行的每轮都独立检索所以让模型真正聚焦在当前问题和当前资料上比什么都重要。4.4 线上知识更新后不生效的原因如果你改了知识库里的文档重新构建索引但线上问答答案还是老的不用怀疑模型缓存基本都是索引没生效。最常见的原因是向量库里旧版本的数据没有清理干净新老数据同时存在检索时老版本排前。这个问题的排查办法是检索完打印命中的文本块究竟来自哪份文档、哪个版本对比一下就知道是不是旧数据在干扰。第二个常见原因是文本切分的缓存机制。有些方案会把切分结果缓存起来如果你更新文档时清缓存不够彻底用的还是旧切分结果。这块需要注意缓存设计的粒度切分缓存以文档哈希为键文档一改哈希就变就很容易识别。第三个原因是向量化那一步本身有随机性问题不过绝大多数嵌入模型的输出是确定性的所以问题不大直接检查向量库里有没有写入最新内容即可。我给自己立了个规矩每次更新知识库之后必打一个跟踪日志把导入的文本块数量、文档清单、版本信息全输出训练和排除效率能提好几倍。5. 进阶思考与后续扩展路径5.1 从单路检索到多路召回RAG基础做到一定阶段单靠一路向量检索就不够看了。多路召回的意思是把多种检索结果混合起来让每个检索器的强项都发挥出来。常见的多路组合方式是向量检索召回Top20关键词全文检索召回Top10再加一道基于知识图谱的检索或者基于规则的精确匹配。各路结果在融合层用分数归一化做合并最后再交给重排序模型统一精排。这套方案能有效覆盖向量检索和关键词检索各自的盲区尤其适合一些专有名词、型号、代码片段密集的行业知识库。有了多路召回之后还需要关注融合权重怎么调。我习惯先把各路召回结果单独放到评测集上跑一遍准确率测出各自的上限再根据场景调节各路权重。调权重的过程记录下来方便以后换数据之后回看和重新调整。5.2 用户问题改写和意图扩展用户提问通常很随意“那个东西能不能退换”跟“七天内无理由退货申请条件”明明是一个意思但字面差异太大向量检索可能召回完全不同的结果所以问题改写几乎是必做的一步。一种改写策略是让一个大模型把用户问题改写成适合检索的关键词组合。比如用户问“那个东西能不能退换”模型改写为“退货申请条件”“七天无理由退换规则”。改写之后的查询再去向量检索召回效果会有可观提升。另一种策略是做同义词扩展和缩写还原。比如“医保”扩展成“医疗保险”“RAG基础”扩展为“检索增强生成基础”。扩展不能盲目做否则会引入噪声所以扩展词建议只放在检索侧不放回到面向用户的生成侧避免答案被扩展词带跑。5.3 引用的价值不只是“合规”现在很多RAG基础项目都会要求模型输出引用来源因为内部知识库问答的业务方最关心的就是答案有没有出处。引用来源可以在切分文本时给每个文本块打上文档编号、版本、页码生成时让模型把对应文本块编号附在回答后面。但引用的真实价值不止是让业务方放心它还能成为评测工具当你发现模型输出了一个带引用但看起来可疑的答案你点开引用材料看看立刻能判断问题出在检索还是生成环节。时间长了你会总结出一批常见错误模式比如“模型引用了正确的来源却编造了来源中没有的数字”这些经验都是纯提示词调参调不出来的。5.4 知识库冷启动和更新策略最后聊一下把RAG基础投入生产时最常见的问题知识库冷启动和持续更新。冷启动阶段语料不足是个很大的麻烦。我建议优先处理高质量、结构清晰的文档先把顶层框架建好比如FAQ、制度手册、产品手册这些。不要把大量噪音很高的扫描件和格式混乱的表格一股脑灌进去否则索引质量整体被拉低后面清理成本很高。先小后大先精后全。更新策略上有两种常见模式全量重建和增量更新。知识库体量不大的时候全量重建最简单可靠每天夜里定时跑任务把全部文档重切重索引就行。到了百万级文档以上全量重建的耗时就变得不可接受这时再用增量更新策略只处理新增和修改的文件删除旧数据再写入新数据。增量更新的逻辑要特别注意文档版本管理要确定更新的粒度是按文档整体更新还是按段落级别更新。生产级RAG基础平台上跑了大半年之后我自己的体会是这个方案最大的优点不是某个单独环节有多强而是整条链路的每一环都有优化的空间而且优化方向非常明确。你遇到问题总能在链路某一个环节找到原因这种“可排查性”在技术选型时最容易被低估。如果你正在准备上手做RAG基础不要怕一开始效果不理想先把小闭环跑通再用真实验证和评测数据把每一个环节打磨到位这条路走完你会觉得大模型应用的地基其实并不玄学就是扎实的工程活。