Gemini 工具组合怎么排

2026-11-06 17:39 更新

Gemini 3 可以在同一请求里组合内置工具与函数调用,内置工具的上下文靠 previous_interaction_id 传递;互不依赖的调用可并行,有依赖的必须串行。(核验 2026-11-05,F83)

一、Gemini 工具组合怎么排:先分层,问题在谁等谁

「既然一个工具不够用,那就多开几个」——这句话听上去合理,落到代码里常常变成一串顺序调用:查航班、订票、发确认邮件,一步接一步。快的时候没问题,一旦某一步返回空,后面两步就全在拿空值往下滚。

组合的真实难点不是「开几个」,而是依赖关系:哪些调用互不相干、可以一起发;哪些必须等前一个的结果。排错了,轻则慢,重则错。

官方对这件事的表述很克制但很明确:Gemini 3 模型可以在 Interactions 里直接把内置工具与函数调用组合在同一个请求中,而且传 previous_interaction_id 会自动传递内置工具的上下文(F83)。同一页也说明了两种多调用形态——独立的并行、有依赖的链式。

这两句话对应两个工程决定:同一层的调用能不能并发,以及跨轮的内置工具上下文要不要显式带上。

二、Gemini 工具组合排序:最小可运行示例

把任务写成「谁依赖谁」,剩下的排序交给拓扑分层,比手写顺序靠谱。

## EXPECT: 有依赖 3 层,同层可并行 0 组 | 独立 1 层,可并行 2 个
DEPENDENT = {
    "search_flights": [],
    "book_flight": ["search_flights"],
    "send_email": ["book_flight"],
}
INDEPENDENT = {
    "get_weather": [],
    "get_flight_status": [],
}

def layers(tasks):
    known = set(tasks)
    unknown = {dep for deps in tasks.values() for dep in deps} - known
    assert not unknown, f"依赖了不存在的任务:{sorted(unknown)}"
    remaining = dict(tasks)
    done, order = set(), []
    while remaining:
        ready = sorted(k for k, dep in remaining.items() if set(dep) <= done)
        assert ready, "存在循环依赖,先修任务图"
        order.append(ready)
        done.update(ready)
        for k in ready:
            remaining.pop(k)
    return order

dep_layers = layers(DEPENDENT)
ind_layers = layers(INDEPENDENT)
parallel_dep = sum(1 for layer in dep_layers if len(layer) > 1)
assert len(dep_layers) == 3 and dep_layers[0] == ["search_flights"]
assert len(ind_layers) == 1 and len(ind_layers[0]) == 2
print(f"有依赖 {len(dep_layers)} 层,同层可并行 {parallel_dep} 组 | "
      f"独立 {len(ind_layers)} 层,可并行 {len(ind_layers[0])} 个")

layers() 返回的是执行批次,不是执行顺序:同一层里的任务互不依赖,可以一次性发出;下一层必须等上一层全部返回。DEPENDENT 排出来是三层、每层一个,INDEPENDENT 只有一层、两个任务——这就是「并行还是串行」的答案,靠的不是猜,是任务图。

三、解释与边界:组合的三个决定

决定一,分层决定并发。 同一层的调用可以一起发,前提是你确认它们之间真的没有数据依赖。写任务图时最容易犯的错是「看起来没关系」——查航班和查天气确实独立,但「订票」和「发确认邮件」之间有隐性依赖(邮件里要带票号),漏写这条箭头,邮件就会在订票完成前发出。

决定二,内置工具与函数调用同请求时,上下文要显式续上。 官方说明 Gemini 3 支持在同一次交互里组合两类工具,且传 previous_interaction_id 会自动传递内置工具上下文(F83)。反过来说,如果不传这个 id,下一轮模型看到的是「没有上下文的新请求」,它会重新搜一遍——多花一次搜索的钱,还可能拿到不同的结果。

决定三,工具数量是一个预算。 官方建议同时激活的工具控制在 10 到 20 个以内(F87)。组合越多,模型选错的概率越高,声明编译成的状态机也越大(见 6.4 的复杂度上限)。所以「组合」的正确姿势是先拆任务再选工具,而不是把所有工具都挂上去让模型自己挑。

