尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AI Agent 开发实战:从最小循环到工程化落地

AI Agent 开发实战:从最小循环到工程化落地 1. 从最小循环说起AI Agent 到底在“循环”什么很多人第一次接触 AI Agent脑子里浮现的是科幻电影里那种能自己思考、自己行动的智能体。但真到了动手搭建的时候你会发现最核心的东西其实特别朴素——就是一个循环。这个循环在业界通常叫Agent Loop翻译过来就是“智能体循环”。它做的事情可以用一句话概括让模型反复地“想一下、做一下、看一下结果”直到任务完成或者达到退出条件。我刚开始接触这块的时候也觉得这玩意儿能有多复杂不就是调个 API 吗但真正踩过坑之后才明白一个能跑通的循环和一个能扛住真实场景的循环中间隔着的不是几行代码而是一整套工程化的思考。这篇文章我会从最基础的循环结构讲起一步步拆到 Function Calling、Prompt 设计、Workflow 编排最后聊到怎么让这套东西变得可靠。适合刚入门 AI Agent 开发的同学也适合已经写过 demo 但总觉得“不太稳”的从业者。先说说为什么是“循环”。传统的 LLM 调用是单次的你给一个 Prompt模型返回一段文本结束。但 Agent 要解决的是多步骤任务比如“帮我查一下明天北京的天气然后根据天气推荐穿什么衣服”。这个任务拆开来看第一步是查天气第二步是根据天气结果做推荐。模型没法在一次调用里既查天气又做推荐因为它没有实时数据。所以你需要让它先输出一个“查天气”的动作你执行完把结果喂回去它再基于结果输出推荐。这个“输出动作 → 执行 → 喂回结果 → 再输出”的过程就是循环。这个循环的最小结构大概长这样while not done: response llm.chat(messages) if response.has_tool_call: result execute_tool(response.tool_call) messages.append(result) else: done True看起来很简单对吧但这里面每一个环节都有讲究。messages怎么维护工具调用的结果用什么格式塞回去什么时候判断done模型如果一直不返回最终答案怎么办这些问题在后面都会展开讲。提示如果你之前只写过单次 Prompt 调用建议先手动实现一遍这个最小循环不要急着上框架。框架帮你封装了很多东西但如果你不理解底层在干什么出了问题根本没法排查。2. Function Calling让模型从“说”变成“做”2.1 Function Calling 的本质是什么Function Calling 这个词听起来很技术但它的本质特别简单你告诉模型有哪些函数可以用模型决定什么时候调用哪个函数并且帮你把参数填好。注意模型本身不执行函数它只是输出一个结构化的调用请求真正执行的是你的代码。举个例子你定义了一个函数叫get_weather参数是city。当用户问“北京今天天气怎么样”模型不会直接回答而是输出一个 JSON 类似{ function: get_weather, arguments: {city: 北京} }你的代码拿到这个 JSON去调真实的天气 API把结果再塞回对话里模型才能基于结果生成最终回答。为什么要有这个东西因为模型的训练数据是静态的它不知道今天的天气、不知道你数据库里有什么、不知道当前股价。Function Calling 就是给它开了一扇窗让它能“伸手”去拿外部世界的信息。2.2 工具定义的几个关键细节定义工具的时候有几个地方特别容易出问题。第一个是描述。很多人写工具描述就写一句“获取天气”这太模糊了。模型需要知道这个工具什么时候用参数是什么意思有没有格式要求我一般会写得比较详细比如{ name: get_weather, description: 查询指定城市当前的天气状况包括温度、湿度、风力。适用于用户询问天气相关问题时调用。, parameters: { type: object, properties: { city: { type: string, description: 城市名称使用中文例如北京、上海、广州 } }, required: [city] } }描述写得越清楚模型调用得越准确。我实测下来描述从一句话扩展到三四句话工具调用的准确率能提升不少。第二个是参数类型。尽量用简单的类型string、number、boolean 这些。复杂的嵌套对象模型容易填错。如果确实需要复杂参数考虑拆成多个简单工具。第三个是工具数量。不要一次性给模型几十个工具它会懵。我一般控制在 5 到 10 个以内超过的话就做分组或者用路由的方式先选类别再选具体工具。2.3 工具调用结果怎么塞回去工具执行完之后结果要以特定格式追加到对话历史里。不同模型的格式略有差异但大体上是一条tool角色的消息带上tool_call_id对应之前的调用请求。这一步如果格式不对模型会忽略结果或者报错。我踩过的一个坑是工具返回的结果太长。比如你调了一个搜索工具返回了五千字的网页内容直接塞回去会占用大量 token而且模型可能抓不住重点。后来我的做法是在工具层面就做截断和摘要只返回最相关的部分。注意工具执行失败的时候不要把异常直接抛给模型。应该返回一个结构化的错误信息比如{error: 城市名称无法识别}让模型知道发生了什么它可能会换个参数重试或者告诉用户。3. Prompt 设计Agent 的“操作系统”3.1 System Prompt 决定了 Agent 的行为边界如果说 Agent Loop 是骨架Function Calling 是手脚那 System Prompt 就是大脑的操作系统。它决定了 Agent 的身份、行为规范、输出格式、边界条件。我见过很多 Agent 跑不稳最后排查下来都是 System Prompt 没写好。一个好的 System Prompt 应该包含这几个部分角色定义你是谁你擅长什么任务说明你要帮用户完成什么类型的事情工具使用规范什么时候该调工具什么时候直接回答输出格式要求回答的结构、语气、长度边界和禁忌什么不能做遇到不确定的情况怎么办我一般会写一个模板然后根据具体场景调整。比如一个客服 Agent 的 System Prompt 可能是这样你是一个电商平台的客服助手负责回答用户关于订单、退换货、物流的问题。 你可以使用以下工具 - query_order根据订单号查询订单状态 - query_logistics根据订单号查询物流信息 - create_return创建退货申请 规则 1. 用户询问订单相关问题时先调用 query_order 确认订单状态 2. 如果用户情绪激动先安抚再处理问题 3. 不确定的信息不要编造告诉用户你会转人工处理 4. 回答保持简洁不超过三句话这个 Prompt 里每一条规则都是有原因的。比如“先调用 query_order”是因为不确认订单状态就回答容易出错“不超过三句话”是因为客服场景用户不想看长篇大论。3.2 Prompt 里的常见坑第一个坑是指令冲突。比如你既说“回答要详细”又说“保持简洁”模型就不知道该听哪个。每一条指令都要检查有没有和别的指令矛盾。第二个坑是过度约束。有些人怕模型乱来写了几十条规则结果模型变得特别死板稍微超出预期的情况就不会处理了。规则要抓大放小核心行为约束住就行。第三个坑是缺少示例。对于输出格式要求高的场景光描述不够最好给一两个输入输出的例子。这叫 Few-shot Prompting能显著提升格式稳定性。还有一个热词里提到的 “invalid prompt” 问题通常是因为 Prompt 里包含了某些被判定为不合规的内容。这种情况一般发生在用户输入被直接拼接到 Prompt 里的场景。解决办法是在拼接之前做一层过滤和转义不要把原始用户输入直接塞进 System Prompt。3.3 Prompt Token 的优化Prompt Token 是成本的大头。System Prompt 越长每次调用的成本越高。优化思路有几个把不常用的规则移到工具描述里按需加载用更紧凑的表达去掉冗余的客套话对于多轮对话定期做历史摘要不要把全部历史都带上工具返回结果做截断我做过一个对比把一个 2000 token 的 System Prompt 优化到 800 token效果基本没降但成本降了一半多。4. Workflow 编排从单 Agent 到多步骤流水线4.1 什么时候需要 Workflow单 Agent 循环能解决很多问题但有些场景它搞不定。比如一个任务需要严格按照步骤来先查数据再分析再生成报告最后审核。这种有明确阶段划分的任务用 Workflow 编排会更稳。Workflow 的思路是把大任务拆成多个节点每个节点是一个独立的处理单元节点之间通过定义好的数据格式传递信息。这样做的好处是每个节点可以单独优化、单独测试出了问题也容易定位。举个实际例子我做过一个“竞品分析报告生成”的 Agent拆成了这几个节点信息收集节点调用搜索工具收集竞品的基本信息信息整理节点把收集到的信息结构化提取关键维度分析节点对比各竞品的优劣势报告生成节点按照模板生成最终报告审核节点检查报告是否有事实错误或遗漏每个节点用独立的 Prompt独立的工具集。这样比一个大循环塞所有逻辑要可靠得多。4.2 Workflow 编排的几种模式常见的编排模式有串行、并行、条件分支、循环这几种。串行最简单A 做完做 BB 做完做 C。适合有严格先后顺序的任务。并行是多个节点同时执行最后汇总。比如同时查三个数据源然后合并结果。并行能省时间但要注意结果合并的逻辑。条件分支是根据上一步的结果决定下一步走哪条路。比如审核不通过就回到生成节点重做。循环是某个节点重复执行直到满足条件。比如反复搜索直到找到足够的信息。实际项目里往往是几种模式的组合。我建议刚开始不要搞太复杂先用串行把流程跑通再逐步加入并行和分支。4.3 节点之间的数据传递节点之间传什么、怎么传是 Workflow 设计里最容易出问题的地方。我的经验是每个节点的输出格式要严格定义最好用 JSON Schema 约束。不要传自然语言因为自然语言有歧义下游节点解析起来容易出错。比如信息收集节点的输出应该是{ competitors: [ {name: 产品A, features: [功能1, 功能2], price: 99元}, {name: 产品B, features: [功能3], price: 129元} ] }而不是“我找到了两个竞品产品A有功能1和功能2价格99元……”这种。提示节点之间的数据格式一旦定下来就不要轻易改。改一次上下游都要跟着改很容易漏掉某个地方导致 bug。5. 从能跑到可靠工程化落地的关键点5.1 错误处理和重试Agent 跑起来之后你会遇到各种各样的错误模型返回格式不对、工具调用超时、参数填错、循环次数超限。这些都要有处理机制。我的做法是分三层工具层每个工具内部做超时控制和异常捕获返回结构化错误循环层设置最大循环次数超过就强制退出并返回当前结果节点层Workflow 的每个节点可以配置重试策略失败几次后走降级逻辑重试不是万能的。有些错误重试有用比如网络超时有些错误重试没用比如参数格式错误。要区分对待。5.2 可观测性Agent 跑在生产环境你必须知道它每一步在干什么。我一般会记录这些信息每次模型调用的输入 Prompt 和输出每次工具调用的参数和返回结果每个节点的开始时间、结束时间、耗时整个任务的 token 消耗这些数据一方面用于排查问题另一方面用于优化成本和效果。比如你发现某个节点的 token 消耗特别高就可以针对性优化。5.3 并发和性能热词里有人问“AI Agent 怎么扛并发”这确实是个实际问题。Agent 的每次循环都要调模型延迟本来就高并发上来之后更容易堵。几个优化方向异步调用模型调用和工具调用都用异步不要阻塞缓存对于相同的输入缓存模型输出或工具结果限流控制同时运行的 Agent 数量避免把下游服务打挂超时控制每个环节都要设超时不能让一个卡住的请求拖垮整个系统我实测下来用异步 缓存的方式同样的硬件资源能支撑的并发量能提升好几倍。5.4 测试和评估Agent 的测试比传统软件难因为输出不是确定的。我的做法是建立一套评估集准备一批典型的输入定义期望的输出特征每次改动后跑一遍看通过率。评估集不用很大几十条就够但要覆盖主要场景和边界情况。通过率下降就说明改动有问题需要排查。6. 常见问题速查问题可能原因排查方向模型不调用工具工具描述不清、Prompt 没说明何时用检查工具描述和 System Prompt工具参数填错参数描述模糊、类型复杂简化参数、补充示例循环不退出退出条件没定义好加最大循环次数限制输出格式不稳定Prompt 缺少格式约束加 Few-shot 示例响应太慢串行调用太多、没缓存改异步、加缓存Token 消耗过高Prompt 太长、历史没压缩优化 Prompt、做历史摘要7. 我踩过的几个坑第一个坑是把用户输入直接拼到 System Prompt 里。有次用户输入了一段很奇怪的内容导致模型行为完全跑偏。后来我改成用户输入永远放在 user 角色消息里System Prompt 保持干净。第二个坑是工具返回结果没做大小限制。有个搜索工具返回了几万字的网页内容直接把上下文撑爆了模型后面的回答全是乱的。后来我在工具层面加了截断只返回前 2000 字。第三个坑是没有设最大循环次数。有次模型陷入了一个死循环反复调用同一个工具跑了上百次才被我发现。后来我加了硬性限制超过 10 次循环就强制退出。第四个坑是Prompt 里的指令互相矛盾。我写了“回答要详细”又写了“控制在三句话以内”模型有时候详细有时候简短很不稳定。后来我把所有指令过了一遍确保没有冲突。这些坑说起来都很简单但没踩过就是想不到。希望看到这里的你能少走点弯路。8. 后续可以怎么扩展这套最小循环 Function Calling Workflow 的架构跑通之后可以往几个方向扩展。一个是多 Agent 协作。让不同的 Agent 负责不同的角色比如一个负责规划、一个负责执行、一个负责审核通过消息传递协作。这个模式适合复杂任务但调试起来也更麻烦。另一个是记忆系统。给 Agent 加上长期记忆让它能记住之前的交互在后续对话中复用。这个需要配合向量数据库来做。还有一个是自适应 Workflow。不是固定流程而是让模型根据任务情况动态决定走哪些节点。这个灵活度更高但可控性会下降需要权衡。我自己目前主要在用单 Agent 固定 Workflow 的组合稳定性和可控性都比较好。等这套跑顺了再考虑往更复杂的方向走。毕竟 Agent 这东西能稳定跑起来比看起来酷要重要得多。
返回列表