Skip to content

用于 ADK 的 Model Consult 工具

Supported in ADKPython v2.11.0

只使用单一模型的智能体面临一个权衡。快速、低成本的模型能让常规步骤更快、更节省资源,但在对复杂任务进行深入分析和决策时可能不够胜任。相比之下,更强的模型能很好地处理复杂决策,但会增加每个智能体步骤的响应时间和资源成本。

Model Consult 让智能体兼得两者之长。智能体运行在快速的执行器模型上,当遇到一个它无法自信解决的决策时,它会调用 Model Consult 工具,从更强的顾问模型那里获取指导。随后智能体自行继续执行任务,使用它自己的工具。智能体只在需要的步骤上使用更强的模型,而且如果咨询失败或咨询预算已用尽,智能体会用已有的信息继续工作。

使用场景

  • 成本优化:在低成本模型上运行智能体的常规编排和工具循环,只在需要的步骤上让智能体咨询更强的模型。
  • 策略协调:让智能体把复杂的多条款策略决策升级给前沿模型,然后用自己的工具执行所得到的指导。
  • 循环救援:当智能体反复发出相同的工具调用时,让它咨询更强的模型,从而帮助智能体跳出重复循环。

前置条件

  • ADK Python v2.11.0 或更高版本。
  • 可以访问两个模型:一个低成本的执行器模型和一个更强的顾问模型,例如托管在 Google Cloud 上的 Gemini Flash 和 Gemini Pro。
  • 为 ADK 配置好模型凭据:要么是一个启用了 Vertex AI API 的 Google Cloud 项目,要么是一个 Gemini API key。

安装

Model Consult 是直接包含在 ADK Python 包中的原生工具。

pip install "google-adk>=2.11.0"

在智能体中使用

把 ModelConsultTool 附加到 Agent 上,与你的领域工具并列,例如下面示例中的 lookup_order 函数。该工具会注册 model_consult 函数声明,并向执行器的系统指令追加一个默认的升级策略,从而给智能体明确的规则,说明何时以及如何咨询顾问。

from google.adk.agents import Agent
from google.adk.tools import ModelConsultTool

def lookup_order(order_id: str) -> dict[str, str]:
    """按标识符查询订单状态。"""
    return {"order_id": order_id, "status": "held_for_fraud_review"}

root_agent = Agent(
    model="gemini-flash-latest",
    name="support_executor",
    instruction=(
        "你是一个订单支持助手。请使用你的工具解决客户问题。"
    ),
    tools=[
        lookup_order,
        ModelConsultTool(
            model="gemini-pro-latest",  # 顾问模型
            max_uses=2,
            session_max_uses=5,
            thinking_level="high",
        ),
    ],
)

在这个示例中:

  • support_executor 智能体运行在快速模型(gemini-flash-latest)上,并尝试使用其 lookup_order 工具解决用户的问题。
  • 执行器模型决定何时调用 model_consult。在默认设置中,执行器被指示在确定一个决定之前、在卡住时,以及在宣布任务完成之前调用 model_consult。
  • ModelConsultTool 拦截该调用,校验 max_uses 预算,并把当前会话事件与 lookup_order 工具的描述打包成一次完整的顾问咨询。
  • 顾问模型评估上下文并返回结构化的文本指导,让 support_executor 重新获得控制权,执行任何推荐的工具,并结束本轮交互。

可用工具

工具 说明
model_consult 将会话历史和一个具体问题升级给更强的顾问模型,以获得结构化的指导。

工作原理

当执行器调用 model_consult 时,ModelConsultTool 会执行四个步骤,并向执行器返回一个结构化字典:

  1. 预算校验 — ModelConsultTool 会将本轮计数器与 max_uses 对比、将会话总计数器与 session_max_uses 对比。如果任一上限已达到,该工具会立即返回 "status": "limit_reached",不再调用顾问模型,并指示执行器使用已收集到的信息继续处理。
  2. 上下文移交 — ModelConsultTool 把这次咨询打包成一条 role='user' 的 types.Content 消息。当 include_agent_instruction 和 include_tool_inventory 为 True 时,消息开头是解析后的执行器指令和同级工具清单。接着,ModelConsultTool 会按照 ModelConsultContextConfig 转换 Session.events 中非 partial、非 rewound 的事件,按说话者给文本部分打标签,并把之前的工具调用和工具响应压平成可读的文本摘要,同时排除任何进行中的 model_consult 调用。最后,ModelConsultTool 追加一个移交部分,其中包含当前活跃的智能体名称、执行器的问题,以及执行器传入的任何额外 context 字符串。
  3. 无工具的顾问调用 — ModelConsultTool 会以禁用工具调用的方式调用所配置的顾问 BaseLlm,并使用默认的顾问系统指令,或在提供了 advisor_instruction 时使用自定义指令。由于顾问请求中排除了工具声明,顾问无法自行执行工具或产生副作用;它只能返回文本指导,说明执行器接下来应该调用哪些工具以及使用什么参数。
  4. 结构化的工具响应 — ModelConsultTool 永远不会把异常抛回智能体循环。取而代之的是,它返回一个带有 status 值的字典,详见响应状态值。

