What is the issue?
Qwen 3.5 27B: Tool calling completely non-functional and repetition penalties silently ignored
Qwen 3.5 27B is the first consumer-GPU-capable model to match GPT-5 mini on SWE-bench (72.4), with native multimodal support, 262K context, and agentic tool calling trained across 1 million RL environments. It fits on a single RTX 5090 at Q4_K_M. There is currently no comparable alternative at this size.
Three bugs in Ollama make its agentic capabilities — the model's primary differentiator — completely non-functional. All three are verified against source code (v0.17.1 through master 79917cf) and the HuggingFace ground truth template. None are fixable by end users.
Full source-level analysis with exact file paths, line numbers, and diffs: Inference Report
Bug 1: Repetition penalties are silently ignored
The Go runner's sampler has zero implementation of penalty sampling. repeat_penalty, presence_penalty, and frequency_penalty are accepted by the API without error and silently discarded. The model card explicitly recommends presence_penalty=1.5 to prevent repetition loops during thinking. Setting it via the API has no effect whatsoever.
The C++ runner (llamarunner) implements penalties correctly — but Qwen 3.5 is forced onto the Go runner via OllamaEngineRequired() and cannot use it.
This affects all models on the Go runner, not just Qwen 3.5.
Full evidence: Missing Penalty Sampling
Bug 2: Tool calling uses the completely wrong format
The registry config blob sets renderer: "qwen3.5" / parser: "qwen3.5", which maps to the Qwen 3 Hermes-style JSON tool calling pipeline (Qwen3VLRenderer + Qwen3Parser).
Qwen 3.5 was not trained on this format. It was trained on the Qwen3-Coder XML format (<function=name><parameter=key>value</parameter></function>), as confirmed by the HuggingFace chat template.
The correct pipeline (Qwen3CoderRenderer + Qwen3CoderParser) already exists in the codebase — it's just wired to "qwen3-coder" instead of "qwen3.5".
The system prompt, the format instruction, the tool call rendering in conversation history, and the output parser are all wrong. There are 6 concrete mismatches between what Ollama sends and what the model was trained on.
Full evidence: Tool Calling Format Mismatch
Bug 3: Unclosed </think> tag corrupts multi-turn tool calling prompts
When an assistant message has thinking + tool calls but no text content (the standard "think then call a tool" pattern), the renderer never emits </think>. The tool call is rendered inside an unclosed <think> block, corrupting every subsequent turn the model sees.
The parser side of this was fixed in v0.17.3 (d98dda4, PR #14477) — the parser now correctly handles model output that has <tool_call> before </think>. But the renderer side remains broken: multi-turn prompts sent to the model still contain unclosed <think> tags. The tool-call thinking tests in qwen3vl_thinking_test.go (lines 119–323) are still commented out.
Full evidence: Bug 3 details
Status across releases
| Bug |
v0.17.1 |
v0.17.2 |
v0.17.3 |
v0.17.4 |
master |
| Penalty sampling silently ignored |
Present |
Present |
Present |
Present |
Present |
| Wrong tool call format |
Present |
Present |
Present |
Present |
Present |
Unclosed </think> (renderer) |
Present |
Present |
Present |
Present |
Present |
Unclosed </think> (parser) |
Present |
Present |
Fixed |
Fixed |
Fixed |
Environment
- Ollama v0.17.1 through master (
79917cf, Feb 26, 2026 UTC)
- Model:
qwen3.5:27b-q4_K_M
- Full report with source-level verification: qwen3.5_27b_inference_report.md
Edited (Feb 27, 2026 UTC): Found two additional issues while implementing fixes for the above three bugs in a fork based on v0.17.4 (cc90a035):
Bug 2 expanded — Coder pipeline has zero thinking support: Simply rewiring "qwen3.5" to Qwen3CoderRenderer/Qwen3CoderParser is insufficient. Both have zero thinking support — no <think>/</think> handling in the renderer, no thinking state machine in the parser. Qwen 3.5 requires thinking support for agentic use (the model card recommends enable_thinking=true), so the Coder pipeline needs to be extended with full thinking support before the rewiring is useful.
Bug 4 — Missing generation prompt after tool call turns: When the last message is an assistant message with tool calls, the renderer treats it as a prefill (incomplete turn to be continued) and never emits <|im_end|> or the <|im_start|>assistant\n generation prompt. Root cause is the prefill variable in both qwen3coder.go:148 and qwen3vl.go:82 — it fires for any last assistant message including ones with tool calls. This breaks the entire tool call round-trip loop. Also affects qwen3-vl-instruct and qwen3-vl-thinking. Full evidence.
Updated status table:
| Bug |
v0.17.1 |
v0.17.2 |
v0.17.3 |
v0.17.4 |
master |
| Penalty sampling silently ignored |
Present |
Present |
Present |
Present |
Present |
| Wrong tool call format (+ missing thinking support) |
Present |
Present |
Present |
Present |
Present |
Unclosed </think> (renderer) |
Present |
Present |
Present |
Present |
Present |
Unclosed </think> (parser) |
Present |
Present |
Fixed |
Fixed |
Fixed |
| Missing generation prompt after tool calls |
Present |
Present |
Present |
Present |
Present |
Relevant log output
OS
No response
GPU
No response
CPU
No response
Ollama version
0.17.4
What is the issue?
Qwen 3.5 27B: Tool calling completely non-functional and repetition penalties silently ignored
Qwen 3.5 27B is the first consumer-GPU-capable model to match GPT-5 mini on SWE-bench (72.4), with native multimodal support, 262K context, and agentic tool calling trained across 1 million RL environments. It fits on a single RTX 5090 at Q4_K_M. There is currently no comparable alternative at this size.
Three bugs in Ollama make its agentic capabilities — the model's primary differentiator — completely non-functional. All three are verified against source code (v0.17.1 through master
79917cf) and the HuggingFace ground truth template. None are fixable by end users.Full source-level analysis with exact file paths, line numbers, and diffs: Inference Report
Bug 1: Repetition penalties are silently ignored
The Go runner's sampler has zero implementation of penalty sampling.
repeat_penalty,presence_penalty, andfrequency_penaltyare accepted by the API without error and silently discarded. The model card explicitly recommendspresence_penalty=1.5to prevent repetition loops during thinking. Setting it via the API has no effect whatsoever.The C++ runner (
llamarunner) implements penalties correctly — but Qwen 3.5 is forced onto the Go runner viaOllamaEngineRequired()and cannot use it.This affects all models on the Go runner, not just Qwen 3.5.
Full evidence: Missing Penalty Sampling
Bug 2: Tool calling uses the completely wrong format
The registry config blob sets
renderer: "qwen3.5"/parser: "qwen3.5", which maps to the Qwen 3 Hermes-style JSON tool calling pipeline (Qwen3VLRenderer+Qwen3Parser).Qwen 3.5 was not trained on this format. It was trained on the Qwen3-Coder XML format (
<function=name><parameter=key>value</parameter></function>), as confirmed by the HuggingFace chat template.The correct pipeline (
Qwen3CoderRenderer+Qwen3CoderParser) already exists in the codebase — it's just wired to"qwen3-coder"instead of"qwen3.5".The system prompt, the format instruction, the tool call rendering in conversation history, and the output parser are all wrong. There are 6 concrete mismatches between what Ollama sends and what the model was trained on.
Full evidence: Tool Calling Format Mismatch
Bug 3: Unclosed
</think>tag corrupts multi-turn tool calling promptsWhen an assistant message has thinking + tool calls but no text content (the standard "think then call a tool" pattern), the renderer never emits
</think>. The tool call is rendered inside an unclosed<think>block, corrupting every subsequent turn the model sees.The parser side of this was fixed in v0.17.3 (
d98dda4, PR #14477) — the parser now correctly handles model output that has<tool_call>before</think>. But the renderer side remains broken: multi-turn prompts sent to the model still contain unclosed<think>tags. The tool-call thinking tests inqwen3vl_thinking_test.go(lines 119–323) are still commented out.Full evidence: Bug 3 details
Status across releases
</think>(renderer)</think>(parser)Environment
79917cf, Feb 26, 2026 UTC)qwen3.5:27b-q4_K_MEdited (Feb 27, 2026 UTC): Found two additional issues while implementing fixes for the above three bugs in a fork based on v0.17.4 (
cc90a035):Bug 2 expanded — Coder pipeline has zero thinking support: Simply rewiring
"qwen3.5"toQwen3CoderRenderer/Qwen3CoderParseris insufficient. Both have zero thinking support — no<think>/</think>handling in the renderer, no thinking state machine in the parser. Qwen 3.5 requires thinking support for agentic use (the model card recommendsenable_thinking=true), so the Coder pipeline needs to be extended with full thinking support before the rewiring is useful.Bug 4 — Missing generation prompt after tool call turns: When the last message is an assistant message with tool calls, the renderer treats it as a prefill (incomplete turn to be continued) and never emits
<|im_end|>or the<|im_start|>assistant\ngeneration prompt. Root cause is theprefillvariable in bothqwen3coder.go:148andqwen3vl.go:82— it fires for any last assistant message including ones with tool calls. This breaks the entire tool call round-trip loop. Also affectsqwen3-vl-instructandqwen3-vl-thinking. Full evidence.Updated status table:
</think>(renderer)</think>(parser)Relevant log output
OS
No response
GPU
No response
CPU
No response
Ollama version
0.17.4