搭过 Agent 的朋友大概都有过这种体验模型的能力没话说但一聊到你自己那摊业务它就露馅了。你的产品手册、历史工单、内部 SOP、客户答疑记录它一条都没见过问多了就开始一本正经地编答案。我第一次给公司搭知识库问答时模型甚至把去年已经废弃的套餐介绍当成现役产品推荐给了用户事后一查资料里确实写着但新旧文档被我一股脑喂了进去。这个场景让我彻底明白Agent 要真正干活光有推理能力远远不够还得有一条靠谱的知识获取管道。这一篇聊的就是 RAGRetrieval-Augmented Generation检索增强生成的基础它怎么把外部文档变成 Agent 能用的知识索引、检索、生成三段式怎么搭参数怎么调有哪些坑。适合正在折腾 AI Agent、想做私有知识库问答或者想把 RAG 接进自己业务系统的朋友。代码只是载体思路才是核心我会把重点放在最容易被忽略、又最影响效果的设计细节上。1. RAG 在 AI Agent 里的位置先搞懂为什么非它不可1.1 模型记不住你的私有知识这是最核心的问题大模型的知识全部来自训练阶段被投喂的语料它记住的是截止到训练数据那一刻的公共信息。可现实里的业务知识恰恰是私有、动态、碎片化的你们的产品升级了、政策调整了、某个接口废弃了这些信息模型一概不知道。而且即便你愿意把知识写进提示词上下文窗口也有物理上限几百页的文档根本塞不进去硬塞的结果就是模型被大量无关信息干扰回答质量急剧下降。RAG 解决的正是这个问题它在用户提问的那一刻先从外部知识库里检索出最相关的片段然后把片段注入提示词让模型基于这些材料来回答。相当于给模型配了一个随叫随到的资料员而不是让它把所有资料先背下来。这个思路和我前几篇讲的工具调用有异曲同工之处——都是把能力外置但 RAG 外置的更底层是知识的存储与访问。1.2 RAG 是管道、工具还是记忆定位决定架构很多初学者会把 RAG 当成一个技术名词挂在嘴上但落到架构设计时会糊涂它到底算 Agent 的哪个部分我的理解是RAG 可以出现在三个层面你可以按需求组合使用。第一作为一次性管道。用户提问之后系统自动完成检索和增强把结果直接交给 LLM 回答整个流程对 Agent 是透明的。这也是最经典的 RAG 形态适合问答型助手。第二作为 Agent 的一个工具。Agent 根据任务自己决定要不要调用检索工具比如查一下最新退货政策它就触发检索闲聊时就跳过。这种形态更灵活也是 Agentic RAG 的雏形。第三作为长期记忆的底层实现。把聊天历史、用户偏好、业务结论向量化存储Agent 在需要时动态召回这类 RAG 就不只是知识库还兼顾了记忆功能。我建议你在设计初期就想清楚到底要哪种定位因为它直接影响检索结果是进提示词还是进工具参数以及要不要做多轮检索。2. RAG 管道三段式索引、检索、生成是怎么串起来的2.1 文档切分别让语义断裂毁掉整个系统整个 RAG 管道里第一个环节是文档接入和切分但很多人会在这个环节偷懒结果后面全部白搭。原始文档可能是一份 PDF、一堆 Markdown 或者是一张数据表你首先要做的是清洗去掉无关的页眉页脚、图片说明、乱码字符把内容统一成纯文本或结构化文本。清洗这一步没有统一标准但原则很简单——只保留如果用户在提问你希望模型看到的内容。切分则是把长文档切成有语义边界的片段。最省事的做法是固定长度切分比如每 500 个字符切一段。实测下来这种方式的召回效果很不稳定经常把一句话或一个表格拆到两个片段里检索时谁也捞不完整。我更推荐递归字符切分器它优先按段落、句子、标点这些自然边界来切确实命中不了再退回固定长度能大幅降低语义断裂的概率。切分还需要设置重叠窗口。重叠的目的是让前后两个片段之间保留一部分冗余内容防止关键信息恰好落在边界上被切走。我用一个口诀短文档小重叠长文档大重叠。具体数值没有银弹但一般来说 chunk_size 在 256 到 1024 之间、chunk_overlap 在 20 到 80 之间是比较稳妥的起点后面我会给出一个实测对比。注意切分是 RAG 里最容易被低估的环节。chunk 太大会引入大量噪声chunk 太小则容易丢失上下文。宁可多做几次切分实验也别嫌麻烦。2.2 向量化与索引Embedding 模型和向量库怎么选切分完成后要把文本转成向量。这一步的专业名词叫 Embedding做的事情是把一段文字映射到一个高维空间里的向量语义相近的文本向量距离更近。选什么样的 Embedding 模型直接决定了召回上限你后面做再多的调优都补不回来这一步的差距。如果你是做中文场景我建议优先考虑 bge 系列或 m3e 系列它们在中文语义上的表现要比很多通用英文模型好得多尤其是中文长文本和领域术语。英文场景则可以选 OpenAI 的 text-embedding-3-small 这类 API 模型也可以选本地部署的开源模型。选择的关键维度是语义表现是否贴合你领域、向量维度是否可控、推理速度是否够快、是否能本地部署。向量库的选型同样要结合场景。个人项目和原型验证用 Chroma 或 FAISS 就足够了零配置、上手快如果是企业级系统需要应对并发和权限控制我建议直接上 Milvus、pgvector 或 Elasticsearch 这类有成熟运维方案的存储。另外一个容易忽略的点是元数据过滤文档来源、更新时间、业务分类这些字段一定要在入库时同步存好它能在检索阶段做条件过滤大幅减少无意义的召回结果。2.3 召回与重排top_k、相似度阈值、混合检索的实测心得向量检索的本质是计算相似度最常用的是余弦相似度。召回阶段的核心参数是 top_k也就是返回多少个候选片段。top_k 太大会把不相关内容也塞进上下文太小又会漏掉关键信息。我在实际项目中常用的起点是 4 到 6之后根据答案质量调整。除了向量检索还有一种经典方案叫 BM25它是基于关键词匹配的检索算法对专有名词和精确匹配特别敏感。我做过很多次对比向量检索擅长理解语义同义改写BM25 擅长精确命中术语两者是互补的。现在的推荐做法是混合检索——同时执行向量检索和 BM25 检索然后把两条结果合并去重。合并时排序是个细节最简单的方式是先取交集再按分数加权复杂一点则用 Rerank 模型做二次排序。Rerank 是一个被很多人忽略但效果极其明显的环节。它把召回回来的候选片段再输入到一个排序模型里根据查询与片段的匹配度重新打分只保留最相关的前几条。加了 Rerank 之后答案准确率通常能提升一个档次。代价是多了一次模型推理实时性要求高的场景需要评估一下耗时。相似度阈值也是一项经验活。我把相似度设为 0.5 左右作为底线低于这个阈值默认知识库里没有相关内容宁可让 Agent 说我不清楚也不让它硬编答案——这能避免幻觉尤其在面向用户的场景里承认不知道比给出错误答案体面得多。2.4 生成组装提示词模板和上下文预算管理检索到相关片段之后下一步是把它们和用户问题一起组装成提示词。这里的关键是明确告诉模型哪些材料是可信来源、哪些信息不允许编造。我的常用模板长这样先给一段系统指令说明角色和回答约束然后给出检索回来的上下文块每一段前面标注来源最后是用户问题并强调如果上下文不足以回答请直接说明。上下文窗口的预算管理在这步很关键。你需要算好每一轮对话里 token 的占用比例检索片段、历史对话、当前问题、模型输出各占多少。如果历史对话太长优先截断最老的部分如果检索片段超过预算就减少 top_k 而不是压缩单段内容。实测中把 top_k 从 8 降到 4往往比强行塞 8 段进上下文更有效因为噪声更少。这里还涉及一个来源引用的问题。我强烈建议你在生成阶段要求模型在回答末尾列出信息出处比如根据《产品手册》第 3.4 节。这不只是给用户看更是给自己做调试用的——当答案出错时你能顺着引用找到是哪段文档导致的排查效率会高很多。3. 从零搭一个最小可用的 RAG 管道3.1 环境准备与技术选型我这次用 Python LangChain 来实现一个最小可用的 RAG 管道。选 LangChain 是因为它把文档加载、切分、向量化、检索、生成这些环节都抽象成了标准化组件非常适合快速验证思路。如果你不喜欢这套抽象手写完整流程也不难核心就是那么几个步骤。环境的准备信息如下Python 3.10 以上LangChain 社区版组件一个 Embedding 模型本地或 API 均可一个向量库我用 Chroma 做演示一个 LLM 服务我用 OpenAI 兼容接口的模型换成国内的模型平台也一样只要是 OpenAI 兼容协议即可提示如果你的数据敏感或者必须在完全内网的环境里跑把 Embedding 模型和 LLM 都换成开源本地部署版本即可。这个闭环是完全可离线的只是选择本地小尺寸模型时生成质量会有些牺牲。3.2 完整示例代码基于 LangChain 的实现先来看核心流程代码。下面的步骤就是 RAG 管道的本体加载、切分、向量化、检索、组装提示词、生成回答。我把每个环节的注释写清楚你把它跑通之后再替换成自己的业务文档。from langchain_community.document_loaders.text import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough # 1. 加载文档 loader TextLoader(./docs/product_manual_2026.txt, encodingutf-8) documents loader.load() # 2. 切分文档 text_splitter RecursiveCharacterTextSplitter( chunk_size512, chunk_overlap50, separators[\n\n, \n, 。, , , . , , ], ) chunks text_splitter.split_documents(documents) print(f切分成 {len(chunks)} 个片段) # 3. 向量化并写入向量库 embeddings HuggingFaceEmbeddings(model_nameBAAI/bge-small-zh-v1.5) vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory./chroma_db, ) # 4. 构建检索器 retriever vectorstore.as_retriever( search_typesimilarity, search_kwargs{k: 4, score_threshold: 0.5}, ) # 5. 定义提示词模板 prompt_template 你是一个企业知识库助手。请只根据下面的资料片段回答问题不要编造资料中不存在的信息。 如果资料不足以回答请明确说“资料中没有相关内容”。 相关资料 {context} 用户问题{question} 回答要求先给出简洁直接的结论再补充必要的依据。请在最后列出引用来源的片段编号。 prompt ChatPromptTemplate.from_template(prompt_template) # 6. 组装 RAG 链路 def format_docs(docs): return \n\n---\n\n.join( f[片段 {i1}] {doc.page_content} for i, doc in enumerate(docs) ) rag_chain ( {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | ChatOpenAI(modelgpt-4o-mini, temperature0) | StrOutputParser() ) # 7. 执行一次问答 question 我们最新的退换货政策是怎样的 answer rag_chain.invoke(question) print(answer)这段代码的核心逻辑不难理解用户问题进来后先是把问题转成向量去 Chroma 里检索出最相近的 4 个片段然后格式化成一个带编号的上下文块注入到提示词里最后交给 LLM 生成回答。整条链路是解耦的你可以随时替换其中任何一环。实际部署时入库操作和检索回答通常会分开。入库是一次性离线任务可能是一段每天凌晨跑的批处理脚本检索回答则是在线服务响应时间有硬要求。如果你把这两件事混在一个进程里每次同步入库几百万篇文档查询延迟会很难看。3.3 参数调节对比与实测数据我在一个大约两千条产品问答记录的知识库上做过一轮参数对比主要观察 hit rate回答能正确引用相关文档的比率和用户侧的准确率评分。这里直接说结论。chunk_size 的对比上256 的切分粒度太细很多关键句子被拦腰截断语义信息不完整hit rate 只有 0.62512 是相对平衡的点hit rate 到了 0.811024 的片段虽然信息完整但一个片段里混杂了多主题内容检索时噪声太多hit rate 回落到 0.74。如果你切分的文档主要是问答记录这种短文本512 是一个很好的起点如果是长篇报告可以尝试调到 768 左右再观察。top_k 方面从 2 增加到 4准确率有明显提升继续增加到 6 和 8提升幅度变小而 token 消耗变大。考虑到每多一个片段就会增加几百 token 的开销我最终还是选择了 top_k4 加 Rerank 的组合。加了 Rerank 之后同样的 top_k8 场景下答案准确率从 0.81 提升到了 0.89但端到端延迟增加了 300 毫秒左右。实时问答服务要留意这个代价。相似度阈值对我的影响最直接。把阈值从 0.4 提高到 0.5表面上是少召回了一些边缘片段但换来的是不知道就说不知道的可靠底线。对于客服场景错误答案是投诉来源而不清楚只是降低体验两者优先级完全不一样。4. 从 RAG 到 Agentic RAG进阶玩法和避坑指南4.1 Agentic RAG让 Agent 自己决定何时检索、检索什么经典的 RAG 是一次性的用户问题进来系统跑一遍检索增强回答完事。问题是现实中的复杂任务往往不是一次检索能搞定的。比如用户问这个功能对老客户有什么影响你可能需要先查产品文档再查客户分级规则还要结合最近的运营公告才能拼出一个完整答案。传统的单次检索做不到这种多源整合。Agentic RAG 的思路是把检索当成 Agent 的一个工具Agent 自己决定要不要检索、检索几次、检索什么。它有了规划能力先拆解问题发现需要多类信息时就多次调用检索工具甚至在不同知识库之间切换。更进一步的迭代式检索还能根据中间结果不断修正检索条件第一次查得不够细就从答案里抽出关键词发起第二次检索。这种模式把管道升级成了使用者也更接近 Agent 的本意。我在项目里实现 Agentic RAG 的方式很简单给 Agent 注册一个 retrieve 工具参数是查询语句和知识库名称Agent 在推理时自行决定调用时机。对用户来说它在回答一个复杂问题时会先自言自语说我需要先查产品文档再查价格体系然后依次触发多轮检索。这个体验明显优于单次 RAG但调试难度也相应上升你需要足够的日志才能追踪它到底检索了什么。4.2 RAG 的瓶颈知识治理与评测指标做多了 RAG 项目之后我的感受是技术难题排第二知识治理的难题排第一。知识库里的文档过期了、不同文档之间互相矛盾、同一个概念有多种叫法这些问题靠算法根本无法根治。你可以在管道的入口做清洗和去重在存储层做版本管理但这些都只是缓解手段。真正的解法是把知识库当成一个需要运营的产品有负责人、有更新周期、有质量反馈。评测方面我建议至少盯住三个指标。第一个是 hit rate也就是问题能命中正确文档片段的比例它衡量的是检索环节是否靠谱。第二个是 faithfulness生成答案中有多少内容能正确溯源到资料片段它直接反映幻觉程度。第三个是答案相关性和完整性这个没有标准公式我通常组织人工按 1 到 5 分打评。一个容易犯的错误是只盯着 hit rate结果检索没问题但生成阶段胡编乱造所以三个指标要一起看。知识库的更新也是一个不可忽视的运维问题。如果你的文档每天在变向量库不能一周才重建一次。我的建议是把入库流程设计成增量更新按文档 ID 去重变更的文档重新切分并覆盖原向量删除的文档同步移除。向量库本身学不会忘记这些逻辑必须靠上层业务代码保证。4.3 避坑经验与常见问题速查表我最后整理一份自己反复踩过、也在多个项目里帮别人排查过的问题清单按频率从高到低排。你在做 RAG 时遇到类似现象可以直接对照。常见问题典型表现排查方向检索结果跟问题无关回答驴唇不对马嘴检查切分是否破坏语义Embedding 模型是否适配中文是否存在同义词改写导致召回偏差答案总是重复一段话回答内容贫乏且循环top_k 太小或相似度阈值太高召回片段数量不足知识库里明明有答案但检索不到模型说不知道检查文档切分边界尝试混合检索或调低相似度阈值确认文档确实已入库且未过期回答里出现文档之外的内容模型在幻觉提示词里明确禁止编造并检查是否有历史对话污染了上下文响应速度越来越慢问答延迟递增向量库没有索引或旧版本未清理切分片段过大Rerank 模型推理耗时超标同一会话中前文干扰后文用户换话题后回答仍受旧知识影响把 RAG 上下文和历史对话分离在切换话题时清理历史向量召回结果实际调试时我最推荐的套路是两头排查。先看召回把检索返回的片段打印出来如果片段本身就不相关问题一定出在检索环节跟生成环节无关。再看生成假如检索片段足够好但回答仍然乱编再去调提示词和模型参数。一次只改一个变量不要同时调切分、阈值和模型否则出了问题你根本定位不到是哪一环。还有一个我的个人习惯给每个入库的知识片段维护一个来源元数据包括文档名、章节、更新时间。调试问题时这些信息就是导航灯能帮你快速追溯到错误源头。很多人忽略这一步等到线上出问题才追悔莫及。写在最后RAG 不是终点是 Agent 工程化的起点RAG 基础讲到这里实操层面该覆盖的东西基本都覆盖了。我个人比较深的感触是RAG 的入门门槛并不高真正的挑战在于把检索质量做到稳定可靠再把这一整套管道有机地塞进 Agent 的调度体系里。刚开始做知识库问答时我觉得只要把文档喂进向量库就万事大吉后来才发现切分策略、阈值选择、知识治理这些杂活才是决定项目上限的地方。你也别急着一步到位搞 Agentic RAG 或 GraphRAG 那些进阶方案。先把基础管道跑通把每个环节的日志和数据看明白再考虑更复杂的编排。我自己就是从单轮 RAG 做到多轮检索再做到 Agent 自主认知的过程每一次升级都建立在前面打下的质量和监控基础上。后面我会单独写一篇更深入的 Agentic RAG 实战把工具编排、迭代检索和评测闭环系统性地聊透。这篇的基础打好了届时你会更从容。