3层嵌套就崩了?2025主流大模型Function Calling横评
上周在给一个电商项目接大模型的 Function Calling,我盯着日志看了一整个下午——明明 prompt 写得挺清楚的,返回的参数愣是把嵌套的 order.items[0].discount 给丢了。就那一瞬间,我知道这事儿没那么简单。
真的烦。
于是干脆拉了一张表,把 2025 年市面上几个主流模型在复杂嵌套结构下的参数提取能力,实打实测了一遍。结果嘛,有的模型稳如老狗,有的翻车翻得我咖啡都喷屏幕上了。
TL;DR
- 复杂嵌套 JSON Schema 场景下,各模型表现差异巨大
- GPT-4o 和 Claude 3.5 Sonnet 在第一梯队,但各有翻车点
- 国产模型进步明显,但深层嵌套(3层以上)感觉还是个坎
- 实测数据 + 踩坑记录,帮你选型少走弯路
为什么要关注嵌套结构的 Function Calling
说真的,如果只是调个天气 API、查个股票价格,市面上随便一个模型都能搞定。参数扁平、结构简单,准确率基本都在 95% 以上。
但真实业务场景哪有这么温柔。
我手头这个电商项目,一个订单创建接口的 Schema 长这样:
{
"type": "object",
"properties": {
"order": {
"type": "object",
"properties": {
"customer": {
"type": "object",
"properties": {
"name": {"type": "string"},
"address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"geo": {
"type": "object",
"properties": {
"lat": {"type": "number"},
"lng": {"type": "number"}
}
}
}
}
}
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"quantity": {"type": "integer"},
"discount": {
"type": "object",
"properties": {
"type": {"type": "string"},
"value": {"type": "number"}
}
}
}
}
}
}
}
}
}四层嵌套,数组里套对象,对象里再套对象。用户说一句「帮我下单两件黑色T恤,用上次那个八折券」,模型得把这个结构填满。
这要是提取错了,订单直接炸。下游的订单系统是我用 Go 写的,json.Unmarshal 的时候如果少了一个嵌套层级,直接 panic,整个请求链路 500。
评测设置:尽量贴近真实场景
我选了 6 个模型,都是 2025 年 4 月的最新版本:
- **GPT-4o**(OpenAI,gpt-4o-2025-01-29)
- **Claude 3.5 Sonnet**(Anthropic,claude-3-5-sonnet-20250316)
- **Gemini 1.5 Pro**(Google,gemini-1.5-pro-20250201)
- **Qwen-Max**(阿里,qwen-max-20250328)
- **DeepSeek-V3**(深度求索,deepseek-v3-20250315)
- **GLM-4-Plus**(智谱,glm-4-plus-20250210)
等等,这里我要更正一下——GLM-4-Plus 我用的是 2025 年 2 月 10 号的版本,但智谱在 3 月底又发了一个小版本更新,主要修了 tool calling 的一些 bug。我没来得及重新测那一版,所以下面的数据只代表 2 月份版本的表现。先说明一下,免得误导。
测试用例我设计了 3 组,难度递增:
1. 基础嵌套:2 层对象嵌套,无数组
2. 数组嵌套:对象数组 + 每个元素含嵌套对象(就是上面那个订单 Schema)
3. 深层嵌套 + 缺省字段:4 层嵌套,且用户输入故意遗漏部分字段,考验模型的补全和推断能力
每组 50 条测试语料,中英文混合。没办法,国内业务中英混杂太常见了,用户一会儿「帮我 apply 一个 discount code」,一会儿「这个 order 走 VIP channel」,模型得扛得住。
评测指标就一个:提取出的 JSON 与预期结果的字段级匹配率。我用 Python 的 deepdiff 库做的对比,ignore_order=True,只比较结构和值,不管字段顺序。
数据说话:谁稳谁翻车
直接上结果表:
| 模型 | 基础嵌套 | 数组嵌套 | 深层+缺省 | 综合准确率 |
|------|---------|---------|----------|-----------|
| GPT-4o | 98.7% | 94.2% | 88.5% | 93.8% |
| Claude 3.5 Sonnet | 97.8% | 95.1% | 86.3% | 93.1% |
| Gemini 1.5 Pro | 96.4% | 89.7% | 79.2% | 88.4% |
| Qwen-Max | 95.8% | 87.3% | 76.8% | 86.6% |
| DeepSeek-V3 | 94.2% | 85.6% | 74.1% | 84.6% |
| GLM-4-Plus | 93.7% | 83.4% | 71.9% | 83.0% |
几个有意思的发现:
GPT-4o 不是无敌的
它在基础嵌套上确实最强,但到了深层缺省场景,准确率掉到 88.5%。我翻了一下失败 case,发现它有个毛病——太爱脑补。用户没说折扣类型,它直接给填了个 "percentage",结果跟我们业务逻辑冲突了。我们系统里折扣类型是枚举值,"percentage" 根本不在白名单里,下游校验直接给拒了。
Claude 3.5 Sonnet 数组处理意外地稳
数组嵌套场景它拿了最高分 95.1%。我仔细看了输出,发现它对数组元素的字段完整性保持得特别好,很少出现「第一个元素有 discount,第二个元素丢了」的情况。这一点在订单场景里太重要了——你总不能第一个商品打折、第二个原价,结果系统只解析出一个 discount 对象吧。
据我了解,Claude 在结构化输出上做了一些针对性的 RLHF 训练,大概是从去年年底那个版本开始的。不确定具体细节,但效果确实摆在那儿。
国产模型的坎:三层以下还行,再深就喘
嗯...这个比较复杂。
Qwen-Max 和 DeepSeek-V3 在基础嵌套上其实不差,95% 左右的准确率完全够用。但一到四层嵌套加缺省字段,准确率直接掉到 70% 档。典型问题是深层字段直接丢失——比如 order.customer.address.geo 整个对象就没了,不是填错,是压根没生成。我看日志的时候,KeyError: 'geo' 刷了一屏。
踩坑实录:花了我三个小时的 bug
说个让我印象深刻的翻车现场。
测试 DeepSeek-V3 的时候,有条语料是:「寄到北京朝阳区望京 SOHO,买两杯拿铁,用会员价」。
预期输出里,items[0].discount.type 应该是 "membership",items[0].discount.value 应该是 null。因为我们系统里会员价是固定折扣策略,走的是另一套计价逻辑,不需要在 order 层面传具体数值。
结果 DeepSeek 返回的是:
{
"items": [
{
"sku": "latte",
"quantity": 2,
"discount": null
}
]
}它直接把整个 discount 对象设成了 null。
炸了。
下游订单系统用的是严格的 struct 解析,discount 字段预期是一个对象,结果拿到一个 null,直接空指针异常。整个链路 500,订单创建失败。
我一开始以为是 prompt 写得不够明确,改了三四版还是不行。prompt 里我甚至加了一句「If a field is optional but its parent object is required, keep the parent object with null fields」。没用,还是丢。
后来我觉得,这可能是模型对「对象内的可选字段」和「整个对象可选」的语义理解有偏差——它觉得既然 value 不知道填什么,那整个 discount 就不要了。但 Schema 里明明写了 discount 是一个 object type,required 字段里也有它。
这种问题在真实业务里太致命了。圈子里有个梗叫「AI 帮你写代码,AI 也帮你写 bug」,大概就是这个意思。
选型建议:别只看跑分
根据这轮测试,我的建议是:
- **复杂业务场景(3层以上嵌套 + 数组)**:优先 GPT-4o 或 Claude 3.5 Sonnet。前者综合最强,后者数组处理更稳。预算充足的话两个都接,做 fallback。
- **中等复杂度(2层以内 + 少量数组)**:Qwen-Max 性价比很高,国产模型里表现最好,延迟也低。我们公司用阿里云,走内网调用延迟大概在 200ms 左右,GPT-4o 走美国那边经常 800ms+。
- **简单场景**:随便选,GLM-4-Plus 都够用,还便宜。智谱最近在搞活动,API 调用打五折,具体到什么时候忘了,可以去他们官网看。
- **对延迟敏感**:DeepSeek-V3 速度确实快,但嵌套场景一定要加后处理校验,不然线上事故率会让你怀疑人生。
另外,不管你用哪个模型,强烈建议在 Function Calling 之后加一层 Schema 校验。我用 jsonschema 这个 Python 库写了个校验中间件,把不少模型的「创造性发挥」给拦了下来。具体做法是先校验 JSON 结构完整性,缺字段的补默认值,多字段的剔除,然后再过一次业务规则引擎。这套搞下来,线上事故率降了不止一个数量级。
写在最后
Function Calling 这东西,2023 年刚出来的时候大家还在惊叹「能调函数了」,到 2025 年已经卷到了「嵌套四层能不能一个字段不丢」。模型的进步是实打实的,但离「扔个 Schema 就完美输出」还有距离。
我现在养成了一个习惯:每次模型升级,第一件事不是看 benchmark,而是跑一遍自己的测试集。毕竟 benchmark 不会告诉你,你的订单系统会因为一个 null 值炸掉,也不会告诉你凌晨三点被 on-call 叫起来修 bug 是什么感觉。
你们在实际项目里用 Function Calling 踩过什么坑?有没有遇到过模型「创造性填参」的奇葩 case?我见过最离谱的一次,模型给 discount.value 填了个字符串 "free",下游系统直接类型转换失败。评论区聊聊,我请喝咖啡(精神上的)。
#functioncalling #大模型评测 #AI开发 #2025技术趋势 #程序员踩坑日记
读者评论 3