☰
从零搭建AI Agent:RAG知识获取管道实战全解析
2026/9/29 18:51:48 网站建设 项目流程

以我自己的实操经验,先给这个“走进 AI Agent”系列定个调:很多人学 Agent,一上来就冲规划、多智能体协作、工具调用这些花活,结果连最基础的知识获取都没打通,Agent 就是个只会聊天、一问正经事就瞎编的空壳。所以第四篇我专门写RAG,也就是检索增强生成,它是 Agent 连接外部知识的“取水管”,决定你的机器人到底是“有脑子的助手”还是“复读机”。

这个内容能解决什么问题?简单说,就是让大模型在回答时不再只靠训练时的那点记忆,而是能从你指定的文档、数据库、网页里实时把相关内容捞出来,再结合问题生成答案。适合谁看?准备从零搭 AI Agent 的开发者、在折腾本地知识库的工程师、以及想搞懂 RAG 原理、不想被各种概念忽悠的产品和技术同学。下面我把管道怎么设计、代码怎么写、坑怎么踩,一次说透。

1. 先把知识获取这件事掰开揉碎

1.1 Agent 为什么需要 RAG 这条管道

要理解 RAG,得先想清楚一个问题:大模型的知识是“死”的。训练完成那一刻,它的知识就冻结了。你问它今天天气,它不知道;你问它公司内部某个项目的上线日期,它不知道;你问它一个 2025 年才发布的研究成果,它大概率还是不知道,甚至开始一本正经地编。

Agent 和普通聊天机器人最大的区别在于“要干活”。干活就得依赖准确、及时、可追溯的信息。这时候我们有几个选择:让模型重新训练去更新知识?成本太高,不可能天天训;让模型上网搜?能拿到实时信息,但没有定向性和可靠性,搜出来一堆营销号垃圾也没辙。RAG 的思路更务实:把知识从模型里“搬出去”,放到一个可检索的外部存储里,模型在回答前先查资料,再把资料作为参考依据来生成。

我常给身边同事打一个比方:模型是学生,RAG 是开卷考试时的参考书。你不需要把整本书背下来,但知道去哪一页找答案,翻到之后照着答,还能在答案后面批注“见第几章第几节”。这不光是提高准确率,更是让 AI 的回答“有据可查”,这在企业落地场景里几乎是必须的。

1.2 从“聊天式 RAG”到“Agent 化检索”的转变

初学 RAG 时会看到一个经典流程:用户提问,系统去知识库检索,拼进 Prompt,模型生成答案。这个流程适合问答机器人,但放到 Agent 场景里是不够的。因为 Agent 有自主决策权,它可以自己决定“我现在需不需要查知识”“查完这个要不要再查那个”。

我把这两者的区别总结为“被动检索”和“主动检索”。普通 RAG 是“每个问题都检索一遍”,Agent 则可以根据任务拆解,在不同阶段触发不同的检索动作。比如说让 Agent 写一份产品竞品分析报告,它可能会先检索“我们产品的技术白皮书”,再检索“竞品公开资料”,两步检索可能要拼装成不同的上下文,甚至要判断某些资料是否可信、是否过时。这就是热词里常说的Agentic RAG。

后面我会详细展开,但你先记住一个核心认知:RAG 不是给 Agent 外挂的一个“搜索按钮”,它是 Agent 的长期记忆和工作台,检索的时机、粒度、策略,都应该由 Agent 的目标来驱动。知识获取管道,说白了就是让 Agent 知道“该去哪儿拿知识、拿到什么程度、怎么用知识”的完整链路。

2. 知识获取管道的整体设计与几个硬选择

2.1 索引、检索、生成,到底哪一段最影响效果

任何一套 RAG 系统,拆到底都是三个大件:

  • 索引构建:把文档切成小段、转成向量,存进向量数据库。
  • 检索:根据用户问题找出最相关的若干条片段。
  • 生成:把检索到的片段和问题一起交给大模型,产出最终回答。

三条链路各有各的坑,但以我实测经验,80% 的 RAG 效果问题都出在索引构建上。很多人拿到文档,随手一切就灌进向量库,后面检索出来的内容牛头不对马嘴,还怪模型不行。其实模型是无辜的,你喂给它的材料本身就没切好。