检查工具调用

默认情况下,人类可读模式的 adk run 只打印最终的文本回复([support_executor]: ...),并隐藏中间的工具调用。你可以通过三种方式检查 model_consult 调用并核对顾问的回答:

  1. ADK Web UI — 在 adk-python 的克隆仓库中运行 adk web contributing/samples/tools: 在聊天面板中,每次咨询都会显示为一个 model_consult 工具事件。点击 model_consult 事件,即可在左侧打开 Events / Trace 检查器:
  2. functionCall 显示执行器发送给顾问的确切 question(以及可选的 context)。
  3. functionResponse 显示 ModelConsultTool 返回的结构化字典,包括 "status"、"guidance"、"advisor_model"、"thinking_level"、"consults"、"usage" 和 "latency_ms"。

  4. ADK CLI: 使用 adk run 命令,可以将每个会话事件(包括 model_consult 的 functionCall 和 functionResponse)以 JSON 形式输出。选择你的模式:

  5. 单次查询模式: 传入 --jsonl,将事件以 JSON 行形式流式输出到 stdout:
    adk run contributing/samples/tools/model_consult \
      "Customer CUST-108 wants a full refund to their original payment method for order ORD-502." \
      --jsonl
    
  6. 交互模式: 传入 --save_session,在退出时保存完整的会话日志:

    adk run contributing/samples/tools/model_consult --save_session --session_id consult_demo
    

  7. 通过 Runner.run_async 事件以编程方式检查: 在 Python 中运行智能体时,检查 event.get_function_calls() 和 event.get_function_responses() 中 name == "model_consult" 的项:

async for event in runner.run_async(user_id="u1", session_id="s1", new_message=msg):
    for resp in event.get_function_responses():
        if resp.name == "model_consult":
            print(resp.response["status"], resp.response.get("guidance"))
            print("Consult budget:", resp.response.get("consults"))
            print("Advisor token usage:", resp.response.get("usage"))

响应状态值

model_consult 返回的字典中,status 字段取以下值之一:

状态 返回时机 字段 咨询预算
ok 顾问返回了指导。 guidance, advisor_model, thinking_level, consults, usage, latency_ms 递增本轮计数器和会话计数器。
limit_reached max_uses 或 session_max_uses 已耗尽。不会调用顾问模型。 message, consults 不消耗。
error 顾问调用超时、失败,或没有产生可见文本。 error, message, advisor_model, consults 不消耗。
invalid_request question 为空或只包含空白字符。 message 不消耗。

一次成功的咨询会返回下面的字典结构。其中显示的 token 计数和延迟仅为示意,并非真实测量值:

{
    "status": "ok",
    "guidance": "1. 使用 order_id='ORD-42' 调用 lookup_order。",
    "advisor_model": "gemini-3.1-pro-preview",
    "thinking_level": "high",
    "consults": {
        "used_this_turn": 1,
        "max_uses": 2,
        "used_this_session": 1,
        "session_max_uses": 5,
        "remaining": 1
    },
    "usage": {
        "prompt_tokens": 612,
        "output_tokens": 184,
        "thoughts_tokens": 320,
        "total_tokens": 1116
    },
    "latency_ms": 842.5
}

最佳实践

Model Consult 无需额外配置即可工作。使用以下做法来改善效果:

  • 在执行器模型上启用思考。
  • 保留默认的升级策略,或在执行器提示词中为你的用例引导升级策略。

在执行器上启用思考

由执行器决定何时调用 model_consult,因此当它能够进行推理时会做出更好的决策。在执行器模型上启用思考。例如,使用一个支持动态思考的轻量模型。

自定义执行器何时咨询顾问

