搭本地 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.3B | 237MB | Qwen3-0.6B 压缩版,原生 tool use |
| Qwen3-0.6B | 609MB(Q8) | 通义小钢炮,agent 判断力公开评测第一梯队 |
| Nexus-TinyFunction-1.2B | 697MB | BFCL 简单调用 94%,纸面最强 |
16 场景综合结果
基准覆盖:简单调用、多参数(枚举)、计算、嵌套对象、并行调用、无关拒绝、多城市、布尔参数、复杂计算、长文本、枚举严格、函数选择、多邮件、显式拒绝等 16 个场景,5 个函数 schema。
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.3B | Qwen3-0.6B | Nexus 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 轮
| 模型 | R1 | R2 | R3 | 稳定失败 |
|---|---|---|---|---|
| LittleLamb 0.3B | 16/16 | 16/16 | 16/16 | 无 |
| Qwen3-0.6B | 15/16 | 15/16 | 15/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 推理实测。
