Measuring the Serving Stack Instead of the Model: Hidden Confounds in Local Tool-Use Evaluation
在解决本地服务栈在模型运行前拒绝或修改请求,在工具调用评估中产生了未知的混淆,导致评估者将基础设施故障误认为模型能力不足。
结论论文证明了 0% 的工具调用率通常是服务栈的假象,而非模型本身能力的缺失。然而,该测量受到极小分母和高方差的限制,这意味着这些数据仅能凸显服务层的混淆,而无法用于可靠地对模型能力进行排名。
1. 任务
这篇论文在解决什么具体问题(输入,输出,场景)。
本文调查了本地服务栈(如 Ollama, llama.cpp, vLLM, SGLang)如何在请求传递给模型之前,评估和处理编码智能体的工具调用请求。在标准的本地智能体设置中,测试框架(harness)发送包含提示词和工具模式(tools=)的请求。服务层必须路由此请求,对其进行格式化,并将响应解析为结构化的 tool_call。
为什么这个问题很重要,难点在哪里。
这个协议步骤至关重要,但往往与模型自身能力相混淆。如果服务端无法处理 tools= 请求或未能解析出有效的模型输出,通常会向测试框架返回一个错误字符串。典型的基于轮次(per-turn)的分析会将这些传输错误读取为模型的普通非调用响应,从而导致测量的无声污染。当中间软件层独立于模型权重修改或拒绝请求时,很难评估真正的模型能力。
前人的方法是怎么做的,哪里不足。 之前的基准测试(如 BFCL)评估了函数调用,但并未将服务接口本身视为实验变量。智能体测试框架通常会记录助手的消息流,但未能保留结构化的错误元数据(如 HTTP 400 拒绝)。因此,当评估 Phi-3 或 Gemma-3 等模型时,它们可能得分为 0% 保真度(fidelity),这并非由于能力不足,而是因为服务层完全拒绝了其原生工具调用请求,而以往的基准测试未能隔离这一问题。
2. 核心思路
核心洞察在于,在本地工具调用评估中,决定工具调用请求是否成功的不仅是模型,还包括服务栈。通过分离工具通道(原生 tools= 与文本提示词)并探究不同的服务端点,作者表明“0% 的工具调用能力”往往意味着服务层直接拒绝了请求或解析失败,从而将基础设施的故障错误归咎于模型无能。
3. 机制 + 心智模型
论文在一个固定的聚合任务(每个模型 8 个种子)上使用三种配置隔离了服务层混淆:
- Native(原生): 测试框架发送默认的
tools=请求。Ollama 会按模型对该请求进行门控拦截(例如,Llama-3.2 获得原生调用;Qwen 返回文本;Phi-3/Gemma-3 直接被拒绝并返回 HTTP 400)。 - Native+hint(原生+提示): 依然发送
tools=,但在提示词中注入纯文本工具列表和明确的 JSON 格式。 - Text-tools(纯文本工具): 丢弃
tools=参数;提供统一的文本引导,从文本中解析调用。
心智模型: 服务层是一个不透明的守门员:如果模型不在服务端原生工具支持的 VIP 列表中,请求在到达权重之前就会被弹回,但测试框架却将其记录为模型主动选择不调用任何工具。
4. 指标 / 数据集
- 基准测试/数据集: 一个需要多次工具调用的固定聚合任务。在依赖链任务(4个种子)和单轮 HumanEval(6个种子)上进行了复现。
- 指标: 协议保真度(有效且符合模式的调用率,仅计算模型实际产生的轮次)。还报告了轮次池化率(turn-pooled rate)、单种子均值(带种子级 bootstrap 95% 置信区间),以及每轮结果的构成比例。
- 模型: Qwen2.5-Coder (0.5B, 1.5B, 3B, 7B, 14B), Llama-3.2-3B, Phi-3-mini, Gemma-3-4B, Gemma-3-270m。云端锚点模型:deepseek-v4-flash。
- 硬件: Ollama/llama.cpp 仅使用本地 CPU。跨栈测试使用 vLLM (T4) 和 SGLang (A800 80GB)。
- 服务栈/测试框架: ReAct 编码智能体框架(LOCA-bench 扩展)。服务后端:Ollama (0.30.8), llama.cpp, vLLM, SGLang。若未提供则填“not reported”。
5. 对比 baseline
论文没有提出新模型或方法,而是比较了标准服务配置与对照组。
- Native vs. Text-tools: 在 Ollama 上,Phi-3 和 Gemma-3 在 native 配置下得分为 0%(被拒绝),但在 text-tools 配置下分别达到了 38% 和 38%-100%。Qwen 系列模型(0.5B-14B)在原生通道加入文本提示后大幅提升(单种子指标绝对提升达 59 个百分点,最高达到 89%)。
- Llama-3.2 例外: native+hint 达到 82%,但统一的 text-tools 协议将其降至 44%,因为它抛弃了 Llama 原生支持的能力。
- 跨栈(Cross-stack)对比: 被 Ollama 拒绝的相同 GGUF 权重在 llama.cpp 上运行成功。vLLM 默认拒绝请求(除非提供特定的 flag 和解析器)。
- 受限解码(Constrained Decoding)对比: 使用结构化输出能保证所有 9 个本地模型在单步测试中达到 100% 有效的工具调用,但在智能体完整运行中会导致较弱的模型陷入无限循环(600-900 轮次)。 所有 baseline 都是作者在匹配的任务和硬件条件下运行的。
6. 开源
代码开源地址:https://github.com/LijuanTang94/serving-confound-repo
7. 关键数字核实
| 说法 | 出处 | 实际条件 | 成立? | 备注 |
|---|---|---|---|---|
| Phi-3 和 Gemma-3 因原生拦截报告为 0% | §1, §4, Table 1 | Ollama native FC | ✅ | 100% 的轮次都是被拒绝的 HTTP 400 请求。这特定于所测试的 Ollama 版本 (0.30.8)。 |
| 对接受请求的模型,在原生通道加文本提示可恢复大部分保真度 | §4, Fig 3, Table 1 | Qwen 0.5B-14B, Llama-3.2 | ✅ | per-seed 成功率从 0-60% 跃升至 35-89%。提升显著,尽管绝对数值有噪声。 |
| 统一纯文本协议降低了 Llama-3.2 的保真度 | §4, Fig 3, Table 1 | Llama-3.2-3B | ✅ | 从 82% (native+hint) 降至 44% (text-tools),因为纯文本丢弃了其原生支持。 |
| 轮次池化 (Turn-pooled) 与单种子 (per-seed) 估计差异达约 55 个点 | Abstract, §4, Table 1 | Qwen-0.5B text-tools | ⚠️ | 确实存在约 55 个点的最大差异,但这是一个由弱模型单次 41 轮死循环导致的极端离群值,而非典型方差。 |
| 受限解码消除了协议错误但引发了不终止问题 | §4 | 所有 9 个本地模型 | ⚠️ | 单步有效率 100% 适用于所有 9 个模型,但在智能体运行中 600-900 轮次的无限循环仅发生在较弱的模型上,而非全部。 |
| 被 Ollama 拒绝的相同权重可以在 llama.cpp 上运行 | §4, Table 2 | Phi-3, Gemma-3 | ✅ | llama.cpp 以 200 text/native 处理了请求。 |
8. 摘要没说的
- Inference/服务混淆: 拒绝机制特定于框架版本。Ollama 0.30.8 根据模型模板进行门控。vLLM 需要明确使用
--enable-auto-tool-choice和--tool-call-parser。SGLang 默认接受,但若未开启解析则返回文本。 - Metric Hygiene(指标卫生): 弱模型的分母极其单薄(8个种子中仅产生 8-16 轮次),导致 bootstrap 95% 置信区间巨大(例如,Qwen-0.5B text-tools 为 34% [9,59])。
- 无响应与保真度: “协议保真度”指标排除了无响应轮次。例如,在 text-tools 下,Gemma-3-4B 看似拥有 100% 的保真度,但这仅仅是因为每个种子它只发出一次有效调用,然后就不再响应(图4)。
- 泛化声明: 论文明确拒绝对模型缩放定律(scale laws)、模型家族或推理能力做出断言,因为在如此小的样本和高方差下,排名是不稳定的。
- 推论(Your Inference): 工程师必须将传输层错误(HTTP 4xx, 超时)与模型响应分开记录。将服务栈视为透明层在统计上是危险的。
9. 可达性与启发
- 可达性: 高。代码和提示词已提供。可以在标准硬件(CPU/消费级显卡)上本地运行。需要固定特定的 Ollama 版本(0.30.8)以完全复现原生的门控行为。
- 启发 (Inference): 务必固定并报告服务栈及其版本。“0% 成功率”可能仅仅是一个 400 Bad Request 错误。在宣布模型缺乏工具使用能力之前,请检查您的服务后端是否需要明确的解析器 flag。
- 启发 (Agents): 智能体测试框架必须持久化记录结构化的错误元数据,而不仅仅是助手的消息流。应使用带有置信区间的单种子(per-seed)成功率,而不是轮次池化(turn-pooled)成功率,后者容易被单一的无限循环人为抬高。
10. 置信度与下一步
- 机制: 高。跨栈探针清晰隔离了服务层作为起因。
- 报告的收益/方差: 高。作者对分母单薄和置信区间过大的问题极为透明。
- 泛化性: 中。特定的拦截行为受限于 Ollama 0.30.8,但服务栈混淆的广泛原则具有普遍适用性。
- 值得复现吗? 是的,关于单独记录传输层错误的核对清单应该立即实现在任何本地评估框架中。
- 下一步读什么? BFCL(了解基准对照)、LOCA-bench,以及关于推理后端作为测量变量的文献(例如 SilentHyper)。
- 未解问题: 标准化的云端 API(如 OpenAI, Anthropic)如何拦截那些不支持或微调模型端点的原生工具调用?模型上下文协议(MCP)是否引入了类似的翻译混淆?
11. 审校记录
- 任务: 更新了 meta.json 中的任务描述,将其改为直接的问题陈述,而不是“本文研究了...”。
- 置信度与下一步: 在 meta.json 的结论中增加了论文的主要局限性(极小的分母和高方差使得跨模型的能力排名不可靠)。
- Qwen 系列模型大幅提升: 明确了“最高提升至 89%”的表述,改为“绝对提升达 59 个百分点,最高达到 89%”。
- Phi-3 和 Gemma-3 因原生拦截报告为 0%: 增加备注,指出该门控拦截行为特定于所测试的 Ollama 版本 (0.30.8)。
- 原生通道加文本提示可恢复大部分保真度: 将 Llama-3.2 也作为恢复保真度的接受模型加入,而不仅是 Qwen 模型。
- 池化与单种子估计差异达约 55 个点: 降级为 ⚠️,因为 55 个点的差异是由弱模型单次 41 轮死循环导致的极端离群值,并非典型的方差。
- 受限解码消除了协议错误但引发了不终止问题: 降级为 ⚠️,因为笔记错误地声称所有 9 个本地模型都循环了 600-900 轮;论文指出这种不终止仅发生在较弱的模型上。
- 无法核实:特定的错误文本“Failed to get response after multiple retries”是否适用于所有 ReAct 框架实现,尽管它对于作者测试的 LOCA-bench 扩展是适用的。