从测试视角理解 Function Calling:模型到底什么时候会调用工具?
很多 Function Calling 的示例,看起来都很顺:
用户问天气 → 模型调用函数 → 返回结果
但在真实系统里,最重要的其实不是“能不能调用工具”,而是:
👉 模型什么时候会拒绝调用?什么时候会纠错?什么时候会追问?
我用一个最小天气查询 Demo,从测试视角系统性跑了一组输入,把模型的真实行为拆了一遍。
一、最小 Demo:一个 get_weather 工具
工具定义比较简单,只要求一个必填参数 city:
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取当前城市天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名词,例如:深圳,上海等"
}
},
"required": ["city"]
}
}
}
]
调用方式使用:
# 调用大模型
response = client.chat.completions.create(
model="glm-4.5",
messages=messages,
tools=tools,
tool_choice="auto" # 自动选择是否调用函数
)
也就是说:是否调用工具,完全交给模型自己判断。
打印响应:
# 拿到模型真正返回的内容
answer = response.choices[0].message
print(answer)
print("tool_calls:", answer.tool_calls)
print("arguments:", answer.tool_calls[0].function.arguments)
二、基础场景:信息充分时,模型会稳定调用工具
输入:
深圳天气怎么样?
输出关键点:
-
tool_calls存在 -
函数名:
get_weather -
参数:
{"city": "深圳"}
测试结论:
-
在信息明确、参数完整的情况下,模型会优先返回 结构化的 tool_calls
-
content基本为空,自然语言回答会延后到“工具执行结果回填”之后
👉 这也是很多人第一次用 Function Calling 时误以为“模型没回答”的原因。
三、多任务场景:一次响应中生成多个 tool_calls
输入:
深圳和广州的天气对比一下
输出:
同一次响应中,生成 两个 tool_calls
-
index=0 → 深圳
-
index=1 → 广州

测试结论(非常重要)
-
模型具备 拆分任务 → 多次调用同一工具 的能力
-
如果代码里只处理
tool_calls[0],就会出现严重逻辑缺陷(只查一个城市就开始对比)
👉 正确做法:必须遍历 tool_calls 执行。
四、跨语言输入:模型会做实体归一,而不是原样透传
输入:weather in Shenzhen
输出:
-
reasoning 是英文
-
但最终参数被归一为:
-
{"city": "深圳"}
测试结论
-
模型在 Function Calling 前,存在一层 跨语言实体归一
-
这会直接影响后端工具的入参兼容性设计(只收中文?还是中英文都行?)
五、错别字场景:先纠错,再调用工具
输入:深证天气怎么样?
输出:
-
模型明确判断“深证”是“深圳”的错别字
-
tool_calls 中参数被修正为:
{"city": "深圳"}
测试结论
Function Calling 并不是简单的字符串提取,
而是发生在 语义理解和实体纠错之后。
六、无效实体:模型会主动放弃工具调用
输入:阿瓦达啃大瓜天气怎么样?
输出:
-
判断该词不是有效城市
-
没有触发 tool_calls
-
转为自然语言追问用户
测试结论(关键)
-
当模型判断参数 语义无效 时,会拒绝调用工具
-
能有效避免“参数幻觉”导致的错误调用
七、缺参场景:required 字段会触发追问,而不是调用
输入:天气怎么样?
输出:
-
识别出缺少
city -
未触发 tool_calls
-
主动询问用户具体城市
测试结论
-
tool schema 中的
required字段,会真实影响模型决策 -
不是摆设
八、行为总结表(测试视角)

九、测试视角下的 3 个核心结论
-
Function Calling 的前提不是“匹配到工具”,而是语义可执行
-
schema 的 required 字段,会改变模型的交互策略
-
真正难测的不是“会不会调用”,而是“什么时候不该调用”
结语
Function Calling 本质上是一个
“语义判断 → 参数构造 → 工具执行” 的决策链。
如果只验证“工具有没有被调用”,其实只测到了最表层。
站在测试视角,更有价值的是:
👉 模型在哪些边界条件下,选择了不调用。
更多推荐


所有评论(0)