简介:本文面向开发者、技术负责人及企业用户,系统讲解2025年AI Agent与RAG技术的落地路径。你将了解AI Agent如何从技术概念演进为可执行复杂任务的数字员工,掌握RAG系统从基础到高级的构建与优化方法,并获得可直接用于生产环境的架构设计、实施步骤、验证手段及排错思路。
本教程旨在帮助读者完成两项核心任务:
第一,理解AI Agent的技术演进脉络,掌握将一个大模型应用改造为具备自主规划、工具调用与任务执行能力的智能体的通用方法。第二,构建一套可用于生产环境的RAG系统,解决大模型在知识时效性、领域专有性和回答幻觉方面的问题。
阅读完本教程后,你将能够:
本教程适用于以下技术场景:
如果你是企业技术负责人,希望评估AI Agent在自身业务中的可行性;或者是后端开发工程师,需要落地一套RAG检索增强生成系统;又或者是算法工程师,想从基础RAG迁移到更高级的多路召回与重排序方案,本教程都适合你。
在开始之前,请确认具备以下基础条件:
普通的模型调用模式是“一问一答”:用户输入一段提示词,模型返回一段生成文本。这种模式缺乏对复杂任务进行分解和执行的能力。
AI Agent的核心区别在于引入了控制循环。在这个循环中,模型不仅生成回答,还生成“下一步做什么”的决策。一个典型的Agent控制循环包含以下环节:
这个控制循环使得Agent从一个被动的文本生成器演进为主动的任务执行器。这也是“数字员工”这一比喻的技术本质:它不是一个只会回答问题的模型,而是一个能够在给定目标下自主调用工具、获取数据、执行操作并交付结果的程序。
要让Agent具备行动能力,首先需要定义工具接口。一个通用的工具定义应包含以下字段:
工具描述:名称:query_metrics功能:查询指定时间范围内某个监控指标的时间序列数据参数:- metric_name: 指标名称,字符串类型,必填- start_time: 起始时间,ISO8601格式,必填- end_time: 结束时间,ISO8601格式,必填- aggregation: 聚合方式,枚举值(avg/max/min/sum),选填,默认avg返回:JSON对象,包含数据点数组和查询状态使用场景:当用户询问某个指标的变化趋势或具体数值时使用
工具描述需要足够清晰,因为模型本质上是依据工具描述文本来决定调用哪个工具、传什么参数的。描述越精确,Agent选取正确工具的概率越高。
建议遵循以下设计原则:
Agent的提示词结构比单轮对话复杂得多。建议采用“角色定义—工具描述—工作流程—输出约束—示例”的五段式结构。
角色定义部分,明确告诉模型它是什么角色、服务什么用户、最终交付什么成果。例如:“你是一个企业级数据分析助手,服务业务运营人员,最终交付一份包含趋势判断和异常原因分析的数据简报。”
工具描述部分,将上一步定义的工具说明以结构化方式嵌入提示词。
工作流程部分,规定Agent的通用执行策略。例如:
输出约束部分,规定最终输出的格式、长度、语言风格,以及是否需要在回答中标注引用的数据来源。
示例部分,提供一到两个完整的“用户输入—规划过程—工具调用—最终输出”的示例,帮助模型进行行为校准。
在代码层面,Agent的执行循环可以用如下伪代码表示:
function run_agent(user_input, max_iterations=8):messages = [{"role": "system", "content": SYSTEM_PROMPT},{"role": "user", "content": user_input}]final_answer = Nonetrace = []for i in range(max_iterations):response = call_llm(messages)action = parse_action(response)if action.type == "answer":final_answer = action.contentbreakif action.type == "tool_call":tool_name = action.tool_nametool_params = action.paramsresult = execute_tool(tool_name, tool_params)trace.append({"step": i,"tool": tool_name,"params": tool_params,"result": result})messages.append({"role": "assistant","content": format_tool_call(action)})messages.append({"role": "tool","content": format_tool_result(result)})continueif action.type == "clarify":user_response = ask_user(action.question)messages.append({"role": "user", "content": user_response})continuereturn final_answer, trace
其中parse_action函数负责从模型输出中解析结构化的行动指令。在工程实践中,推荐使用工具调用能力,即模型直接输出结构化的JSON格式调用指令,而非自由文本解析。
max_iterations是重要的安全边界。它防止Agent出现无限循环,确保在最坏情况下也能终止。生产环境中建议设置为5到10之间,同时监控每一步的耗时。
Agent在获得工具调用权限后,风险也随之上升。一个失控的Agent可能反复调用接口导致成本飙升,或者执行了不应执行的操作。
建议在工具执行层加入以下防护:
RAG(检索增强生成)的核心思想是:在生成回答之前,先从外部知识库中检索与问题相关的文本片段,将这些片段作为上下文与用户问题一起送入大模型,引导模型基于检索到的信息生成回答。
RAG解决了两类核心问题:
其一,知识实时性。大模型的训练数据存在时间截止,无法回答训练后发生的事件。通过接入实时更新的知识库,RAG让模型具备获取新知识的能力。
其二,幻觉控制。当模型被要求基于给定材料回答时,生成内容偏离事实的概率显著降低,因为上下文中已经有明确的依据。
一个最小的RAG系统包含以下组件:
文档加载与清洗
将目标文档读取为纯文本。对于PDF文档,需要先将页面内容提取为文本;对于网页内容,需要去除HTML标签和导航元素。清洗阶段重点处理以下问题:
文本分割策略
文本分割是影响检索质量的关键环节。分块太大,检索结果会携带过多无关信息,稀释有效上下文;分块太小,语义完整性被破坏,模型无法获得足够上下文。
建议的通用做法是:以256到512个Token为基本分块大小,同时保留一定的重叠区域(通常为分块大小的10%到15%),以减缓边界信息丢失。对于结构化较强的文档(如技术规格书),可以按章节标题进行结构感知的分割。
一个简化的分割处理如下:
function split_document(text, chunk_size=512, overlap=64):tokens = tokenize(text)chunks = []start = 0while start < len(tokens):end = min(start + chunk_size, len(tokens))chunk = tokens[start:end]chunks.append(chunk)if end >= len(tokens):breakstart = end - overlapreturn chunks
嵌入与索引
将每个文本分块通过嵌入模型转换为向量。向量维度通常在768到3072之间,具体取决于所选用的嵌入模型。将所有向量存入向量数据库,并保留原始文本作为向量的元数据。
索引完成后,验证方法:随机选取几个文本分块,用其中一个分块的内容作为查询,检查该分块自身是否能被检索到。这是最基础的召回自检手段。
检索与生成
当用户提问时,流程如下:
你是一个知识库问答助手。请根据以下参考资料回答用户的问题。如果参考资料中没有相关信息,请明确说明“根据现有资料无法回答”,不要编造内容。参考资料:[片段1内容][片段2内容][片段3内容]用户问题:{用户问题}回答要求:回答需准确、简洁,并在结尾标注所引用的参考片段编号。
基础RAG在很多真实场景下表现不佳,常见问题包括:用户问题与文档片段之间的语义存在差异导致检索不准、单一向量检索无法覆盖不同维度的相似性、检索到的文档片段之间缺乏关联导致上下文碎片化等。
高级RAG通常从以下维度进行优化:
查询改写
用户自然语言提问通常比较口语化,与文档中的专业表述存在较大差异。解决方法是使用一个轻量级的LLM调用,在检索之前对用户查询进行改写和扩展。
常见的查询改写策略包括:
一个查询改写示例:
原始用户问题:我们那个系统最近总是卡,怎么弄?查询改写结果:业务系统响应延迟高,排查方法与优化建议多视角扩展:查询1:系统性能下降原因分析查询2:响应时间过长故障排查查询3:服务端接口延迟优化方法
混合检索
单一向量检索倾向于捕获语义相似性,但对精确的关键词匹配不敏感——尤其在涉及工单编号、报错代码、版本号等领域专有标识时,语义检索可能完全失效。
混合检索同时执行:
通用融合逻辑如下:
function hybrid_rerank(vector_results, keyword_results, alpha=0.6):combined_scores = {}for result in vector_results:combined_scores[result.id] = alpha * result.scorefor result in keyword_results:if result.id in combined_scores:combined_scores[result.id] += (1 - alpha) * result.scoreelse:combined_scores[result.id] = (1 - alpha) * result.scorereturn sort_by_score_desc(combined_scores)
其中alpha控制向量检索与关键词检索的相对权重,通常设置在0.5到0.7之间,需要结合实际场景通过离线评估确定。
重排序
初次检索返回的Top-K片段在原检索模型中的相对顺序并不总是与最终答案的相关性一致。重排序阶段使用一个更精细的相关性判断模型,对候选片段进行二次打分和排序,选取精排后的Top-N(通常为3到5个)片段送入生成阶段。
这一步的核心价值在于:进入模型上下文的内容质量比数量更重要。与其塞入10个半相关的片段,不如只提供3个高度相关的片段。
文档摘要索引与片段关联
对于长文档场景,可以先建立文档级别的摘要索引,再在文档内部建立片段索引,形成两级检索结构。用户查询先定位到相关的文档,再在文档内部进行片段级检索。这种方式能有效减少跨文档的零散片段混入上下文的情况。
同时,可以在片段元数据中记录该片段所属的文档、章节标题、前后邻接片段编号。当某一片段被检索命中时,可以顺带拉取其前后邻接片段,保证上下文的连贯完整。
RAG系统的优化是一个迭代过程,没有评估就没有方向。建议在进入优化循环之前,先建立一套基线评估集。
评估集至少包含30到50个真实的用户问题,每个问题标注:
基础评估指标包括:
每次调整RAG系统的任何环节(分割策略、嵌入模型、检索参数、提示词模板等),都需要在评估集上重新跑一遍,对比前后指标变化,形成“修改—评估—再修改”的闭环。
问题一:检索结果与用户问题完全无关
排查方向:检查查询嵌入是否与文档嵌入使用同一模型和同一向量空间;检查文档预处理是否导致文本被错误截断或混入乱码;尝试用几个文档中的原句作为查询,验证索引是否正常工作。
问题二:检索到了相关文档,但回答中声明“无法回答”
排查方向:检查上下文拼接后的总Token数是否超出了生成模型的上下文窗口,导致有效片段被截断;检查提示词模板是否对“无法回答”的判定过于敏感,需要调整措辞。
问题三:回答内容确实来自文档,但信息过时
排查方向:检查索引更新流水线是否正常运行。文档修改或新增后,旧向量是否已从索引中删除?是否存在重复索引导致新旧版本同时被检索到的情况。建议在写入向量时附带文档版本号,并在检索结果去重时优先保留最新版本。
问题四:多轮问答中,后续问题丢失了对话上下文
排查方向:检索阶段是否只使用了当前轮的用户问题,而忽略了对话历史。解决方案是将改写后的对话压缩摘要与当前问题拼接后作为检索查询,同时将历史对话摘要注入生成阶段的提示词。
问题五:混合检索的融合结果不稳定
排查方向:检查向量检索和关键词检索各自的分数分布,确认归一化方法是否合理。可能需要调整融合权重alpha,或在融合前对两路分数分别做百分位归一化。
性能层面:对文档预处理和嵌入生成采用批量异步处理;对高频查询使用缓存,降低重复计算;对超长文档的分割和嵌入使用并行任务。
安全层面:在文档写入索引前进行敏感信息扫描与脱敏;对用户查询和检索结果进行内容过滤;在涉及企业内部的权限控制场景中,应实现文档级或片段级的访问控制,将鉴权逻辑放在检索阶段而非生成阶段。
稳定性层面:为检索和生成环节设置超时与重试机制;对索引构建过程记录状态和断点,支持失败重跑;在每次系统升级前备份索引版本,确保可回滚。
可维护性层面:将分割策略、嵌入模型、检索参数、提示词模板等作为可配置项外置,避免硬编码在逻辑代码中;为每次索引构建保留参数快照,方便问题回溯。
成本控制层面:根据问题的复杂度动态选择生成模型;对简单事实类查询优先返回检索片段本身,减少生成调用;对Agent场景中的工具调用次数设置上限,避免失控访问。
本教程从AI Agent的控制循环本质出发,梳理了从工具接口设计、提示词框架构建到执行循环实现与安全管控的完整落地路径。在RAG部分,我们覆盖了从基础流水线搭建到查询改写、混合检索、重排序等高级优化手段,并给出了评估体系的构建方法和常见问题的排查思路。
AI Agent与RAG并非相互独立的技术方向。将RAG作为Agent的核心工具之一,让Agent在自主规划中动态决定何时检索、检索什么、如何使用检索结果,是当前企业级智能化应用中最具实用价值的组合模式。掌握本文所描述的基础能力后,你可以进一步探索Agent的长期记忆管理、多Agent协作机制以及面向特定垂直领域的深度调优。