1. 一个老问题模型“一本正经地胡说八道”做 AI 应用开发的人几乎都遇到过这种场景你问模型一个比较具体的问题它回答得流畅、自信、结构清晰看起来毫无破绽——但实际上完全是编的。比如你问某公司某产品什么时候发布它能给你答出详细日期和发布会地点哪天确认下来发现根本没这事。这就是大模型圈子里常说的“幻觉”Hallucination。我最初做智能问答项目时也栽在这个问题上。当时直接用一个通用大模型做客服机器人用户问产品退换货规则模型能头头是道地讲出一整套流程甚至具体到“需要填写某某表单”。但公司压根没这个表单。用户真的照做体验直接崩掉。后来我把模型换成微调版本情况好一些但依然不稳。微调能教会模型“说话的腔调”但没法把公司所有动态变化的业务数据灌进它的参数里。产品规则、库存信息、售后政策这些内容本身就是高频变动的模型根本做不到持续同步。那段时间我反复在想一个问题能不能不强行让模型“记住”所有东西而是让它在回答之前先去查一下资料这个思路最终落地成了 RAG也就是检索增强生成Retrieval-Augmented Generation。说直白点就是让大模型回答前先“查书”查到的内容作为依据再组织语言回答。它的核心作用就是把“闭卷考试”变成“开卷考试”从机制上把幻觉降下来。这篇文章我会把整个 RAG 项目的设计思路、落地过程、踩过的坑和优化经验完整拆开讲一遍。如果你是做 AI 应用开发、正在被幻觉问题折磨或者刚接触 RAG 想找个能参考的实战案例这篇应该对你有帮助。2. 回答前先翻书RAG 的整体设计思路2.1 为什么不是“继续微调”很多人的第一反应是幻觉是因为模型学得不够那我再喂数据微调不就行了这个思路在某类场景下有效比如让模型学习特定的“文风”或“对话格式”。但换到知识密集型场景问题就来了。举个例子某公司内部有几千份业务文档规则还在不断更新上个月还能退换的商品这个月起可能就不能退了。如果你把知识微调进模型参数里每次规则一变都得准备数据集、重新训练、评估、上线整个链路跑下来至少几天。而 RAG 改一条文档、重跑一遍索引几分钟内知识就生效了。从成本上看微调一批参数动辄几万块钱的算力开销换来的是“模型记住了某句话”。RAG 则是把知识外置模型只需要学会“怎么使用资料”知识内容本身可以随时替换。另外还有一个更本质的问题。微调是在“模仿”模型学到的是一种概率分布它无法精确区分“这个规则只适用于某个业务线”还是“这个规则适用于所有用户”。但 RAG 不同——它把上下文直接放进提示词里生成时模型能真实地“看到”资料原文回答的依据是具体的段落而不是模糊的记忆联想。我当时做技术方案对比时用了这样一个判断标准如果目标是“让模型变成某个领域的人设”——选微调如果目标是“让模型准确说出某个领域的事实”——选 RAG两者也可以结合底层用微调控制表达风格上层用 RAG 注入事实知识我的项目最终选择“轻微调 重 RAG”的组合。微调部分只花了一个周末训练用来调整回答语气和格式知识部分全部走 RAG业务规则更新只需要替换文档库即可。2.2 RAG 的核心流程拆解整个 RAG 流程可以分成几个环节知识库预处理、嵌入化、检索、增强提示、生成回答。用“查书”来类比就很好理解。你是一个博学但健忘的研究员别人问你一个问题你不会凭记忆瞎说而是先跑去图书馆查资料。查的时候你不会从头翻到尾而是先查目录、查索引找到最相关的那几页翻开来仔细看再结合自己的语言组织能力把答案讲出来。对应到系统实现上知识库预处理把文档切分成小块每一块就是一个“知识点卡片”嵌入化把每个卡片转成数学向量不同卡片按语义远近排列在“向量空间”里检索用户提问时先把问题也转成向量去找和问题最接近的卡片增强提示把找到的卡片原文拼进提示词告诉模型“资料如下请基于资料回答”生成回答大模型基于给定资料和用户问题生成最终输出这里面有两个“为什么”值得展开。为什么要把文档切块因为大模型的上下文窗口是有限的不可能把整本手册都塞进提示词。而且检索追求的是“精准找到关键段落”而不是“检索一整个章节再让模型自己找重点”。切成小块之后每块字数可控检索时命中率更高也不会浪费上下文空间。为什么要用“向量”做检索因为关键词检索只能匹配字面相同的词语义检索靠向量可以识别“换个说法但意思相同”的句子。比如用户问“这手机防水吗”文档里写的是“支持IP68级防尘防水”字面上一个词都对不上但向量距离上很接近这种能力对问答体验的提升非常明显。2.3 一条查询的完整旅程我把自己项目里一次真实查询的完整链路记录一下方便你建立直观的体感。用户问“笔记本电脑保修期内维修需要带什么”这个问题的处理过程如下第一步问题嵌入化。系统调用嵌入模型把这句话转成一个维度为 768 或更高维的向量向量中的数值对应这句话在语义空间中的坐标。第二步向量检索。系统拿这个向量去向量数据库里做相似度计算找距离最近的候选块。我们项目中设置的是先召回 Top 20这 20 块来自不同篇文档涵盖了“保修政策”“维修流程”“客户须知”等多个分类。第三步重排序。这一步是 RAG 的进阶操作。Top 20 里很可能有内容重复或者相关性不够高的块如果全部塞给模型会稀释注意力。我们部署了一个交叉编码器模型把每块“被检索文档”和“用户问题”成对输入模型逐对打分从 20 块里筛出最相关的 Top 5。第四步构造提示词。系统组装出一段结构系统提示部分设定角色和回答规则 资料部分贴上筛选出的 Top 5 块原文来源文档名标注在每段前面 用户问题部分原样放入第五步模型生成。模型阅读资料后组织出一个自然回答带保修卡和发票需提前在官网预约网点检测后确认问题属于保修范畴即可免费维修。整个过程端到端耗时大约两秒其中检索加重排序占 300 毫秒左右生成占 1.5 秒左右。用户感知就是一问一答但内部已经完成了“查书再作答”的完整闭环。3. 落地实操从文档到向量库的全链路搭建3.1 文档处理与切块策略RAG 效果好不好一半以上取决于文档预处理做没做好。我最早犯过一个错误拿 PDF 直接切结果大量段落被拦腰截断检索出来的内容前言不搭后语。正确的流程是先做文本清洗再做结构化识别最后才切块。文本清洗是指把文档里的多余符号、乱码、页眉页脚、水印内容去掉。这一步看似简单但实际非常琐碎。PDF 解析出来的英文单词可能被硬拆成两行、表格结构会变成一堆空格加字母。我是先按文档类型做了分流PDF 用专门的解析库提取Word 用文档转换库HTML 走抓取清洗统一转成 Markdown 或纯文本格式再进入后续流程。切块策略上我最开始用的固定字数切块设定 512 个字符切成一块。跑了一轮发现问题很典型有的块正好切开一个意思完整的句子检索时模型只能看到一半有的块全是列表项语义不完整。后来我改成了“结构化感知切块”具体做法是先按文档标题切分再按段落切分然后按句子边界修正切块位置。每个块尽量是一个完整语义单元。经验参数参考下面这个表文档类型推荐块大小重叠长度说明产品说明 / 操作手册300-500 字50-100 字段落结构清晰按小节切即可政策制度 / 法律文本200-300 字50 字条款独立小块精度高技术文档 / 代码注释500-600 字100 字上下文依赖强需保留衔接问答对 / 聊天记录每条独立0直接按条切重叠长度的作用让相邻块之间保留一部分重合文本避免关键词被切在边界上导致两边都搜不到。我的经验值是固定字符切块用 10%-20% 的重叠率语义切块用 5%-10%重叠太多会加剧索引存储和检索噪音。3.2 嵌入模型选型与向量索引构建切好块之后下一步是把每个文本块转成向量。这一步的“模型选型”直接影响后续检索质量。我的选型标准是三条中文语义理解能力足够好、向量维度适中不浪费存储、本地可部署不依赖外部服务。为什么强调本地部署因为企业知识库涉及内部资料把文档内容通过第三方嵌入模型服务传输本身就存在数据安全风险。我最终选用的是开源的中文嵌入模型部署在一台带 GPU 的服务器上跑离线批处理。实测下来它对长句、反问句、业务专有名词都能给出符合直觉的语义向量。嵌入模型本身不大的话用 CPU 跑批处理也能接受。比如一个 1 亿参数的嵌入模型用 CPU 处理一万篇短文档大约需要几十分钟项目初期完全可以接受。如果文档量大且更新频繁再上 GPU 也不迟。向量构建完成后把向量和原文元数据一起存入向量数据库。我当时的选型考虑过专业向量库和传统数据库加向量插件。项目规模不大最终选了轻量的、支持向量检索的数据库方案一条记录保存三类信息向量数组、原始文本块、来源元数据文档名、页码、更新日期。存储结构大致是-- 简化后的向量表设计 CREATE TABLE doc_chunks ( id INTEGER PRIMARY KEY, doc_name TEXT, -- 来源文档名 chunk_content TEXT, -- 原始文本块内容 vector_embedding VECTOR(768), -- 嵌入向量 created_at TIMESTAMP );建完索引之后我写了一个本地测试脚本随机拿问题去检索人工检查返回结果的相关性。这一步能帮你快速发现“嵌入模型不适配你的领域”或“切块太小导致语义不完整”这类早期问题不用等系统全部搭完才回头返工。3.3 检索方案从单路向量到混合检索只用向量检索能解决大部分语义匹配问题但实测中我发现还有一个盲区精确关键词。比如用户问“移动平均线是什么”文档里写的是“MA 移动平均线指标”。语义向量可以把“移动平均线”匹配到“MA”但如果用户直接问“MA是什么”向量检索的结果往往不如关键词检索来得精准。反过来用户用口语描述问题时关键词检索又匹配不上。所以我的最终方案是混合检索Hybrid Search同一问题同时跑路向量检索和路关键词检索BM25 这种词频算法然后把两路结果的得分归一化后加权融合。融合逻辑不复杂。每路检索都返回一组命中文档及其相似度分我做归一化处理得分减去该批最小值除以最大值减最小值把分数压到 0 到 1 之间然后按权重相加。两个搜索会找到相同的命中项则特殊处理匹配命中则加分。然后取总分排序的 Top N 作为最终候选。这套方案上线后一个明显的变化是“精确词命中”和“语义理解”两个场景都能兼顾。用户问“换货要发票吗”混了关键词检索后包含“发票”字样的文档被加权召回准确率比纯向量检索高了几个百分点。4. 最核心的环节构造提示词与生成控制4.1 提示词的结构化模板RAG 的“生成环节”常见误区是把检索到的一堆文章整段丢给模型然后说一句“请回答”。效果通常很差因为模型不知道“哪段资料对应哪个话题”也不知道“资料里没有的内容该怎么处理”。我最终的提示词结构分四层。第一层是系统角色设定告诉模型它是什么角色你是某公司智能客服助手只能根据提供的内部资料回答用户问题回答自然友好。第二层是检索资料区用明确的标识符包裹以下是内部资料原文来源于知识库检索结果。资料与用户问题之间以分隔符标识。第三层是回答规则逐条列出约束仅基于资料内容作答资料未提及的内容明确说明无法确认。回答须提取资料关键信息不重复资料全部原文。引用资料时标注来源文档名称。不确定时不推测避免编造。第四层是用户问题原样呈现。实际模板的简化示意如下系统: 你是企业智能客服。严格依据检索资料回答问题。 资料: [资料1] 来自文档《售后政策_v3》保修期内用户需提供服务发票或购买凭证。 [资料2] 来自文档《售后政策_v3》人为损坏不在免费保修范围内。 规则: 1. 只根据资料内容回答。 2. 资料中找不到答案时明确告知用户无法确认。 3. 回答末尾标注依据的资料编号。 用户: 保修期内维修要带什么这套结构里最关键的是“回答规则”那部分。你可别觉得是废话——模型非常容易顺着“资料”的语感走如果你不强调“不推测”它很可能在资料没提到的地方自己补充一段合理但错误的内容。4.2 温度参数和最大生成长度的调节“查完书再回答”并不等于完全禁用模型的创造力。温度参数控制的是输出概率分布的平滑程度温度调低模型倾向于选最高概率的词输出更确定温度调高模型更愿意“发散”输出更丰富但更不可控。在 RAG 场景下我的经验是温度设置在 0 到 0.3 之间。0 的结果最稳定但回答会略显生硬0.3 时回答更自然幻觉风险依然可控。如果超过 0.5就算给了资料模型也偶尔开始发挥某次实测中它甚至编了一个文档里不存在的售后网店地址。不要用高温度搭配 RAG这是很多新人在“回答生动性”和“准确性”之间找平衡时会踩的坑。最大生成长度也要控制。如果你的知识库回答通常控制在 150 字以内那 max tokens 设 500 就足够设太大反而给了模型“发挥空间”长回答里更容易夹杂编造细节。配合结束词设计让模型答完即停不要继续补充。一个补充技巧是加入“思维过程”的提示。对复杂问题可以让模型先简述判断逻辑再给结论。比如规则中加一条回答前先说一句“根据资料我的理解是”有助于模型在内部先梳理一遍检索内容减少跳跃式输出。4.3 生成前的前置校验这个阶段可加可减但在我实战中价值很高。简单来说就是在生成之前做两道闸门第一道检索置信度检查。向量检索返回的相似度分数过低时说明知识库里可能根本没有相关内容。此时不硬着头皮生成而是启动另一套回复模板“抱歉知识库中暂时没有找到这方面的信息请稍后咨询人工客服。”这比让模型瞎编强一万倍。第二道重排序过滤。前面提到的 Top 20 重排序筛出的 Top 5如果第一名得分依然很低同样触发避让逻辑。有人担心这样会让系统显得“笨”事实上用户在知识库确实没有答案的场景里最想要的就是一句诚实的“不知道”而不是一个听起来专业但错误的回复。这在客服场景里尤其重要——错误信息误导用户操作的代价远比“答不上来”大得多。5. 实战中的优化过程效果怎么一步步变好的5.1 评测集的建立优化 RAG 效果最怕的是凭感觉调。今天换个切块参数觉得“好像好了一点”明天换个提示词又觉得“似乎没变差”但说不清整体效果是提升还是回退。我搭了一个小规模评测集约 120 个问题覆盖几类核心场景事实查证类、规则咨询类、操作指引类、无答案类故意问知识库没有的内容。评测维度分了三个准确率人工标注正确答案后对比模型输出、忠实度答案表述是否基于检索资料而不是凭空发挥、拒答率无答案类问题中模型给出“不知道”的比例。每周固定跑一次评测把每次改动前后的结果记录到一张表里。这个习惯帮了大忙——有一次我以为重排序模型效果更好结果评测数据显示部分场景准确率反而下降了最终定位到是重排序模型对长文本块不敏感做了针对性调整后才通过了回归。5.2 向量检索的几个“隐身”短板这类问题不跑真实数据很难发现。我遇到过几个有代表性的。第一专有名词被切碎。比如某公司的产品名“智汇导航终端”切块时如果按字符边界硬切可能变成“智汇”和“导航终端”两块。“智汇”单独检索时召回了很多不相关内容。我最终是给专有名词维护了一个关键词词典在切块前做一次短语合并把整词看作不可分割单元问题解决。第二同义改写造成的语义漂移。用户说“退钱”文档里写“退款”向量模型能识别大部分。但用户说“把押金退给我”和文档里的“款项原路退回”之间向量距离就没那么近了。单纯靠模型很难覆盖所有改写变体这个问题的解法之一是在索引时额外加入同义词扩展块把“退款-退钱-原路退回-返还金额”这些表达关联起来让检索系统更容易在两路碰头。第三时间敏感信息会把检索带偏。文档里有旧版规则和新版规则向量检索只认语义不分新旧常常把已废弃的旧规则排到前面。我给索引加了一层“有效时间”过滤当前时间不在有效期内的规则检索时直接排除不回。这个逻辑逻辑简单但实用性极高做企业知识库时强烈建议加上。5.3 重排序用大模型精筛候选段落如果说向量检索是“海选”重排序就是“终审”。我在项目中期加入了重排序模型效果提升很明显。具体流程向量检索召回 Top 20 段落后把用户问题分别和每一段拼接成一句话对交给一个交叉编码器打分。交叉编码器能对“问题和段落是否相关”做出更精细的判断因为它在计算时能看到问题与段落的完整交互而不是像双塔模型那样只比对两个独立向量。我踩过的一个坑重排序打分直接排序后只取 Top 1。有时 Top 1 是“高度相关但信息量极少”的一段比如一段文档只说“见附录二”没实际内容。最终我的策略是 Top 5 都进提示词同时在提示词里让模型参考多个资料输出一个综合回答。这样既利用重排序的精度又不丢失多段信息互补的好处。6. 不够满意的部分检索增强的边界在哪RAG 把幻觉降下来了但不能归零。一种常见残漏是“资料存在但检索不到”。说到底RAG 的回答质量上限取决于“检索能不能召回到正确段落”。向量检索本质是近似搜索模型对语义的理解受训练数据和微调效果影响遇到领域性极强的说法召回还是可能出错。某次测试中用户问“月光石的保养”文档里写的是“宝石类饰品需避免接触化学品、避免碰撞、洗澡前摘下”语义距离高度相关但向量检索硬是把“月光石”匹配偏到了“月光”返回了一块完全无关的天文知识。另一种残漏是“资料本身就是错的”。RAG 只能做到“忠实于给定资料”不能替知识库做真实性审计。如果研发团队上传的文档本身写错了参数RAG 会忠实地把错参数回答给用户。这时真正需要补的就不是 RAG 能力而是知识库的产出和审核机制。看到这里应该能理解RAG 不是大模型时代的万能药但它确实以很低的成本解决了一个非常关键的问题把模型的生成能力与知识的持续更新解耦开。模型只需专注“怎么把话说好”知识正确与否由知识库负责。这个分工思路是这套系统给我带来的最大启发。7. 踩坑与心得这些细节才是决定体验的地方7.1 常见问题速查把过程中遇到的高频问题整理成表方便你直接对照排查。现象可能原因解决方案回答与资料不符温度过高 / 提示词未约束温度降到 0.3 以下规则中明确“只根据资料回答”检索结果明显不相关切块过大或过小 / 嵌入模型不适配检查切块边界换用领域化嵌入模型知识库更新后回答没变化向量索引未同步更新确认增量更新任务是否执行索引重建后重试类似问题时好时坏缺少重排序环节加入交叉编码器精筛缩小输入范围特定名词永远检索不到切成碎块 / 词向量未覆盖专有名词词典合并或添加同义扩展块资料中找到答案但回答护搪Top 1 相关但信息不足改用 Top 5 进提示词多段互证回答总说“不知道”相似度阈值过高调整阈值均衡准确率与召回率7.2 几个反常识的经验第一个反常识不是资料越多越好。把 Top 20 全部塞给模型效果通常不如精选 Top 5。信息过载时大模型会“平均用力”反而抓不住关键段落。适量的资料加上清晰的结构提示比堆砌资料更可靠。第二个反常识嵌入模型越大不一定越好。大模型嵌入能力更强但也更慢更贵。一个轻量但经过领域微调的嵌入模型在小规模企业知识库上的检索效果并不比通用大模型差多少。真正决定效果的是文档切块质量和知识库覆盖率其次才是嵌入模型选型。第三个反常识提示词写“不要编造”不如写“只引用资料”。前者是抽象要求模型不一定能落地后者是具体指令模型更容易遵循。把“禁止做某事”转换成“应该怎么做”是提示词工程里很实用的一条经验。第四个反常识评测集比算法优化更重要。没有评测集时我反复调参但无法判断好坏建了评测集之后每次改动都有据可依反而更快逼近了最佳配置。花一个下午构建评测集能省接下来两周的返工时间。7.3 更适合自己项目落地的最小方案如果你也在做 RAG可以参考我用下来的最小可行方案一个轻量开源的向量数据库做存储一个中文嵌入模型做向量化一个大模型 API 做生成再用少量脚本完成切块、清洗、索引构建。整套系统完全跑通后端加运维工作量在一到两周左右。依我的经验在这个最小方案的基础上按以下顺序迭代价值最高先搭评测集、再做混合检索、然后加重排序、最后才是换更大的嵌入模型或做成多级知识库。很多人一上来就追求复杂架构效果反而兜不住。我在实际项目里的最终配置是中文嵌入模型、混合检索、交叉编码器重排序、温度 0.2、Top 5 上下文。这套配置下测试集中的准确率从初版的约 82% 提升到了 93%无答案问题的拒答率从 30% 提高到 85%。对业务场景来说这个水平已经足够支撑上线。最后再分享一点个人体会RAG 的“知识库”才是这个系统真正的核心资产。模型、算法、框架都会随时间迭代但一份结构清晰、覆盖全面、持续更新的知识库会持续给系统提供稳定价值。我后期几乎所有精力都花在了知识库治理上——给文档分类、标注有效期、补充同义词、清洗过期内容。这些事看起来琐碎、不性感但对 RAG 系统整体体验的提升比任何花哨的模型调优都来得直接。