索引构建里最要命的决定是切分粒度。比如一份技术手册,按固定字符数切,可能把“函数定义”和“函数说明”切到两段里,检索时只召回后半段,模型根本不知道参数是什么意思。按语义段落去切,又可能切出几千字的超长片段,向量检索的关联度被稀释。我的建议是“默认走 Markdown 标题或段落结构切分,再结合业务的问答粒度微调,没有万能参数,必须试”。

向量化模型的选择同样关键。现在主流用 BGE、M3E、OpenAI embedding 这一类的模型,中英文混合场景需要特别关注模型对中文的语义覆盖度。有些英文模型转中文向量,近邻检索结果一看就是谐音梗聚会,完全没法用。这属于典型的基础设施选型失误,不是在调参能救回来的。

2.2 技术栈选型:LangChain、LlamaIndex 还是自己拼

确定完 RAG 的大方向,就得选实现框架。我见过不少团队,一上来就全盘抱 LangChain,理由是“生态全”,结果项目后期被框架的抽象层折腾得够呛。我的选型原则一向是“按需使用,不要为了框架而框架”。

  • 如果以 Python 为主、要快速验证 idea,LangChain 和 LlamaIndex 都可以,个人偏 LlamaIndex,它本身就以“文档索引”为核心,对 RAG 场景抽象得更好。
  • 如果团队是 Java 技术栈、要接 Spring Cloud 那套体系,Spring AI 的 RAG 支持已经可用,LangChain4j 也是主流方案,不要强行跨语言层。
  • 如果是大型企业要做统一知识服务,甚至可以考虑把 RAG 封装成独立服务,这就是热词里提到的“RAG as a service”,由平台团队统一管理文档接入、权限、索引策略,业务团队只管调用。

我自己的习惯是,核心链路可以手写。因为框架帮你省的是“胶水代码”的时间,但也框死了你的控制力。文档切分、检索逻辑、提示词组装这些核心动作,手写一遍能让你对每个环节发生什么了如指掌。实际落地时,可以先用框架做原型,跑通后再把慢的、不对劲的地方替换成自己的实现。

2.3 向量数据库和混合检索的取舍

向量数据库是 RAG 的存储底座。市面上可选的不少:Chroma、FAISS 适合本地轻量场景,Milvus、Qdrant、Weaviate 适合规模化和云原生场景。选型标准无非看三点:支持的数据量、检索性能、是否方便做过滤。

但这里有个误区,很多人以为 RAG 就是“向量检索”,其实关键词搜索的价值被严重低估了。例如检索一段包含型号“A1-200B”的技术参数,向量模型经常把 A1-200B 和 A1-200C 混在一起,关键词却能精准命中。所以成熟方案普遍走混合检索:向量检索负责捞语义相近内容,BM25 或全文检索负责捞字面精确匹配,再用 RRF(倒数排名融合)或重排序模型把两路结果合并排序。

我在一个智能客服项目里做过对比实验,单独用向量检索的命中率(hit rate)大概 68%,叠加关键词检索后能到 88%,再加重排能冲到 94%。这个过程很能说明问题:RAG 每一步微调,效果都是肉眼可见的。

3. 核心环节逐层拆解:从文档加载到上下文组装

3.1 文档加载和清洗:垃圾进垃圾出

RAG 的起点是喂文档。这一步看起来没有技术含量,却是最容易埋雷的环节。PDF 排版混乱、扫描件缺字、Word 里的文本框丢失、网页上的导航栏混入正文,这些都是常见坑。你需要根据公司实际文档形态,开发一套加载清洗流程,目标是“只把该留的正文留下来”。

我的经验里必须处理三类脏数据:页眉页脚和重复导航栏,它们是天然的噪声,会让切分后的每个片段都带着无关信息;乱码字符和特殊符号,会干扰向量化;表格。表格是 RAG 的老大难,直接把 Markdown 表格灌进模型,经常丢行错列,我建议对大表格做结构化提取,把每个表格转成自然语言描述再入库。

这一步做到位的判断标准是:你随手抽一个片段看,它是否单独拿出来就是一个有信息量的完整表达。如果片段读起来前言不搭后语,就别指望模型能从里面学到什么。

3.2 切分策略的实操要点

