构建具备错误恢复能力的多工具Gemma 4智能体
本文展示了如何将一个基础的工具调用脚本转变为一个能够优雅处理工具失败、模型输出错误和服务不可用等问题的弹性智能体。涵盖了迭代式智能体循环、四种不同的错误恢复模式以及如何设计信息丰富的错误消息以帮助模型自我纠正。
在之前的教程中,我们使用Ollama的工具调用API将Gemma 4与几个Python函数连接起来,实现了一个单轮调度器:模型选择工具,代码执行工具,模型给出答案。这是一个有用的起点,但距离真正的智能体还差得很远。
将工具调用演示转变为真正的智能体的关键之一,在于如何处理出错的情况。工具会失败,模型可能幻觉出错误的函数名,或者传入字符串而期望数字,或者询问查找表中不存在的城市。上游API可能超时,必需参数可能缺失。在之前的教程中,这些情况要么导致脚本崩溃,要么被try/except捕获后打印一条消息就放弃。这对于单路径演示没问题,但对于任何希望长期运行的程序来说远远不够。
本文重新构建了智能体,假设一切都会出错,并展示了如何优雅地恢复。模式很简单:在边界捕获错误,将其转换为模型可读的消息,发送回模型,让模型决定是重试、绕开问题还是向用户解释失败。我们还将所有内容包装在带有迭代次数上限的迭代式智能体循环中。
重新思考工具循环
原来的调度器运行单轮:发送用户查询,收集工具调用,执行它们,发送结果,打印模型回复。这是一种一次性交互。当模型的第一响应正确回答用户问题时没问题,但一旦出错就没有退路。如果工具失败,模型只有一次机会反应,然后结束。如果模型在查看第一个结果后想调用另一个工具,已经太晚了。
真正的智能体循环是迭代的。结构很简单:将当前消息历史发送给模型;如果模型产生工具调用,执行每一个,将所有结果追加到历史中,然后再次循环;如果模型产生纯文本响应,那就是最终答案,返回。循环设置MAX_ITERATIONS上限,防止困惑的模型无限调用工具。
构建工具注册表
我们构建了四个确定性、离线的工具:获取天气、获取当地时间、转换货币、获取城市人口。它们使用硬编码数据,没有网络调用,以便专注于错误处理架构。每个工具在无效输入时抛出异常,而不是返回错误字符串。例如,get_weather在未知城市时抛出ValueError,并列出已知城市。这样调度器可以统一处理所有失败,并将信息丰富的错误消息传递给模型。
四种错误恢复模式
- 工具执行错误:调度器将每个工具调用包裹在try/except中,捕获TypeError、ValueError、ToolUnavailableError和通用的Exception,并将错误作为工具结果返回给模型,而不是抛出异常。模型可以读取错误并决定下一步。
- 模型产生的格式错误的工具调用:在调用前验证工具名称是否在注册表中,如果不在,返回纠正消息列出有效名称。对于参数错误,类似处理。
- 信息缺失:当工具返回“未知城市”时,模型可以主动询问用户是否提供了正确的城市名。
- 上游服务故障:通过
SIMULATE_GEOCODING_OUTAGE标志模拟地理编码服务故障,展示如何优雅降级,例如返回缓存数据或向用户解释。
本文的核心观点是:不要害怕错误,而是设计系统让错误成为模型学习和恢复的机会。通过将错误反馈到消息历史中,模型可以在下一轮迭代中做出明智的决策。