上一篇文章说,Agent 是让模型在“判断下一步”和“执行一步”之间循环。
这篇把这个循环岔开看看,还是用天气提醒这个场景。
用户说:“查一下天津今天的天气,如果下雨,提醒我带伞。”
普通大预言模型接收到这个信息它会怎么处理?
它可能回你一段:“我会搜索天气网今日天津天气,你也可以打开天气应用查询天津今天天气,如果显示有雨,记得带伞。”
提醒也没建。模型生成了一段回答,任务并没有往前推进。
Agent 要做的不是生成这段回答,而是把这个任务拆成几轮,一轮一轮往前推。
第一轮:模型会先判断该不该调工具
用户内容输入进来之后,系统不是直接把整段话扔给模型让它“完成这个任务”。
更准确地说,系统把用户输入、当前上下文、以及可用工具的描述一起交给大模型,让模型判断下一步。
大模型看到的是:用户要查天津今天的天气,如果下雨要提醒。
可用工具有两个,一个查天气,一个建提醒。
模型主观上判断:现在还不知道天气,得先查。
于是大模型返回一个工具调用请求,大意是“调用天气查询工具,城市天津,日期今天”。
注意,这个时候天气还没执行查询操作。模型只是提出了一个请求。
程序执行,把结果拿回来
模型发出请求之后,真正干活的是程序。
程序拿到请求,先确认这个查询天气工具存在、参数合法、当前用户有权限调用,然后才去调实际的天气服务。
天气服务返回:“天津今天下午有雨,建议带伞。”
程序把这个结果整理好,连同之前的上下文,一起交回给模型。
这一轮才算走完。
划分下边界:模型负责“提出请求”,程序负责“执行请求”。模型说“我想查天气”,不等于天气已经查了。真正查没查、查到了什么,由程序决定并返回。
这个分工是后面讲 Tool Calling 的基础,这里先记住“请求和执行是两件事”就够了。
第二轮:模型拿着结果再判断
现在大模型拿到了天气结果:下午有雨。
它根据拿到的结果重新判断:用户的任务是“如果下雨,提醒带伞”。
现在下雨了,条件成立,需要建提醒。
于是它发出第二个工具调用请求:调用提醒工具(第三轮),内容“带伞”,时间大概是今天出门前。
程序再次执行:检查参数、写入提醒、返回“创建成功”。
结果再交回模型。
模型这时候判断:天气查了,提醒也建了,用户的需求都覆盖了,可以结束了。
于是它生成最终回答:“天津今天下午有雨,已帮你创建带伞提醒。”
到这一步,任务才算完成。
整个过程运行了两轮工具调用。
循环什么时候停
这个调用工具循环什么时候停止,肯定不能一直转。
实际系统中必须设停止条件,不然模型可能反复调同一个工具,或者在一个查不到结果的任务上死循环。
常见的停止条件有三类。
- 任务完成,模型自己判断不需要再调工具了,生成最终回答
- 达到最大轮数,比如设了 5 轮,到第 5 轮还没结束就强制停,把当前结果返回给用户
- 遇到不可恢复的错误,比如工具连续失败、参数怎么都校验不过,程序主动终止,如实告诉用户哪一步没做成。
这里暂时不展开超时、重试、异常处理这些工程细节,后面的文章会详细讲。
现在只需要知道:循环必须有出口,不能靠模型“自觉”。
这个循环,是 Agent 和单次调用的分水岭
单次模型调用是一条直线:输入进去,回答出来,结束。
Agent 是一个带反馈的循环:模型判断,程序执行,结果回填,模型再判断,直到停。
差别不在模型多聪明,在于每一轮执行结果都会变成下一轮判断的依据。
第一轮模型不知道天气,第二轮它知道了;
第二轮它不知道提醒建没建成,第三轮它知道了。
信息是一轮一轮补充进来的,不是一开始就有的。
这也解释了为什么 Agent不适合所有任务。
如果任务一步就能完成,或者步骤完全固定、不需要根据中间结果调整,那这个循环就是多余的。
循环的价值在于“根据执行结果决定下一步”,任务如果没有这种不确定性,那就不需要 Agent 。
循环里还有几件事没展开
这个最小流程只讲了主干:模型判断、程序执行、结果回填、再判断、停止。但真要做成一个能跑的东西,还有几件事得处理。
工具到底怎么定义、参数怎么传、模型返回的调用请求长什么样、程序怎么解析和执行,这些是 Tool Calling 要解决的问题。模型判断该调工具,但它怎么知道有哪些工具可用、每个工具收什么参数,这背后有一套机制。
循环里每一轮都要把历史信息带上,不然模型聊到第三轮就忘了第一轮查过什么。
上下文怎么组织、多轮之后怎么不爆 token,这是记忆管理要处理的。
还有,这个循环放在固定流程里怎么嵌、什么时候该用循环什么时候该用固定步骤,那是 Workflow 和 Agent 如何选型的问题。
这篇只讲了一件事:Agent 的运行是一个“判断—执行—回填—再判断”的循环,循环必须有停止条件,循环的价值来自根据执行结果调整下一步。
后面几篇,分别拆这个循环里的各个零件。
本文由 楸木 原创,转载请注明出处。
评论
0发表评论
登录 后发表评论