文档清洗完,就进入切分。切分时要考虑的不是“多少字一段”这个数字,而是“切出来的片段是否语义自洽”。实操中,我按优先级使用三种策略:

  • 结构切分:优先按标题层级、段落、列表项、表格边界切分,能保留章节上下文。
  • 滑动窗口切分:对结构不明的文本,设定块大小如 512 字、重叠 64 字,保证边界信息不那么突兀。
  • 父子切分:父块是整章或整节,子块是更小的内容单元;检索时命中小块,上下文却带上大块的内容。这种方式非常适合技术文档,因为一个概念往往要结合前后文才能解释清楚。

切分完毕,还需要做一轮元数据标记。比如这个片段来自哪个文档、哪个章节、什么时间、针对什么产品线。元数据在后续检索时会发挥大作用,尤其是做权限过滤或业务筛选时,没有它,你只能把所有文档混在一起检索。

3.3 向量化、存储和检索:参数和算法都别将就

向量化的目标是把文本变成一串浮点数,让语义相近的文本在向量空间里靠得近。Embedding 模型的选择,我建议直接在 MTEB 这类排行榜上筛选适合自己语言场景的模型,而不是道听途说。切分好的一批文档,先跑一个小的相似度抽查,人工看几组检索结果,比任何理论指标都直观。

存储方面,如果团队已经用了 ES,现在的 ES 也支持向量检索,算是兼顾关键词和向量的折中方案。如果从零搭建,Milvus 这种专用向量库能省去很多运维心力。

检索时,相似度算法通常用余弦相似度,但向量检索召回的结果默认只能看“距离”,并不能区分“绝对不相关但距离近”和“高度相关但距离稍远”的细微差别。所以新增一层重排是性价比极高的做法:召回 20 条,重排后只取前 5 条送给模型,效果往往比直接取前 5 条好一截。

我统计过一个病案知识库项目的检索实验结果,用 BGE-large 做 embeddings、设置 Recall 20 + Rerank 5,Top-5 命中率比直接取 Top-5 高 11 个百分点。这里多说一句,重排模型的推理成本比 embedding 高,但它是管道的最后一道闸门,这个开销花得值。

3.4 怎么把上下文组装进 Prompt,才不会让模型“飘”

检索做完,剩下的就是生成。可很多人偏偏在最后一步翻车。模板大概是“请基于以下资料回答,资料:...”。问题在于:上下文塞得太满,模型抓不住重点;塞得太杂,模型容易把不相关内容也编进答案;甚至你要问的问题和检索材料不匹配时,模型还理直气壮地硬答。

我现在的做法是尽量给模型制造“翻译”的语境:先让它把资料里与问题最相关的部分摘出来,再让它据此作答,并在 Prompt 里明确写上“如果资料里没有充分依据,请直接说不知道”。这样做的效果,比直接命令“你必须根据资料回答”好很多。本质上是把“从资料中找根据”这个隐性任务显式化,模型完成质量会更高。

另外,生成时不要把原始问题丢给模型就完事。很多场景需要先做一轮问题改写,把“它的故障率如何”改写成“产品型号 X 的年度故障率指标是多少”再进入检索,召回效果天差地别。这一步在 Agentic RAG 里往往是 Agent 自己完成的。

4. 实操:5 分钟从零跑通一条本地 RAG 管道

4.1 技术选型和准备

这里我演示一条适合本地起步的完整管道,技术栈选 Python + LlamaIndex + Chroma + BGE embedding。为什么这么选?LlamaIndex 对文档索引和检索的抽象做得顺手,Chroma 零配置跑本地,BGE 模型对中文友好、可以本地离线跑,不依赖外部服务。

先准备环境,Python 3.10 以上,安装依赖库:

pip install llama-index chromadb torch transformers sentence-transformers

如果你想把 embedding 换成国内模型,也可以直接加载 BGE 系列。这个环境在小内存机器上也能跑,就是切大文档时慢一点,不影响演示。

4.2 构建索引的核心代码

先加载文档,我建议直接让 LlamaIndex 用默认的加载器处理 txt 或 markdown:

from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, Settings from llama_index.embeddings.huggingface import HuggingFaceEmbedding from llama_index.vector_stores.chroma import ChromaVectorStore import chromadb # 设置本地 embedding 模型 Settings.embed_model = HuggingFaceEmbedding( model_name="BAAI/bge-small-zh-v1.5" ) # 读取文档目录 documents = SimpleDirectoryReader("docs/").load_data() # 初始化 Chroma 客户端 db = chromadb.PersistentClient(path="./chroma_db") chroma_collection = db.get_or_create_collection("my_knowledge") vector_store = ChromaVectorStore(chroma_collection=chroma_collection) # 生成索引 index = VectorStoreIndex.from_documents( documents, vector_store=vector_store, )

注意目录下不要混入临时文件和隐藏文件,否则加载器会全部吃进去,索引里出现一堆乱码。

4.3 检索和问答的代码实现

索引构建好后,检索问答就很简单了:

query_engine = index.as_query_engine(similarity_top_k=5) response = query_engine.query("BGE 模型支持的最大序列长度是多少?") print(response)

similarity_top_k=5表示从库里取最相关的 5 个片段。默认的 query engine 其实已经封装了检索、组装 Prompt、生成答案的全过程,适合快速验证。

但真实场景下我更喜欢把它拆开操作,便于定位问题:

retriever = index.as_retriever(similarity_top_k=10) nodes = retriever.retrieve("BGE 模型支持的最大序列长度是多少?") for node in nodes: print(node.node.get_text()[:200]) print("score:", node.score)

先打印检索返回的片段,确认材料对不对,再决定要不要把全部片段直接送给模型。很多诡异问题看一眼原始检索结果就明白了。

4.4 本地知识库管道优化的几个直接做法

基础管道跑通之后,可以从三个方向快速提效果:

  • 把切分调成“按段落切”而不是“按固定字数切”,尤其是 Markdown 文档,LlamaIndex 支持 MarkdownNodeParser,可以用它替代默认切分。
  • 检索前加一个问题改写,比如把口语化问题补全成技术文档的检索用语。
  • 给索引加元数据过滤器,比如只检索特定目录或特定标签的文档。

这些都是低成本高回报的改动。但我要提醒你,不要一上来就追求 GraphRAG、知识图谱这种高阶玩法。先把这个线性管道做到极致,再看需求决定要不要引入更复杂的结构。

5. 常见问题、排查思路与调优实录

5.1 检索效果差,第一步不是调模型而是看切分

我在一个合同审查 Agent 项目里遇到过典型问题:用户问“违约金比例”,检索回来的片段全是“合同双方约定违约金比例不超过 30%”,但合同里的具体条款是被拆开的,模型拼不回去,答非所问。

排查过程很简单,直接把检索结果打印出来,发现命中片段里缺失了上下文部分。这让我把切分策略换成父子切分,让检索时带上父块信息。效果立竿见影。所以排查 RAG 问题时,永远先去“看检索中间结果”,而不是直接怪生成模型。这一步能省你一半的调参时间。

5.2 hit rate 低、召回率差的常用解法

“hit rate”就是命中率,指问题相关文档片段被检索出来的比例。平时我们总说“检索不准”,其实就是 hits 不够。解法优先级我排一下:

  • 切分和 embedding 不匹配,先换 embedding 模型;
  • 单路向量检索不够,加关键词检索;
  • 召回数量太少,从 5 调到 20,再用重排模型把前 3 条选出来;
  • 相关性判断太粗,改为给每个片段加业务权重,例如产品手册比新闻稿优先级高。

这些动作按顺序逐个试,每次只改一个变量,保留测试集,记录变化。RAG 优化最怕“一次改三样”,出了问题你根本不知道是哪一步的功劳。

5.3 模型仍然幻觉和胡说,该怎么堵住

RAG 已经给了知识,模型却还是编,多半是上下文和指令的问题。我有个土办法:在 Prompt 里加一句“如果资料中没有描述该内容,直接回复‘知识库中没有相关信息’,不要推测”,它确实能硬性压住一部分幻觉。

另外,一定要观察模型实际看到了什么。有些框架会把“检索到的内容”和“历史对话”一股脑塞进去,上下文里混着用户早期说的错误信息,模型就被带偏了。解决办法是限制上下文只保留与当前问题最相关的内容,减少干扰。

