ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI Agent必备:RAG知识获取管道从原理到代码实践

AI Agent必备:RAG知识获取管道从原理到代码实践 聊到AI Agent绕不开的一个问题就是模型肚子里那点知识不够用怎么办。大模型再能打它的知识截止到训练那天而且没有你公司内部的文档、你手头的项目资料、你积累的经验笔记。这时候就需要RAGRetrieval-Augmented Generation检索增强生成上场它是Agent的知识获取管道。这篇文章是“走进AI Agent”系列的第四篇专门聊聊RAG的基础。适合所有正在搭Agent、或者想搞清楚“模型怎么学会他不知道的东西”的开发者。我会从底层原理讲到实际代码再聊聊我在真实项目里踩过的坑争取一篇讲透。1. 先搞清楚RAG在Agent里的位置1.1 Agent、LLM和RAG到底什么关系网上一堆人在问“Agent和LLM/AI模型有什么区别”其实没那么玄乎。LLM是大脑它负责理解语言、生成文本、做推理Agent是“大脑手脚”它不光能思考还能调用工具、执行动作、观察结果、迭代决策。而RAG是Agent的一根重要血管——专门给大脑输送外部知识的管道。我见过不少人以为RAG就是把文档丢给模型让它“记住”这是很典型的误区。你要真把一个几十万字的文档直接塞进上下文先不说能不能塞得下就算塞下了模型也会被海量信息干扰回答出来的东西大概率是“在文档里但找不到找到了但拼错”的缝合怪。RAG的思路完全反过来模型不需要记住全部内容它只需要在回答问题的时候从你的知识库里把最相关的那几段捞出来临时“翻书”看。DeepSeek这类模型属于LLM。有人问“DeepSeek是RAG还是Agent”答案是它本身都不是。DeepSeek是基座模型你可以拿它作为RAG的生成引擎也可以拿它做Agent的推理核心。RAG和Agent是模型之上的架构设计和应用模式模型只是里面被调用的一个组件。1.2 为什么“知识获取”是Agent的核心能力短板现在的Agent框架越来越成熟工具调用、任务规划、多轮对话这些能力已经做得相当顺手了。但这些能力都建立在“模型知道该怎么做”的基础上——而现实世界的业务场景里Agent要处理的恰恰是模型不知道的内容企业内部知识库、产品手册、售后工单、法律法规、行业标准。没有RAG的Agent就像一个空有高学历但没有任何工作资料的新人。你说得头头是道但一碰具体业务就露馅。这是任何微调方案都解决不了的问题。微调是让模型“成为某个领域的专家”它的成本高、周期长、而且知识一更新就要重新训练RAG是让模型“在需要的时候查某本书”它的成本低、见效快、知识随时更新今天改了文档明天就能生效。我见过一些团队试图用微调来解决知识获取问题结果几千条数据训完模型还是会在具体业务参数上出错而且训完一次就再也不敢动数据了。用RAG就灵活多了你的知识库只是外部存储换一批文档、增删几个条目完全不碰模型本身。1.3 RAG到底解决哪些问题不解决哪些问题RAG擅长解决的是事实型问答和知识密集型任务。比如“我们公司的年假制度是什么”“这个接口的鉴权流程是几步”“去年的订单处理量是多少”。这些问题的答案明确存在于文档里RAG能精准捞出来给模型当参考资料模型就能给出一句带出处的、可信的回答。但RAG不解决推理和创造问题。你让RAG帮你做战略规划它捞出来的资料只能提供素材背景真正的分析、权衡、决策还是靠模型本身的推理能力。另外RAG也不解决模型完全没有逻辑能力的问题。如果基座模型本身智商不够你给它喂再多资料它也可能只会摘抄原文不会归纳总结。一句话记住三者的分工LLM负责想Agent负责做RAG负责查。三者配合Agent才真正具备处理真实业务的完整能力。2. RAG管道核心环节拆解从文档到答案的四段旅程2.1 索引阶段先把文档变成模型能检索的形态RAG的第一阶段是索引Indexing这个阶段的工作在用户提问之前就已经完成了。为了让检索系统能够快速、准确地找到所需内容原始文档需要经过加载、切块、向量化、存储四道工序。每一道工序都会直接影响最终检索结果的质量。首先是文档加载Loading。现实世界中的文档格式极其混乱PDF、Word、Markdown、HTML、扫描件、PPT每种格式都有不同的解析难点。PDF尤其麻烦有的是文字版可以直接提取有的是扫描版需要OCR有的排版复杂会导致文字提取顺序错乱。我处理过一份技术手册的PDF标题和正文在视觉上排得清清楚楚但提取出来之后散落成碎片直接切块检索的效果惨不忍睹。后来我改用基于版面分析的工具先把页面结构识别出来再按逻辑顺序重组文字检索质量才上去。接着是切块Splitting这是整个RAG中最容易被低估的环节。切块决定了你的知识库会被切成多大粒度的小段而这个小段会成为检索的最小单位。切的太小语义信息不完整每个片段都孤零零的检索时找不到完整答案切的太大检索出来的片段虽然完整但混入大量无关信息模型反而被噪音干扰。我用的切块策略并不是一刀切的固定字数而是按文档结构做层级拆分章节标题、段落结束、语义转折都作为切分边界。关于切块的具体参数和策略后面单独展开说。然后是向量化Embedding。这一步需要把文本转换成计算机能计算相似度的数字向量。选择的Embedding模型会直接影响文本语义的捕捉能力。市面上可用的模型很多从OpenAI的text-embedding-3系列到开源的BGE系列、M3E系列各自的中文表现差异很大。选型的时候最好用你自己领域的真实问题做评测不要把公开榜单的数字直接当真。最后是存储Storing。向量数据要落到专门的向量数据库里比如FAISS、Milvus、Qdrant、pgvector。除了向量本身还要把原始文本、文档元数据比如来源、日期、作者一起存上方便检索之后溯源。元数据的作用不只是给人看的它还能用于检索时的过滤条件——比如限定某个产品线的文档、排除过期的政策条款。2.2 检索阶段召回策略决定答案的上限RAG的第二阶段是检索Retrieval。用户提问来了系统先把问题向量化然后到向量数据库里做相似度搜索找出与问题最相关的Top-K个文本片段。这个阶段的核心是“怎么定义相关”。最简单的做法是向量相似度检索。把用户的问题变成向量后在向量空间里找距离最近的片段。这种方式对同义改写、语义模糊的提问表现不错但对关键词精确匹配不敏感。比如用户问“工伤认定需要哪些材料”如果你的知识库里原文写的是“申请工伤认定时应当提交的证明材料”向量检索依然能找到因为它们的语义是接近的。但如果用户用了一个知识库里从没出现过的表述方式向量检索就可能会漏掉真正相关的那个片段。更稳的是混合检索Hybrid Search把向量检索和关键词检索结合起来。关键词检索比如BM25能保证精确匹配不被遗漏向量检索能捕获语义相关但表述不同的内容两者取个交集并集按权重融合效果比单用任何一种都好。我在生产环境里做过对比混合检索的命中率比纯向量检索普遍高5-10个百分点特别是处理产品型号、专有名词这种东西的时候差距更明显。检索出来之后还有个**重排序Reranking**的环节。向量检索的Top-K里面经常混杂着“语义接近但并非真正答案”的片段。重排序模型会把检索出来的候选片段和问题一起做深度交互计算输出更准确的关联度分数把最靠谱的排在最前面。这等于在粗糙初选之后再搞一轮精筛对最终生成质量的影响非常显著。检索质量这里面有个很实在的判断标准看召回结果表。如果你的RAG搭完发现效果不好先别急着调Prompt把检索结果打出来看看前五条里面是不是真的有一条是“看起来就是标准答案”的。如果不是问题出在检索不是生成。2.3 生成阶段给模型递上参考资料而不是原文照抄RAG的最后一个阶段是生成Generation。系统把检索到的文本片段、原始用户问题拼装进Prompt让模型基于这些资料生成回答。这里有个关键点Prompt的设计直接决定模型会怎么使用检索到的资料。我在初学RAG时常犯的一个错误是把检索到的文本全部塞进Prompt然后就不管了。结果模型要么把资料原文大段Copy出来要么被不相关的片段带着跑偏。后来的做法是在Prompt里明确告诉模型怎么做。很多RAG系统会在Prompt里加上这些约束“你是一个基于知识库回答问题的助手”“请严格基于提供的资料回答”“如果资料中没有相关信息请明确告知”。这些文字看着简单但对输出质量的控制非常有效。还有一个容易被忽略的问题检索到的片段越长模型的忠实度绑架越严重。当相关资料达到一定长度时模型更倾向于摘抄或者亦可称为“局部复述”而不是理解后用自己的话表达。这会导致回答看起来像“粘贴拼接”而不是“融合回答”。处理方式是在Prompt里要求模型用自己的话重新组织语言并且只输出最终答案不要附带“根据资料”之类的话。整个RAG管道就是这样一个四段旅程文档进来切块向量化存储问题进来检索召回重排最后把资料交给模型生成一个有依据、有来源、可信赖的回答。3. 实操落地用LangChain搭一个最小可用的RAG管道3.1 环境准备和框架选型关于RAG框架这里多说一句。现在市面上的RAG框架五花八门有LangChain、LlamaIndex、Haystack还有各种“全家桶式”的企业级平台。我的建议是学习阶段从LangChain入手生产阶段尽量别过度依赖框架。LangChain的表达很清晰它把RAG流程抽象成Document Loader、Splitter、Embedding、VectorStore、Retriever、Prompt、OutputParser这几个组件学一遍LangChain基本就能把RAG的骨架摸透。但它的问题也在这它太爱“封装”了很多细节被藏起来出了问题不好排查。我见过一个项目LangChain升级一个小版本之后Embedding模型的参数格式变了整个检索结果全部跑偏排查了整整一天。为了让你透彻理解RAG内部逻辑我下面刻意不使用LangChain直接用原生代码把流程串起来。这样写的代码虽然多一点但每个环节做到什么、数据变成什么样子都是一眼能看明白的。你理解了原理之后再回到LangChain或者自研框架都会轻松很多。环境准备其实很简单用Python 3.9以上的版本安装以下依赖即可pip install openai numpy pypdf jieba fastapi uvicorn这里说明一下为什么用这些包。openai用于调用Embedding模型和Chat模型如果你用的是兼容OpenAI协议的本地模型这个包同样适用numpy用来做向量相似度计算最基础的向量数据库本质就是“一个数组暴力搜索”pypdf用来解析PDF文档这是最常见的知识库格式jieba是中文分词库做关键词搜索的时候用得上。fastapi和uvicorn是最后搭建API服务用的。3.2 第一步文档加载与切块我们假设场景是给Agent接入一份《员工手册》我们用它来回答员工关于请假、报销、福利相关的问题。from pypdf import PdfReader # 加载PDF文档 def load_pdf(file_path): reader PdfReader(file_path) full_text [] for page in reader.pages: text page.extract_text() if text and text.strip(): full_text.append(text) return \n.join(full_text) manual_text load_pdf(员工手册.pdf) print(f文档总字数: {len(manual_text)})这里要提醒一点pypdf的extract_text()对排版简单的PDF表现尚可但遇到多栏排版、复杂表格、带图片的文档就会乱掉。如果遇到这种情况建议换成专门的版面解析工具比如MinerU或PyMuPDF的版面识别模式。至于具体的PDF库怎么选后面章节会专门说明。然后是切块。我参考了一个长期验证过的策略按段落语义切分每段控制在300-500个中文字符之间并在保留上下文完整性的前提下控制重叠区。import re def smart_split(text, chunk_size400, overlap_size80): # 先按段落切分保留标题和段落结构 paragraphs re.split(r\n\s*\n, text) chunks [] current_chunk for para in paragraphs: # 如果当前块加新段落超过chunk_size先落库 if len(current_chunk) len(para) chunk_size and current_chunk: # 保留尾部overlap_size字符用于上下文衔接 overlap current_chunk[-overlap_size:] if overlap_size 0 else chunks.append(current_chunk) current_chunk overlap para else: current_chunk \n para if current_chunk: chunks.append(current_chunk) return chunks chunks smart_split(manual_text) print(f切块数量: {len(chunks)}) for i, chunk in enumerate(chunks[:3]): print(f--- Chunk {i} (长度: {len(chunk)}) ---) print(chunk[:100])为什么这样切因为固定长度的暴力切块很容易把语义切断。比如一段讲“报销流程”的文本被直接切成了两半前半说“需要提交的材料”后半说“审批人是谁”那用户问“报销需要什么材料”时检索很可能只命中前半截答案就不完整。按段落切块更贴近文档本身的语义边界生产环境还可以根据Markdown标题结构做递归切块确保一个章节不会被拆分到多个块里。3.3 第二步向量化与检索实现接下来对每个切块做向量化。我们用OpenAI的Embedding接口来做示例。如果你的场景是私有化部署换成BGE-M3或者M3E这类开源模型也是同样的流程只是调用的接口不同。from openai import OpenAI import numpy as np client OpenAI( api_keyyour-api-key, base_urlhttps://api.openai.com/v1 # 替换为你的服务地址 ) def get_embedding(texts): 批量获取文本向量 # 单条文本长度超过8000字符时截断避免API报错 processed [t[:8000] for t in texts] resp client.embeddings.create( modeltext-embedding-3-small, inputprocessed ) return [item.embedding for item in resp.data] # 对全量切块做向量化 chunk_vectors get_embedding(chunks) print(f向量维度: {len(chunk_vectors[0])}) print(f向量数量: {len(chunk_vectors)})注意这一步会调用API大批量文本会产生一些费用。在正式投产时会把向量化和向量存储做成离线任务每天晚上定时增量更新而不是每次问答时实时计算。如果是做原型验证第一次全量计算之后就保存到本地后续直接用VectorStore加载。向量检索的核心操作其实就是“计算余弦相似度然后排序”。我们用Numpy实现def cosine_similarity(vec_a, vec_b): dot np.dot(vec_a, vec_b) norm_a np.linalg.norm(vec_a) norm_b np.linalg.norm(vec_b) return dot / (norm_a * norm_b) def search(query, top_k5): 检索与查询最相关的文本块 query_vec get_embedding([query])[0] scores [] for idx, chunk_vec in enumerate(chunk_vectors): score cosine_similarity(query_vec, chunk_vec) scores.append((idx, score)) # 按相似度排序 scores.sort(keylambda x: x[1], reverseTrue) return [(idx, score, chunks[idx]) for idx, score in scores[:top_k]]试试效果results search(年假有多少天可以拆开休吗) for idx, score, chunk in results: print(fChunk {idx} | 相似度: {score:.4f}) print(chunk[:200]) print()这一步输出的结果千万要肉眼检查一遍。如果Top 5里没有出现“年假”相关内容别往下走先把检索修好。这是我做RAG这么多年的铁律生成效果不好可能是模型的锅但检索效果不好一定是检索自己的锅。3.4 第三步Prompt组装与生成回答检索到相关资料后把它们组织和Prompt拼在一起调用LLM生成最终回答。def build_prompt(query, contexts): context_block \n\n---\n\n.join( [f【资料{idx1}】\n{context} for idx, context in enumerate(contexts)] ) prompt f你是一名专业的企业知识库助手。请基于以下资料回答用户问题。 要求 1. 优先引用资料中的内容确保回答有依据 2. 如果资料不足以回答问题明确告知“现有资料无法完整回答这个问题” 3. 不要编造资料中不存在的信息 4. 回答尽量简洁、直接使用用户的语言习惯 【参考资料】 {context_block} 【用户问题】 {query} 请回答问题 return prompt def rag_answer(query): # 1. 检索 results search(query, top_k4) contexts [chunk for _, _, chunk in results] # 2. 生成 prompt build_prompt(query, contexts) resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: prompt}], temperature0.3 ) return resp.choices[0].message.content, [(idx, score) for idx, score, _ in results] answer, sources rag_answer(我入职满一年后年假有几天) print(回答, answer) print(检索来源, sources)这里有个重要设计temperature0.3。知识问答场景要求的是准确性不是创造性温度越高越容易让模型“发挥”出原文没有的东西。生产环境我通常固定在0.1-0.3区间。另外Prompt中强调“不要编造”等于给模型画了一道红线——检索到的资料才是唯一事实来源切口越死输出越可信。3.5 最后一步包装成API服务让Agent能够调用这套RAG能力最简单的做法是把它包装成一个FastAPI服务。Agent的工具调用机制通过HTTP接口就能访问。from fastapi import FastAPI from pydantic import BaseModel app FastAPI(titleRAG Knowledge Service) class QueryRequest(BaseModel): question: str top_k: int 4 class QueryResponse(BaseModel): answer: str sources: list app.post(/query, response_modelQueryResponse) def query(req: QueryRequest): answer, sources rag_answer(req.question, req.top_k) # 把检索来源的引用信息格式化方便Agent引用 return QueryResponse(answeranswer, sourcessources) # 启动命令: uvicorn main:app --host 0.0.0.0 --port 8000这样一个最简RAG服务就搭好了。内部逻辑不复杂本质就三步查、拼、答。但真正做到生产级别还要考虑并发、缓存、增量更新、权限隔离、检索质量监控等一堆问题。不过骨架先立起来后面往里面填肉就有方向了。4. 检索质量优化从“能跑”到“好用”的关键改造4.1 三种主流切块策略横向对比切块这件事在网上争议很大问“rag切块到底用什么策略”的人特别多。归根结底切块方式的选择取决于你的文档类型。我把三种主流策略放在一起做了个对比策略实现方式优点缺点适用场景固定长度切块按固定字符数切割可加重叠实现简单速度最快容易切断语义检索完整性差纯文本、无结构文档快速原型结构感知切块按标题/段落/列表层级切分语义完整性好检索精度高依赖文档结构识别处理复杂Markdown、HTML、格式规范的文档父子切块检索用小块喂给模型用父块兼顾精度与完整上下文实现复杂存储量翻倍长篇文档、技术手册、法规政策我实际用得最多的是结构感知切块。如果文档本身有清晰的标题层级就递归地按章节切没有明显结构就按段落语义断点来切。一个小技巧是给每个块打上元数据标签记录它属于哪个章节、哪个文档、哪个产品线。检索时先用元数据过滤掉明显不相关的领域比如用户问福利就别把“薪酬计算”章节捞进来再做向量排序效率高不少。切块大小也是要调的。我试过从200到800字符的多个档位300-500这个区间在大多数业务问答场景下表现最好。太短了信息量不足比如答案本身需要跨段落才能凑齐太长了又会让模型迷失在细节中比如一个块里包含了三个不同的主题模型不知道该用哪段。4.2 Embedding模型和向量数据库怎么选Embedding模型的选择直接决定相似度计算的“语义观”。不同模型的中文语义空间差异很大。我的建议是做一套自己的评测集至少准备50个真实业务问题每个问题标注标准答案所在文档然后拿不同模型跑一遍看Recall5的命中率。开源这边BGE系列和M3E系列都不错在中文语义理解上表现稳定。必须说明的是Embedding模型没有“谁全面碾压谁”这回事不同专业领域的表现差异很大。你是做法律问答的他是做代码问答的评测结果可能完全相反。只信自己的测试数据。向量数据库选型方面如果数据量在百万级以下、单机跑直接用FAISS就够了需要在SQL里同时管业务数据和向量选pgvector真要搞大规模分布式的企业场景再上Milvus或Qdrant。**大部分团队开始时根本不需要单独部署向量数据库服务轻量方案能省掉大量运维成本。**等数据量真的大了再迁移也来得及数据导出导入的工程成本远小于提前搭建复杂架构的沉没成本。谈到“本地erp rag llm 产品检索”这类场景我倒是想多说一句。企业ERP里的产品数据是结构化表格跟文档型知识库不一样。结构化数据做RAG通常不直接embedding整张表而是先把每行数据用自然语言“描述”成一个句子比如“A型空气净化器适用面积30-50平方米CADR值400立方米/小时售价2999元”然后对这些描述文本做向量化。这样既保留了结构化字段的规范性又能利用RAG的语义检索能力。4.3 多轮对话里的RAG怎么设计才不翻车RAG在单轮问答里表现很稳但放在Agent的多轮对话场景就会出现各种尴尬。用户问完“年假几天”之后接着问“那我可以连着春节一起休吗”如果你直接把第二句话去检索检索出来的结果大概率是“春节放假通知”而不是“年假政策”。想让RAG服务好Agent需要处理历史状态。业界主流做法是查询改写而不是把历史记录全部喂给检索。具体来说Agent在进入知识库检索之前先调用一次LLM把多轮对话压缩成一个独立问题。比如上面的例子查询改写的结果应该是“员工年假能否与春节假期连续休息需要满足什么条件”。这相当于在检索之前先做一次意图补全让检索器拿到的是一个能独立存在的完整问题。这个环节的实现并不复杂核心就是让LLM根据对话历史和当前问题生成一个“独立的检索问题”def rewrite_query(dialogue_history, current_question): prompt f你是一个对话查询改写助手。根据对话历史和当前问题生成一个独立的、可用于知识检索的完整问题。 要求保留核心实体和意图去掉口语化指代词不能用对话历史里的指代如“它”“这个”“那个”。 【对话历史】 {dialogue_history} 【当前问题】 {current_question} 请输出改写后的独立问题 resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: prompt}], temperature0 ) return resp.choices[0].message.content.strip()还有一个常见的多轮坑就是引用追踪。我在做AgentRAG时发现用户特别喜欢追问“你刚才说的这个规定在哪一条”。如果你在多轮状态里只记录大模型的回答文本没有保留它回答时到底引用了哪个知识块遇到这种追问就完全懵了。解决办法是在返回答案时一起返回source的元数据并且把这些source ID存进对话状态的上下文里让Agent在后续追问时能直接定位到当初引用的原文块。4.4 RAG和MCP模型上下文协议的区别“rag和mcp区别”也是高热度问题。简单说RAG是“让模型读到没学过的知识”MCP是“让模型调用没学过的能力”。RAG打通的是外部静态知识库MCP打通的是外部动态工具比如查询实时天气、调用业务API、读写数据库、操作办公软件。两者经常配合在一起用。一个企业Agent的知识获取管道里面往往既有RAG成分也有MCP成分RAG负责提供公司的制度文档、技术资料这些静态知识MCP负责实时查询某个订单的状态、写入一条CRM记录、在工单系统里创建一个工单。它们解决的不是同一类问题也不存在谁取代谁的选择。还有一种说法叫Agentic RAG这个概念指的是让智能体自主决定“什么时候检索、检索几轮、检索完之后还要不要查另一个库”。传统的RAG是固定管道用户一问就检索一次拿结果就回答。Agentic RAG把检索策略本身交给了Agent来决策——可以先粗查一遍发现资料不够再深挖一轮也可以把一个大问题拆成几个子问题分别对不同知识库检索最后汇总。这种思路更接近真人查阅资料的过程效果更好但工程复杂度也相应高很多。初学者先把基础RAG做扎实再考虑Agentic化别一上来就整大架构。4.5 检索不到与检索错误排查顺序要固定我把RAG实际跑起来之后遇到最多的情况就是“检索结果不对”。这个问题的排查一定要按固定顺序来不能瞎试。我的排查顺序是文档解析质量 → 切块粒度 → Embedding模型 → 检索方式 → 重排序 → Prompt质量。先看原始文档解析出来是否完整无误这一步最容易出问题但最容易被忽略——PDF表格解析错位、扫描件文字错乱这些脏数据会让后面所有环节白干。然后是切块切开之后人工读几块看内容是否完整、语义是否连贯。然后是Embedding模型用标准问题测试Top 5命中率如果这个模型在你的数据上效果不好就换一个。检索方式的对比测试要记录数据不要纯靠感觉判断。很多团队调RAG效果不好其实不是RAG本身的问题而是**“脏数据进脏数据出”**。我见过最夸张的一个案例客户说RAG效果差结果一查是PDF解析工具把整个表格的列顺序全打乱了所有检索出来的“答案”都是几个字段拼接的乱码。你后面再怎么调Prompt、换模型都没用根源在数据源。所以我的建议是在数据进入知识库之前一定要做数据质量检查这不只是看有没有乱码还要检查完整性、重复度、时效性。5. 实战中的高级技巧与架构扩展方向5.1 从“搜索”到“知识打通”分层检索架构当知识库规模变大单个检索已经不够用了。我搭过一套分层检索架构第一层是关键词粗筛把所有文档按标签、产品线、业务域做倒排索引先把候选范围缩小到可能相关的几百篇第二层是向量细排对候选文档里的切片做向量检索精确找出Top-10相关片段第三层是重排序精排用重排序模型在这10个片段中选出最相关的3-5个交给模型生成。整个过程类似你在一个图书馆里找一本书先按分类找到书架区再浏览书目找到书最后翻开书找到细节。这样做的好处有三个一是大幅减少向量检索的计算量不需要每篇文档都算相似度二是减少噪音干扰关键词粗筛把领域过滤掉了三是检索结果稳定不会因为某个离谱的上下文匹配引入无关内容。这一套架构对于“产品检索”这类高频业务场景尤其好使。5.2 结构化知识与知识图谱的引入RAG的另一个升级方向是Ontology RAG也就是把知识图谱引入RAG管道。纯文本向量检索解决不了多跳推理的问题比如“甲产品用的芯片供应商和乙产品的芯片供应商是不是同一个”这种问题如果你只对独立文本切片做检索根本无法把跨文档的实体关系串联起来。引入知识图谱后的RAG流程是先把文档里的实体如产品、供应商、负责人、日期和关系如“使用”“依赖”“负责”抽取出来构建成图结构检索时先走向量通道找到相关文档再沿着图中实体关系做一跳或多跳扩散把间接相关的信息一起捞出来。这个做法的效果在“关联信息查询”场景下非常明显但它对数据质量的要求更高图谱构建的冷启动成本也更大。如果是小型项目不建议一开始就上图谱先用增强型RAG把基础体验做好就够用了。5.3 生产环境的增量更新与缓存设计知识获取管道跑起来之后没人想让每次改动都全量重建索引。合理的做法是增量更新机制文档有新增、删除、修改时通过监听事件触发对应文档的重新切块、重新向量化、替换旧索引。这里面有个坑要注意文档修改后旧切块必须精准删除不能只往向量库里加新数据——否则同一个文档的新旧版本会共存检索结果就出现“哪个版本都说自己是正确的”这种混乱。回答缓存也可以考虑。同一问题短时间内被重复提问时比如多个员工问同一句“报销流程”直接命中缓存返回上次答案能大幅降低LLM调用成本。但缓存要设计有效期知识库里内容变了缓存就得失效。最简单的做法是把知识库版本号作为缓存key的一部分知识库一更新旧缓存自动作废。5.4 AI Agent和RAG的经典配合场景我把这些年做过的RAG落地场景串一下你会发现它们都有一个共同点有一个明确的知识源用户问的问题标准答案就在这个知识源里。最有代表性的三类应用是客服助手、内部知识问答、产品智能推荐。客服助手收到的用户问题五花八门但解决办法基本都在公司FAQ、操作手册、政策文件里用RAG就能答得八九不离十内部知识问答跟Agent配合做“企业大脑”对接制度文档、项目档案、供应商资料产品智能推荐则是把产品参数表、客户评价、销售话术打通给销售在谈单时提供实时参照信息。比较值得多说一句的是“ai agent与plc编程”这种偏工控领域的场景。在工业控制领域RAG同样有用武之地把设备手册、PLC编程规范、历史故障处理记录做成知识库接入Agent工程师提问“西门子S7-1200的模拟量模块组态步骤是什么”RAG就能从几百页手册里把对应章节捞出来由Agent整理成操作指南。这类场景还经常结合OCR使用把纸质设备说明书先数字化再建知识库。5.5 踩坑实录三个最典型的翻车现场这两年我做过不少RAG项目事先声明一下下面这些坑全是我自己或者客户真实遇到过的不是网上抄来的段子你可以当场对照检查自己的项目有没有踩雷。翻车现场一PDF表格解析乱序。有一次做合同条款审查的Agent用户问某个合同里价格调整条款怎么写的RAG检索返回了一大段文字模型根据这段文字给出的回答是正确的。但另一个用户问违约金的计算方式答案就驴唇不对马嘴了。后来一查发现那份合同是扫描版的PDFOCR识别时表格结构全乱数字被串到了不同的列里。从那以后我立了一条规矩凡是PDF进来的数据必须抽样人工核对解析结果不核对不建库。翻车现场二切块切断了关键数字。一个设备维修知识库里有一条规定“设备冷却水温超过85摄氏度时必须停机”如果切块时把这个句子拦腰切断“设备冷却水温超过85”是一块“必须停机”是另一块用户问“水温多少度需要停机”时检索到的块只有前半句模型就给出了“超过85”这种没头没尾的答案。系统性解决方法是关键信息完整性检测——切完块之后扫一遍看有没有数字、单位、条件句被截断的迹象发现异常就调整切分边界。翻车现场三把RAG当搜索引擎用。有次一个客户非说他的RAG效果不好一看日志好家伙用户问“咱们公司有健身房吗”知识库里根本没有健身房相关记录模型严格按照“不基于资料编造”的规则回答“现有资料中没有找到相关信息”这结果本身是对的但客户认为“正确回答问题”应该是“主动告诉用户公司健身房在哪个楼”。这类问题暴露的是两条一是知识库覆盖度不够二是Agent缺少“主动去查另一个数据源”的能力——前者好解决补数据后者就要引入上面说的Agentic RAG和MCP去打通更多数据源了。6. 我把RAG当成一个系统工程来做写了不少干货最后说点掏心窝的话。**如果你搭完RAG之后效果不理想不要马上怀疑模型不够强。先老老实实跑一遍检索质量测试看看你的知识库数据够不够干净、切块粒度合适不合适、Embedding模型在你的领域里表现怎么样。**我见过太多团队把大量精力花在调Prompt上结果根本问题在数据层。RAG的效果上限基本由你的知识库质量决定LLM只是把检索到的信息最终转述出来而已。还有个小技巧每次给Agent接新的知识库之前我都建议先准备一套“标准问题集”——至少50个覆盖高频场景的问题每个问题标注标准答案应该在哪些文档里能找到。每次改完知识库管道跑一遍这个测试集看命中率的变化。这样你就不是靠感觉调参而是有数据在背后支撑决策。最后再分享一个方向**RAG其实还有很大的优化空间比如“Self-RAG”让模型在生成时对检索结果做自我反思评估检索内容是否足够回答还有“Corrective RAG”检索质量差的时候自动触发第二轮回溯更有“Long RAG”先把检索扩展到整个段落甚至整个章节让模型读更长的上下文理解全局关系。**这些都是从“基础RAG”走向“生产级RAG”的必经之路。第四篇先讲到这里下一篇可以聊聊Agent里的记忆机制或者工具调用设计等我把思路整理完再来更新。
返回列表