Skip to content

Qwen 3.5 27B: Tool calling completely non-functional and repetition penalties silently ignored #14493

Description

@BigBIueWhale

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions