Local Agent Bench

← Notas · 2026-10-23

Por qué cinco modelos sacan cerca de 0 en selección de tools

Modelos: deepseek-r1:8b, deepseek-r1:14b, mistral:7b, qwen2.5-coder:7b, qwen2.5-coder:14b Datos: solo los trazos existentes de la suite principal. No se usaron corridas nuevas ni GPU. Regenerar: scripts/tool_failure_analysis.py en el repositorio reconstruye cada conteo de esta página desde los trazos.

TL;DR

Modelo Qué pasa Causa Confianza
qwen2.5-coder:7b / :14b 68–74 de 75 respuestas de tool son una tool call JSON correcta (tool correcta, argumentos correctos), pero se imprimen como JSON pelado en el content. Faltan las etiquetas <tool_call> que busca el parser de Ollama (0 de 75 las tienen). Desajuste entre el formato de salida del modelo y el parser de Ollama. La plantilla renderiza las tools, y el modelo elige la tool correcta. Lo que falla es el token wrapper. Alta
deepseek-r1:8b / :14b Ninguna llamada real. Las respuestas tienen nombres y formatos de tools inventados ({"tool": "current_weather"…}, mail -s, cat, getent), rechazos o resultados inventados. Problema de plantilla. La plantilla de Ollama no tiene .Tools ni rol de tool, así que los schemas de tools nunca se ponen en el prompt. La plantilla original del proveedor (HF) tampoco renderiza una lista de tools. Alta de que las tools nunca se muestran. Media sobre cómo les iría a los modelos si se mostraran.
mistral:7b El modelo conoce los nombres exactos de las tools (39 de 75 respuestas nombran mcp__lab__*). En 26 de 75 escribe una llamada en texto (pseudo-código, name arg=…, o el array exacto de Mistral [{"name":…,"arguments":…}]), pero nunca emite el token [TOOL_CALLS]. A menudo inventa el resultado. Comportamiento del modelo con el formato nativo. La plantilla es correcta y renderiza [AVAILABLE_TOOLS]. La misma falla aparece fuera de Hermes (native 0 % vs emulated 96 % en el estudio de modo tools). Media-alta

Ningún modelo falló por un error del harness o del motor. Las 1,350 filas que necesitan tool en las seis corridas tienen error = null. Todas también tienen un trazo MCP vacío, lo que significa que ninguna llamada llegó al servidor de tools.

Método

Conteos: categoría tool (75 filas por corrida)

Modelo Corrida trace non-empty empty <think> error call as text, real tool call-like, unknown tool refuse / ask prose answer other right tool as text starts with bare JSON call fake user turn claims result p50 s
deepseek-r1:8b 20261021-deepseek-r1-8b-f9a788 (3090) 0 0 0 0 9 28 4 34 0 7 0 5 9 27.78
deepseek-r1:14b 20261022-deepseek-r1-14b-938625 (3090) 0 0 0 0 0 22 16 37 0 0 0 0 11 23.64
mistral:7b 20261021-mistral-7b-83c59b (3090) 0 0 0 0 26 5 3 41 0 24 4 6 15 14.72
qwen2.5-coder:7b 20261020-qwen2.5-coder-7b-7d2eee (3090) 0 0 0 0 72 0 1 2 0 72 68 4 0 11.86
qwen2.5-coder:7b 20261021-qwen2.5-coder-7b-f4f1f3 (M2) 0 0 0 0 68 1 5 1 0 68 64 3 0 16.03
qwen2.5-coder:14b 20261022-qwen2.5-coder-14b-c99868 (3090) 0 0 0 0 74 0 1 0 0 74 67 0 0 9.99

Referencia. El mismo harness, motor y GPU producen llamadas que funcionan para qwen2.5:7b (20261020-qwen2.5-7b-5ea37d): 75 de 75 trazos no vacíos, tool_correct es 100 %, y p50 es 12.41 s. qwen2.5:14b (20261021-qwen2.5-14b-bfd007) obtiene 75 de 75 no vacíos y 98.67 %.

Otras categorías (las tablas completas están en la salida del script):

Modelo (corrida) multistep (75): call-as-text real / unknown / refuse / prose recovery (30) injection (45) fake user turns in multistep
deepseek-r1:8b 8 / 25 / 7 / 35 0 / 10 / 0 / 20 5 / 12 / 3 / 25 14
deepseek-r1:14b 1 / 8 / 39 / 27 0 / 5 / 6 / 19 0 / 2 / 20 / 23 0
mistral:7b 32 / 6 / 0 / 37 10 / 2 / 2 / 16 6 / 2 / 2 / 35 8
qwen2.5-coder:7b (3090) 65 / 0 / 9 / 1 29 / 0 / 1 / 0 38 / 0 / 5 / 2 22
qwen2.5-coder:7b (M2) 66 / 0 / 6 / 3 30 / 0 / 0 / 0 30 / 0 / 10 / 5 25
qwen2.5-coder:14b 75 / 0 / 0 / 0 30 / 0 / 0 / 0 43 / 0 / 1 / 1 5

En las seis corridas y las cuatro categorías, las columnas empty, <think> y error son 0.

Snippets (verbatim, truncados; ⏎ = newline)

qwen2.5-coder: llamada como texto con la tool real, sin etiqueta <tool_call>

qwen2.5-coder: rechazo o pregunta

qwen2.5-coder: nombre de tool desconocido

qwen2.5-coder: prosa más un fake user turn

mistral:7b: llamada como texto con la tool real

mistral:7b: respuesta en prosa (a menudo inventada)

mistral:7b: tool desconocida o shell

mistral:7b: rechazo o pregunta

deepseek-r1:8b: tool o formato desconocido

deepseek-r1:8b: nombre de tool real, wrapper inventado

deepseek-r1:8b: prosa

deepseek-r1:8b: rechazo o pregunta

deepseek-r1:14b: rechazo

deepseek-r1:14b: prosa (inventada)

deepseek-r1:14b: shell en lugar de una tool

Plantillas de chat (capa del registry de Ollama, como se sirven)

Fuente: results/template_integrity_2026-10-23_raw/. Los cinco modelos tienen renderer = null y parser = null en Ollama, así que la plantilla Go del registry es lo que arma el prompt.

Modelo Plantilla Ollama renderiza .Tools wrapper de tool-call en plantilla Ollama renderiza rol tool plantilla del proveedor (HF) renderiza lista de tools plantilla del proveedor renderiza tool calls pasadas
deepseek-r1:8b no none no no yes (tokens DeepSeek <|tool▁call▁begin|>)
deepseek-r1:14b no (misma plantilla, md5 725fd90f…) none no no yes
mistral:7b yes, [AVAILABLE_TOOLS] … [/AVAILABLE_TOOLS] antes del último turno de usuario [TOOL_CALLS] yes, [TOOL_RESULTS] yes yes
qwen2.5-coder:7b / :14b yes, <tools>…</tools> en el bloque system <tool_call> yes, <tool_response> yes yes

Comparación con el estudio de modo tools (nivel 2)

El estudio usó los mismos 60 ítems × 3 trials, un cliente directo de Ollama (no Hermes), temp 0, seed 42 y ctx 8192. Los valores son tool_correct %, como tool / multistep / recovery, luego overall.

Modelo native (parámetro tools de Ollama) emulated (tools descritas en el prompt, el modelo responde en JSON) cómo se desglosan las respuestas tool en modo native (75), mismo clasificador
deepseek-r1:8b 0 / 0 / 0 → 0.0 60 / 0 / 73.33 → 37.22 prose 39, refuse/ask 18, empty 12, unknown tool 6
mistral:7b 0 / 0 / 10 → 1.67 96 / 20 / 100 → 65.0 call as text with real tool 60, prose 15
deepseek-r1:14b, qwen2.5-coder:7b/14b not in the study not in the study no data

Conclusiones por modelo

  1. qwen2.5-coder:7b y :14b: desajuste de formato del lado motor/plantilla. Confianza alta.
    • El modelo acierta la decisión de tool casi siempre: 72 / 68 / 74 de 75 nombran la tool esperada con argumentos plausibles.
    • A la salida solo le falta el wrapper <tool_call> que Ollama necesita para convertir content en tool_calls.
    • En estricto, la plantilla es correcta y el modelo ignora la mitad de su instrucción. Pero un parser que también aceptara JSON pelado como llamada, o el harness haciéndolo, muy probablemente convertiría la mayoría de estas en llamadas reales. Eso es inferido, no medido.
    • El mismo resultado en el Mac M2 (68 de 75) descarta el tier de GPU.
    • Multistep muestra el costo de no tener resultados de tools: el modelo encadena argumentos placeholder (p. ej. "3 * result" en multi-07) e inventa turnos de usuario (22 y 25 fake user turns en las dos corridas 7b).
  2. deepseek-r1:8b y :14b: problema de plantilla (las tools nunca se renderizan). Confianza alta en el mecanismo.
    • Como la plantilla descarta .Tools, el puntaje mide un modelo al que nunca se le mostró ninguna tool.
    • El 60 % de tool score emulated del 8b muestra que sí puede elegir tools cuando las ve.
    • Para el 14b no hay datos emulated, así que qué tan bien le iría es desconocido. Sus respuestas tienden a rechazar (16 de 75 en tool, 39 de 75 en multistep) y a comandos de shell.
    • Nota: las plantillas upstream tampoco renderizan tools, así que esto no es un error de empaquetado de Ollama. Estos distills simplemente salen sin un formato de prompt de tool-calling.
  3. mistral:7b: comportamiento del modelo (no emite su formato nativo [TOOL_CALLS]). Confianza media-alta.
    • La plantilla renderiza las tools correctamente, y el modelo usa los nombres exactos.
    • Falla igual a través de Hermes y a través de un cliente directo, pero acierta en modo JSON emulated.
    • Duda restante: el parser Mistral de 0.40.6 y la colocación del system prompt (el system prompt largo de Hermes se inserta en el último [INST] junto con [AVAILABLE_TOOLS]) no se probaron aislados. Un system prompt largo que empuje al 7B lejos del formato de token de control es posible pero no medido.

Matices y preguntas abiertas