如果模型反复从资料里抽取数字却算错账,就别让它直接算,改为先抽取关键参数,再用代码计算。这一步已经是把一个单纯 RAG 升级成拥有工具调用能力的 Agent 了,也是绕过模型弱点的经典策略。

5.4 常见问题速查表

现象可能原因首选排查动作
检索结果不相关embedding 模型不适合领域人工查看 Top-10 相似片段
答案合并多段信息时出错切分粒度太碎,上下文丢失切分策略改父子切分
专业术语检索不到向量模型对术语不敏感叠加 BM25 关键词检索
模型回答和资料不一致Prompt 约束不足显式要求“资料无依据就直说”
同义改写后检索变差问题改写丢失关键实体检索前做实体/关键词保留
多个文档主题混杂缺少元数据过滤按文档类型/部门加过滤条件

这张表基本覆盖了从入门到进阶的第一批坑。遇到问题先对着表定位,别一上来就重新训练模型。

6. 从基础 RAG 走向 Agentic RAG:检索成为能力而不是流程

6.1 把检索封装成 Agent 可以调用的工具

如果你按前面的内容搭好了基础 RAG,下一步不是去做知识图谱,而是先让 RAG 变成 Agent 的一个“工具”。在 Agent 框架里,一个工具是有名字、有描述、有入参出参的函数。比如定义一个名为“knowledge_search”的工具,描述为“用于检索内部技术文档和产品手册”,参数是查询字符串。

为什么要这么做?因为基础 RAG 是“每问必检”,而 Agent 能自己判断“这个问题需不需要查知识”。有些简单事实性问题,模型直接答更快;有些需要最新数据的问题,Agent 就会主动调用检索工具。这样既省成本,又避免无关检索干扰生成。

我在一个企业内部问答 Agent 里,把文档检索做成工具后,Agent 还可以先检索“是否有相关规范”,再检索“该规范对应的模板”,两个检索之间夹杂其他操作,这是普通 RAG 流程根本做不到的。

6.2 自我反思、问题改写和多轮检索的落地套路

Agentic RAG 的进阶玩法是让 Agent 参与检索质量的闭环。典型的流程是:

  • Agent 拿到用户问题,先做意图分析,决定用哪个检索策略;
  • 把原始问题改写成适合搜索的查询,这步可以交给大模型自己完成;
  • 检索后,Agent 自评“这些资料足够回答问题吗”,不够就换一个角度再检索;
  • 最后汇总多次检索结果,组织答案。

这就是热词里常说的自我反思和多轮检索,也是 GraphRAG、Ontology RAG 这些概念兴起的原因。结构化知识确实能提升复杂问题的回答能力,但初学阶段不建议碰,连线性管道都没调好就上知识图谱,只会多出一堆调度和维护成本。

6.3 与 Skill 机制结合:让知识获取带业务逻辑

现在 Agent 框架里流行 Skill 机制,也就是把某个业务能力做成一段可复用的带 Prompt 和工具定义的“技能包”,RAG 完全可以作为一个 Skill 嵌入进更大的 Agent。比如我有客户在 ERP 系统里做产品检索,就是把“产品参数检索”和“库存状态查询”封装成两个 Skill,一个做 RAG 检索,一个去查数据库,Agent 通过决策把它们拼成完整回答。

这里的关键点是,RAG 不应该是一个孤立的 service,而是知识管道里的一个环节,它的上层有业务规则,下层有数据治理。只有当 RAG 和 Agent 的其他工具协同起来,知识获取才真正“管道化”。

一些个人体会

我从做第一个 RAG demo 到现在,最大的感触是:RAG 的资料和风口远没有 T恤上印的那么光鲜,真正决定落地效果的是数据库整理、切分调优、检索评估这些脏活累活。很多人问我要“最好用的 RAG 框架”,我通常回一句:框架只是帮你省掉从 0 到 1 的时间,从 1 到 100 全靠你对文档、对业务的理解。

如果你现在正准备从零搭建 Agent,我的建议很直接:先用五页以内的文档跑通管道,再逐步加文档类型、加元数据规则、加 Agent 决策。每一个环节都打印中间结果给自己看,肉眼确认过的东西才可信。RAG 这条管道没有放之四海而皆准的参数,但它有一条放之四海而皆准的原则——检索只是手段,知识真正被用上,才算数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询