一个容易踩的坑,来自前置文本。 有些提示词要求模型在调工具前先输出一段结构化文本(XML、YAML、JSON 之类)作为思考记录。官方指出这种写法可能让工具调用偶发 Malformed_Function_Call,并给了三种绕法:改用专用 update() 函数承载这些笔记(首选)、改用 Markdown 标题、或者干脆不要求前置文本(F88)。组合了多个工具时这个问题更明显,因为每轮都要「先说一句再动手」。

什么时候该把一次组合拆成两个请求。 不是所有依赖都适合塞进同一条交互。遇到这三种情况,拆开更划算:一是工具集超过 10 到 20 个的建议上限(F87),模型的选择准确率会掉,此时按业务子域拆成两条链路,各自带一小撮工具;二是上下文已经很长,再多轮工具往返会把历史撑爆(预算见 9.3);三是两个阶段的操作权限不同——查询和写操作混在一次交互里,白名单没法按阶段收窄(见 6.3)。拆分的代价是你得自己维护两次调用之间的状态,好处是每一步都更容易审计、重试与灰度。

边界。 本节只排「谁等谁」。白名单与模式选择见 6.3;参数级校验见 6.4;检索类内置工具的分工(搜索、文件检索、URL 上下文)见第 7 章。本节也不讨论怎么让模型更愿意用某个工具——那是声明描述的质量问题。

四、预期输出与异常分支

真跑输出:

有依赖 3 层,同层可并行 0 组 | 独立 1 层,可并行 2 个

七类分支。同层并发打爆外部接口:两个调用一起去请求同一个第三方,限流一起触发;并发前先看对方配额。漏写隐性依赖:邮件带不上票号,因为它在订票完成前就发了,任务图要补箭头。不传 previous_interaction_id:内置工具上下文断了,模型重搜一遍,结果可能不一致。组合后 schema 超限:工具声明会一起编译成状态机,组合越多越容易撞上 400 INVALID_ARGUMENT,简化口径见 6.4。前置文本触发解析失败:偶发 Malformed_Function_Call,按 F88 的三种绕法改,别先去怀疑模型。循环依赖:任务图里 A 等 B、B 等 A,layers() 会断言失败——这是好事,让它在发请求之前就炸。组合后成本翻倍:检索类内置工具按次计费,组合里每多一轮搜索就多一笔(费用口径见 7.3);上线前拿一条典型请求跑一遍,看账单再决定要不要摘掉某个工具。

五、判据卡:什么时候别组合

该这么做 不该这么做
先画任务依赖图,再决定并发 凭感觉排一串顺序调用
同层并发前确认外部配额 默认「一起发更快」
跨轮传 previous_interaction_id 续上下文 每轮都重新搜一遍
活跃工具控制在 10 到 20 个以内 把全部工具挂上去让模型挑

六、来源与核验

  • https://aistudio.google.com/docs/function-calling.md(核验 2026-11-05,F83、F87、F88)
  • https://aistudio.google.com/docs/api-errors.md(核验 2026-11-05,F27)

组合方式、上下文传递与工具数量建议属于「API 结构」档事实,复核周期三个月,见 1.3。若官方调整多工具的同请求能力或 previous_interaction_id 的语义,本节的分层示例要按新原文重排。

七、动手试

  1. 在 DEPENDENT 里加一条 "notify_manager": ["book_flight"],重跑。预期仍是三层,但第二层变成两个任务、同层可并行 变成 1 组;验收标准是你能说清「它和 send_email 为什么能并发」。
  2. 把 INDEPENDENT 改成一个有依赖的链条(get_weather 依赖 get_flight_status),重跑。预期层数变成两层、可并行变成 1 个;验收标准是给出「依赖从哪来」的业务理由。
  3. 打开你项目里的工具调用代码,把它的执行顺序画成任务图。验收标准:能指出哪些调用其实可以并发、哪些箭头是漏写的;画不出来,说明顺序是靠代码行数决定的。
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号