首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
AI Agent底层逻辑:LLM推理与RAG协作的完整工程实践
📅 2026/10/17 3:28:44
✍️ 爱科研究院
👁 阅读 3,247
先说一个我观察到的现象现在聊 AI Agent很多人的第一反应是“这不就是给大模型加个工具调用嘛”或者“RAG 不就是检索文档喂给模型让它回答嘛”。这种认知不能说错但如果你真的拿这套理解去设计一个 Agent 系统大概率会踩坑踩到怀疑人生。尤其是把 LLM 和 RAG 放进同一个项目里时它们的关系绝不只是“一个负责思考、一个负责找资料”那么简单。这篇东西我不打算写成教科书式的概念堆砌而是基于我自己实际搭建过的几个模拟项目什么客服问答、资料整理、自动报告生成都试过拆解一下 AI Agent 的底层逻辑重点讲清楚 LLM 作为推理核心到底在干什么、RAG 在什么环节介入、两者之间是怎么协作的。同时会把一些“文档里不会写”的取舍和教训拿出来晒一晒。如果你正在设计自己的 Agent或者准备学习这方面的架构这篇文章应该能帮你省掉不少瞎折腾的时间。1. 先拆清楚Agent 到底“智能”在哪一步很多人把 Agent 想成“一个聪明的东西”实际上 Agent 不是什么黑盒它是一套循环系统感知任务 → 规划步骤 → 调用工具 → 观察结果 → 再规划 → 直到完成。这套循环里的“大脑”是 LLM但 LLM 不是每时每刻都在“想”它只是在关键节点做决策——就是你要它从一堆选项里选一个下一步动作的时候。举个我做过的最简客服 Agent用户问“我的订单怎么还没发货”如果只是套一个 LLM 摆在前面直接让它回答它大概率会从自己的训练记忆里编一个物流状态这在生产环境里是不能接受的。所以我在它的循环里加入了工具集查订单接口、查物流接口、查售后政策Agent 的“智能”体现在它决定调哪个接口、怎么处理接口返回的数据、以及拿到数据后怎么组织语言回复用户。这就是 Agent 和普通 chat 接口的分水岭普通的 LLM 对话是一次性生成Agent 是多轮递进生成它会根据每一轮的结果调整下一步行为。理解这个以后再看 RAG 在其中的角色就清晰了——RAG 负责的是“系统在决定下一步动作前需要补充哪些知识”这件事。1.1 为什么说 LLM 是“推理器”而不是“知识库”说个最容易被误解的点很多人觉得大模型训练了那么多数据它应该什么都知道。实际用下来它“知道”的东西是它的训练语料里出现过的模式而不是随时更新的、具体到你业务场景里的事实。你让它总结一段文档内容它做得很好你让它回答“咱们公司今天库存还有多少”如果你没有接入任何实时数据源它要么编一个要么告诉你不知道。所以在 Agent 架构里我通常把 LLM 的作用限定为基于给定的信息进行拆解、判断、选择、生成。它更像一个拿着工具的工人工具给得好不好、工作流程顺不顺决定产出质量。RAG 就是给这个工人递资料的人——但它比一般的人靠谱一些能在递资料之前先帮工人筛选掉不相关的东西。1.2 RAG 在 Agent 循环里到底补了什么RAG检索增强生成全称是 Retrieval-Augmented Generation。它的核心动作是“先查再答”把用户的问题先去知识库检索相关片段把检索到的片段拼进 prompt再由 LLM 基于这些片段组织答案。这样做有两个直接的好处一是答案的准确性大幅提高因为模型不需要凭空推测事实二是回答可以带上知识来源的“痕迹”方便后续追溯。放到 Agent 的循环里看RAG 往往不是每轮都要触发。Agent 先判断当前这一步需不需要外部知识如果需要就走检索通道如果不需要就直接让 LLM 推理。这个判断本身的准确度决定了整个系统是不是高效。2. 构建 Agent 第一步决策循环的设计我在项目里最常用一个极简的四步循环Step 1接收任务做意图识别和初步拆解Step 2检查工具清单判断当前需要哪些工具或外部知识Step 3调用对应工具 / 进行检索观察返回结果Step 4根据结果判断是继续下一步还是输出最终答案这个循环看起来简单真正麻烦的是 Step 2 和 Step 4 的“判断”。LLM 在这里扮演的是路由器的角色但路由器也会有犯迷糊的时候。2.1 用大模型做“路由判断”的实战设计我最初做的 Agent 里路由逻辑写得很粗暴每条用户输入都先用一个二分类标签需要检索 / 不需要检索过一遍。分类标签本身也有人让 LLM 直接做效果不稳定最后选择了给 LLM 一个“工具选择列表”和“当前任务状态”让它自己选实测效果好很多。具体怎么设计这个 prompt我习惯把所有工具描述成一个 JSON 列表每个工具包含名称、用途、适合场景、参数要求。这里不能偷懒去写“调用 xxx 工具”而是要把工具的白话场景说明写清楚模型才能准确匹配。例如你有一个“查天气”工具如果只写“天气查询参数是城市名”模型在一个复杂的 Agent 任务里就很容易调用错地方因为描述缺少“适合什么时候用”的语义信息。2.2 一次真实的“多步骤任务”拆解演算有个实际例子我让 Agent 执行一个“整理目标客户公司近期动态并做摘要”的任务。Agent 收到这个任务后的内部序列长这样第一次调用 LLM它判断需要两个能力公司信息检索 新闻文章检索。它列出了一个计划。执行公司信息检索拿到了公司简介和基础资料。再执行新闻检索发现没有找到近期新闻返回的结果为空。它没有就此停住而是判断“这个公司可能有其他别名或者媒体报道里用的是简称”于是改了一个关键词重新检索。这次拿到了新闻列表接着它从新闻里提取出和“融资、团队变动、产品发布”相关的段落再调用 LLM 做摘要。最后输出一份包含多条结论的汇总报告每条后面都标注了信息来源。整个序列里最让我惊喜的其实是第三步那个“发现检索结果为空 → 换一个关键词再试”的行为。这不是我显式写进规则里的而是 LLM 在“当前状态 可用工具描述”的组合下自主决策的结果。这也说明了设计 Agent 时到底应该把多少逻辑交给 LLM、多少逻辑交给规则。我的经验是稳定可控的部分用规则需要灵活判断的部分用 LLM。比如工具之间的依赖顺序、必须校验的参数格式这类我全用代码约束至于“检索结果为空时下一步怎么办”交给模型判断反而更灵活。3. RAG 链路的关键环节检索不是把文档塞进 prompt 那么简单RAG 看似是个简单的三步曲——索引、检索、生成实操起来每一步都有不少坑。我在早期项目里直接把 PDF 文字塞进向量库检索效果惨不忍睹后来拆开才发现问题出在“分块策略”上。3.1 文档拆块的粒度与策略选择分块大小直接影响检索质量。块太长向量表示不够聚焦检索出来的一段内容里会包含大量无关信息块太短语义可能不完整模型拿到手后的生成质量很差。我做过一组对比实验同一份技术文档分别按 256、512、1024 的 token 长度分块配合 50 token 的滑窗重叠测试不同的问答效果。结论是512 token 左右的块在这份文档上综合表现最好既保住了语义完整性又没有引入太多噪声。但这个数值不是万能参数如果你的文档本身是问答对形式可能几百字一块就够了如果是长段落论述可能要更大的块加重叠窗口。对于分块我的个人建议是不是简单地按字数硬切而是结合文档的标题层级、自然段落来切。一种比较稳的方法是把 Markdown 文档按段落先拆散然后基于 token 上限做“块合并”保证每一块的语义相对独立。3.2 检索效果不好时的排查套路我把检索质量的排查套路大致整理成了一个清单每次 RAG 效果不对劲就走一遍这个流程检查项具体做法预期标准文档本身是否已被正确解析为纯文本直接打开索引前的内容看一眼没有乱码、没有乱序分块是否合理抽样看 10 个块的起始和结束位置每块语义相对完整检索结果与问题相关性用同一个问题手动执行一次 embedding 搜索看 TopK 结果里有没有正确答案重排序有没有做对比重排序前后结果排序差异重排序能修正向量相似度的偏差prompt 里有没有给模型足够的上下文指引检查生成 prompt 的指令区域明确要求“仅基于材料回答”这个清单陪我排查过好几个“模型回答文不对题”的问题多数时候问题出在前端检索而不在生成链路。4. 把 LLM 和 RAG 接起来的落地细节理论讲再多落到代码层面才是最真实的挑战。我这边用一个 Python 伪代码把核心逻辑展示一下方便你在此基础上搭建自己的结构。class Agent: def __init__(self, llm, retriever, tools): self.llm llm self.retriever retriever self.tools tools def run(self, task): messages [{role: user, content: task}] for step in range(self.max_steps): response self.llm.chat(messages) if response.is_final_answer(): return response.content action response.parsed_action() # 假设返回一个 JSON 动作 if action.is_retrieval(): docs self.retriever.retrieve(action.query) messages.append({ role: user, content: f检索结果{docs} }) else: tool_result self.tools.execute(action.tool_name, action.args) messages.append({ role: user, content: f工具返回{tool_result} }) return None # 超过最大步数则失败核心思路让模型每一轮返回一个结构化动作是回答就输出内容是检索就给检索词是调工具就给工具名和参数。Agent 执行完这个动作后把结果作为新的上下文继续喂给模型。4.1 给 Agent 配好“工具描述”的分寸感工具描述写不好整个 agent 的水平能跌一半。我见过太多次 agent 把“查天气”工具当成“问时间”工具来用原因就是描述里缺少边界条件。我现在的写法会包含工具名称、工具用途一句话、适合触发的情况、参数说明、以及不适合触发的情况。举个例子{ name: search_news, description: 检索指定主题的新闻文章列表适合用户询问某公司、某行业或某事件的最新动态时使用。如果用户只是询问常识而不需要最新消息无需使用此工具。, parameters: { keyword: string, 必填搜索关键词, time_range: string, 可选时间范围例如 7d、30d } }工具描述写得详细以后模型选错的概率明显下降。这不是什么高深的技巧就是你能不能让模型理解你的“设计意图”。4.2 引入 RAG 时的 Prompt 组装顺序我发现一个影响很大的细节RAG 检索到的资料放在 prompt 里的位置和格式会直接影响生成质量。我把检索结果放在一个独立的“参考资料”字段而不是当成普通对话历史的一部分并且在指令里明确声明“仅供参考不包含答案时要主动说明不知道”。如果检索结果格式是杂乱的网页文本我会先做一个简单的清洗步骤把段落拼接成一个带编号的列表。这样模型在回答时能够引用编号方便后续追踪它到底用了哪些材料。5. 工程化落地的几个“非功能”问题除了核心逻辑生产环境的 Agent 系统还有很多边角问题不处理好一样会难产。5.1 上下文窗口管理RAG 和工具调用都会显著增加上下文长度尤其是多轮工具调用之后对话历史里塞满了中间过程。直接用原始对话历史喂给模型很快会顶到上下文上限。我处理的方法是把 Agent 的“长期记忆”和“短期记忆”分开。多轮工具调用的中间结果只保留摘要不保留全文用户对话历史则做降采样。这样上下文窗口的占用可以大幅下降同时不丢失关键信息。5.2 检索结果的去重和重排序向量检索出来的 TopK 结果经常有重复内容尤其当文档分块有重叠窗口时。我在 RAG 链路里加了一个简单去重先按文档来源 块内容哈希去重然后再用独立的 rerank 模型对剩余结果重新排序。重排序这一步实测收益不小它能修正纯向量相似度带来的相关性偏差。如果你已经用上了 rerank检索结果的质量会再上一个台阶。5.3 可观测性给 Agent 装上日志Agent 系统调试靠什么靠日志。没有一次完整的推理过程记录出了问题你根本不知道是模型选错动作、工具返回异常还是检索没找到东西。我在每次循环的每个关键节点都打了一条结构化日志包含当前步骤、模型输出动作、工具调用结果、以及本次调用的 token 数。这样复盘时就像重放录像定位问题很快。日志字段主要包含以下几个字段说明step_id当前循环步数action_name模型选择的动作名action_input模型给出的动作参数tool_status工具/检索返回的状态码latency_ms单步耗时context_tokens当前已消耗的上下文 token 数6. 踩过的三个经典坑以及我怎么爬出来的干货不踩坑等于没干货。分享三个真实项目里让我印象极深的坑。6.1 依赖 LLM 判断所有事结果它乱来早期我把动作判断和内容生成全丢给 LLM没有做任何规则兜底。结果有一次 Agent 在检索结果为空时没有重试也没有放弃而是编造了一篇“不存在的新闻摘要”输出用户差点投诉。加了一段校验逻辑之后再也没出过这种情况。校验逻辑的核心是如果最终答案里有从外部获取的事实性内容必须能从检索或工具返回中找到对应来源否则强制拒答或输出“未知”。这个“来源验证”约束是我现在所有 Agent 项目的标配。6.2 RAG 检索到了内容但生成时“跑偏”有一次我调好的 Agent 在回答专业问题时明明检索结果正确模型回答却加了大量自己训练记忆里的泛化内容带着错误信息。后来发现问题出在 prompt 指令的措辞上——我给出的要求是“请根据以下资料回答问题”这太软了模型把它理解为“资料仅供参考你可以自由发挥”。改了几个版本下来“你只能使用以下资料中的信息回答不要加入资料以外的知识”效果最稳定但同时也建议加上“如果资料不足直接说无法回答”。6.3 纠结于“一步到位”的复杂设计反而拖垮了效果我不止一次见到上来就想做多 Agent 协作、动态规划、自我反思的团队最后卡在调试地狱里几个月出不来。我自己早期也有这个倾向。实际上单体 Agent 简单 RAG 能解决 80% 的问题复杂架构只在规模、效率、准确率确实撑不住的时候才值得上。我的原则是先把一个简单闭环跑通再逐步增加复杂度。每一步增加都要有明确的目的和可量化的效果提升而不是“为了架构而架构”。7. 最后分享一点心得我自己把 Agent 从“玩具”调到“勉强能用的生产工具”的经历里最大的教训是别迷信模型能力要把你的系统当作一个工程系统来设计。LLM 是组件RAG 是组件工具调用是组件中间的数据流、约束、兜底、监控才是让整个系统立住的骨架。还有个实用技巧如果你刚开始做 Agent与其用复杂的框架不如先用几十行代码把循环逻辑自己写一遍你能对每个环节有更直觉的理解。等清楚了瓶颈在哪再引入框架解决也不迟。包括 RAG 的分块参数、检索 TopK、重排序、prompt 指令设计这些看起来不起眼的细节才是真正决定 Agent 好用不好用的那部分。别让概念停留在“我知道”的层面亲自动手逛一圈你会发现那些坑都长得一模一样。
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/17 3:28:44
双电芯被动均衡BMS设计:MP2642GR-Z与TM4C123GH6PZ实战
2026/10/17 3:23:44
AVPlayer打造资讯App级列表视频流:UITableView自动播放与Cell复用实践
2026/10/17 3:23:44
STM32硬件IIC驱动QMC5883L磁力计与航向角校准实战
2026/10/17 4:23:48
VirtualBox安装CentOS7全流程避坑指南:镜像、网络、增强功能一次搞定
2026/10/17 4:23:48
物理AI入门:从感知到执行,重塑制造业与物流业的智能变革
2026/10/17 4:23:48
PHP酒店预订微信小程序源码拆解:从登录到支付全闭环
2026/10/17 4:23:48
ollama v0.14.2:离线翻译模型TranslateGemma与MLX构建指南实测
2026/10/17 4:23:48
深入理解MMDetection配置系统:从跑通到精通的第二篇
2026/10/17 4:18:48
C# 使用 ModbusTcp 读取西门子 S7-1200 的完整实现与避坑指南
2026/10/17 0:02:58
NetSpot 实战:用信道分析与频宽优化解决 Wi-Fi 卡顿
2026/10/17 0:02:58
C++ split() 字符串分割的五种实现与性能实测
2026/10/17 0:02:58
R语言坐标轴范围设置:从xlim/ylim到coord_cartesian的完整指南
2026/10/16 1:17:36
流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南
2026/10/16 1:17:35
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别
2026/10/16 1:17:35
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容
2026/10/16 1:17:35
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/16 18:46:48
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/16 18:46:46
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)