三个小模型 16 场景通过率对比

搭本地 Agent 时我一直有个想法:调度层用小模型(判断该调哪个函数、填什么参数),重活交给大模型——又省钱又快。但网上评测都在跑聊天,没人认真测过小模型的 function calling 到底靠不靠谱。所以我自己设计了一个 16 场景综合基准,把三个候选小模型拉出来跑了一遍。结果反直觉:最小的 0.3B 全对,1.2B 反而翻车

环境:llama.cpp 纯 CPU 8 线程、--reasoning off、temperature=0.2,JSON Schema 校验 + 失败重试一次。2026-08-26 实测。

三个候选

模型体积(Q4)背景
LittleLamb-ToolCalling-0.3B237MBQwen3-0.6B 压缩版,原生 tool use
Qwen3-0.6B609MB(Q8)通义小钢炮,agent 判断力公开评测第一梯队
Nexus-TinyFunction-1.2B697MBBFCL 简单调用 94%,纸面最强

16 场景综合结果

基准覆盖:简单调用、多参数(枚举)、计算、嵌套对象、并行调用、无关拒绝、多城市、布尔参数、复杂计算、长文本、枚举严格、函数选择、多邮件、显式拒绝等 16 个场景,5 个函数 schema。

16 场景通过率(JSON Schema 校验口径)
LittleLamb 0.3B16/16
Qwen3-0.6B15/16
Nexus 1.2B11/16
总耗时(16 场景,越短越好)
LittleLamb 0.3B13.2s
Qwen3-0.6B20.3s
Nexus 1.2B60.7s

Nexus 1.2B 为什么翻车

不是能力问题,是输出格式问题

  • Qwen3-0.6B / LittleLamb 走 Qwen 原生 tool_call 格式,llama.cpp 直接解析成标准 OpenAI tool_calls 字段,无缝接入 LiteLLM / OpenAI SDK
  • Nexus 输出 <tool_call>{...}</tool_call> XML 标签,llama.cpp 不转换,得自写 XML 解析器
  • 更糟的是嵌套对象会被压平成字符串(send_email.to)、枚举多包一层 properties——同请求重试也修不回来,这是结构性的缺陷
  • 偶发把无关请求误调用 set_reminder(应该拒绝)

纸面跑分高(BFCL 94%)≠ 实际可用,格式兼容性才是工程第一门槛

代表性场景明细(三模型对比)

场景LittleLamb 0.3BQwen3-0.6BNexus 1.2B
简单调用(查天气)✅ get_weather{Beijing}✅ get_weather{Beijing}✅ 通过
多参数(枚举 unit)✅ fahrenheit 正确⚠️ 偶发拼成 "celsius fahrenheit"⚠️ 多包一层 properties
嵌套对象(send_email.to{name,email})✅ 结构完整✅ 结构完整❌ to 被压平成字符串
多函数选择✅ calculate{156/12}✅ calculate{156/12}✅ 通过
并行调用(京沪双查询)✅ 两次调用❌ 未调用、反向澄清✅ 两次调用
无关请求拒绝✅ 拒绝✅ 拒绝⚠️ 偶发误调用 set_reminder
布尔参数(关闭提醒)✅ enabled=false⚠️ 主动不调用(合理语义但判失败)❌ 重试仍失败

三个高频踩坑点提炼:① 枚举参数偶发拼接("celsius fahrenheit")——所有小模型都会犯,必须做后处理修正;② 并行调用是 0.6B 的能力天花板;③ 嵌套对象是 Nexus 的死穴,重试也救不回来。

稳定性:连跑 3 轮

模型R1R2R3稳定失败
LittleLamb 0.3B16/1616/1616/16
Qwen3-0.6B15/1615/1615/16仅「关闭提醒」场景(enabled=false 不调工具,属合理语义判断)

两个模型三轮零摇摆,耗时波动 <3%——比想象中可靠得多。

纯 CPU 启动参数(实测调优)

llama-server -m LittleLamb-0.3B-Q4_K_M.gguf -t 6 --reasoning off -c 8192
  • 线程数 = 物理核心数:6 核机用 -t 6,输出 98.7 t/s;开到 -t 16 反而暴跌到 59 t/s(内存带宽争用)
  • 这些 GPU 向的参数在纯 CPU 小模型上全是负优化:--flash-attn、KV cache 量化(--cache-type-k/v q8_0)、--mlock、投机解码——实测均无正收益
  • 比默认 -t 8 快约 19% 输出 / 12% 输入

生产建议

  • 调度层首选 LittleLamb 0.3B:体积最小、最快、16/16;或 Qwen3-0.6B 更「谨慎」(enabled=false 主动不调用,实为正确判断)
  • 必须加保险:temperature 设 0 并固定 seed;输出做 JSON Schema 校验 + 失败重试一次;枚举字段做后处理修正(小模型偶发把 enum 两值拼成 "celsius fahrenheit")
  • 重活交给大模型:30B 级 MoE 做执行,0.3B 只做调度

想看速度层面的原理(为什么 MoE 快、带宽为什么是瓶颈),看这篇纯 CPU 推理实测

免责声明:小模型输出有随机性,测试为特定 prompt 与采样参数下的结果;换模型版本或框架可能得出不同结论。

For local agent stacks, the dispatcher (deciding which function to call and with what args) doesn't need a big model. But nobody seriously benchmarks small-model function calling — so I built a 16-scenario suite and ran three candidates. Counter-intuitive result: the smallest model (0.3B) aced it; the 1.2B flopped.

Setup: llama.cpp, CPU-only (8 threads), --reasoning off, temperature 0.2, JSON Schema validation with one retry. Tested 2026-08-26.

Results (16 scenarios)

ModelSizePassRetriesTotal time
LittleLamb-ToolCalling-0.3B237MB16/16013.2s
Qwen3-0.6B (Q8)609MB15/16120.3s
Nexus-TinyFunction-1.2B697MB11/16660.7s

Why the 1.2B failed

Not capability — output format. Qwen3/LittleLamb emit native tool_calls that llama.cpp converts to the OpenAI format, plugging straight into LiteLLM/OpenAI SDKs. Nexus emits <tool_call> XML that requires a custom parser, flattens nested objects (send_email.to), wraps enums in extra properties, and occasionally calls tools on irrelevant requests. High BFCL scores ≠ production-ready; format compatibility is the first engineering gate.

Stability (3 rounds)

LittleLamb: 16/16 × 3 rounds, zero flips. Qwen3-0.6B: 15/16 × 3 (the only "miss" is semantically correct — it declines to call a tool when enabling=false). Time variance under 3%. Far more reliable than expected.

CPU launch tuning

  • Threads = physical cores (-t 6): 98.7 tok/s out; forcing -t 16 crashes it to 59
  • GPU-oriented flags are all negative on CPU-only small models: flash-attn, KV-cache quantization, mlock, speculative decoding — none helped

Production advice

  • LittleLamb 0.3B as the dispatcher (smallest, fastest, 16/16); Qwen3-0.6B if you prefer "cautious"
  • Always add: temperature 0 + fixed seed, JSON Schema validation with one retry, enum post-correction
  • Heavy lifting goes to a 30B-class MoE; the 0.3B only dispatches
Disclaimer: small-model outputs are stochastic; results are specific to these prompts, versions and parameters.
返回文章列表