一个 ModelConsultTool 对象会向执行器的系统指令添加升级策略。默认情况下,该策略要求执行器在做出决定之前、在陷入困境时,以及在宣布任务完成之前调用 model_consult。这些覆盖了下表中的规划、诊断和复盘触发条件。

要替换默认策略,请在 executor_instruction 中传入你自己的文本。要移除该策略,请传入空字符串("")。

ModelConsultTool(
    executor_instruction=(
        "在你的第一次回复之前调用 model_consult,并且每当工具调用"
        "因你无法解释的原因失败时也调用。"
    ),
)

常见的咨询触发条件

下表列出了咨询顾问的常见原因,以及你可以添加到 executor_instruction 中的触发条件。

原因 为何有帮助 触发条件示例
规划 任务早期的错误解读或方法会影响之后的每一步,浪费时间和 token。 - 在第一次回复之前。
- 在执行器收集完事实、开始主要工作之前。
- 当请求提出一个方案时,询问如何验证它。
- 当存在多种可能的方法或解读、且没有证据倾向其中之一时。
- 对于你知道比较困难的请求类型。
诊断 失败或矛盾意味着执行器的某个假设是错误的。 - 工具调用失败或返回了意外结果,而执行器无法解释原因。
- 执行器在没有新信息的情况下重复相同的工具调用或其近似变体。
- 执行器推翻了自己的工作。
- 两个来源或工具结果不一致。
- 执行器得出请求本身是错误的结论。
复盘 对照需求检查结果,可以在用户发现问题之前找出错误和遗漏。 - 在给出最终答案之前。
- 在执行器完成复杂任务中相当一部分工作之后。

配置选项

ModelConsultTool 对象负责配置顾问模型选择、咨询预算和提示词覆盖,而 ModelConsultContextConfig 控制会话事件在移交前如何被格式化和限制。

ModelConsultTool 选项

ModelConsultTool 类接受以下构造函数参数:

选项 类型 默认值 说明
model str | BaseLlm 'gemini-3.1-pro-preview' 通过 ADK 模型注册表解析的顾问模型名称,或一个预配置的 BaseLlm 实例。默认是一个预览模型,可能会发生变化。
max_uses int None 每个用户轮次中成功咨询的最大次数。None 表示没有每轮上限。
session_max_uses int None 整个会话中成功咨询的最大次数。None 表示没有会话级上限。
thinking_level str | types.ThinkingLevel 'high' 顾问模型的推理力度:'minimal'、'low'、'medium'、'high'、一个 types.ThinkingLevel 枚举值,或 'off'、'none'、None(表示不设置思考)。
max_output_tokens int None 顾问输出 token 的可选上限,涵盖推理模型上可见输出和思考 token。
timeout_seconds float None 每次调用的挂钟超时时间(秒)。None 表示没有工具级超时。
context_config ModelConsultContextConfig None 控制会话历史如何被打包并限定后提供给顾问。
executor_instruction str None 覆盖自动追加到执行器 system_instruction 的默认升级策略。传入 "" 可禁用自动注入。
advisor_instruction str None 覆盖发送给顾问模型的默认系统指令。
description str None 覆盖展示给执行器模型的默认工具说明。
include_agent_instruction bool True 将执行器智能体自身的指令转发给顾问,使指导遵循执行器的约束。
include_tool_inventory bool True 在顾问咨询提示词中包含执行器其他工具的名称和说明。
generate_content_config types.GenerateContentConfig None 每次顾问调用时克隆的基础生成配置,例如 temperature 或 safety_settings。
name str 'model_consult' 暴露给执行器模型的工具名称。

ModelConsultContextConfig 选项

ModelConsultContextConfig 控制 Session.events 如何被转换为顾问的输入内容:

选项 类型 默认值 说明
include_session bool True 为 True 时发送转换后的 Session.events 历史;为 False 时省略之前的会话事件。
max_events int None 在进行字符预算裁剪之前,最多保留这么多最近的非 partial 会话事件。None 表示保留所有事件。
max_chars int 200000 所有移交的会话轮次的字符预算。None 表示禁用字符预算。
max_part_chars int 4000 渲染后的工具调用、工具结果和代码块的单部分字符上限,纯文本部分允许该上限的八倍。
include_media bool True 为 True 时将内联媒体和文件引用转发给顾问模型;为 False 时用文本占位符替换它们。如果不想将会话媒体发送给顾问模型,请设置为 False。
include_thoughts bool False 为 True 时在顾问移交内容中包含执行器的内部思考部分。

其他资源