Skip to content

Guard Qwen3.5+ chat-template failure modes; stop deriving the low reasoning tier - #229

Merged
t-timms merged 1 commit into
mainfrom
fix/qwen38-template-500s-and-effort-tiers
Sep 24, 2026
Merged

t-timms merged 1 commit into
mainfrom
fix/qwen38-template-500s-and-effort-tiers

Conversation

@t-timms

@t-timms t-timms commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Why

The Ternary-Bonsai-2-27B KNOWN_ISSUES.md (updated 2026-09-24) documents Qwen3.8 chat-template failures. The template is shared by every Qwen3.8 build, so I checked Godspeed against each item. Three real exposures, plus a follow-up to #228.

Changes

Problem Where Fix
Resumed sessions append a system message after the first message; Qwen3.5+ templates raise System message must be at the beginning -> HTTP 500 Conversation.add_system_message (only caller: TUI resume bootstrap when only a summary is available) On an empty conversation, merge into the single leading system prompt; once messages exist, add a labelled user note.
Empty / None tool-call arguments stored in history; templates reject them (HTTP 500/400) Conversation.add_assistant_message Store "{}". Non-empty (even malformed) strings untouched; caller dicts not mutated.
A zero-argument call arriving as "" is dropped as malformed _parse_tool_call (json.loads("")) Empty/None parse as no arguments. Malformed JSON still rejected.
Derived reasoning-effort tiers pick low (budget <= 2048, minimal alias), but low does not shorten Qwen3.8 reasoning (Prism ML measured about xhigh token use) LLMClient._qwen_template_kwargs Budget <= 8192 -> medium, otherwise xhigh; minimal -> medium. An explicit reasoning_effort: low is still honoured. Follow-up to #228.

Docs (GODSPEED_ARCHITECTURE.md) and CHANGELOG.md updated.

Verification

  • ruff check ., ruff format --check ., mypy src/ (CI flags), bandit (CI flags): clean.
  • 696 passed / 27 skipped across the touched areas (test_qwen38_template_safety, test_session_resume, test_thinking, test_agent_loop, test_llm_client, test_context/, test_tui_commands). Full suite: see CI.
  • New: tests/test_qwen38_template_safety.py. Two existing resume tests asserted the old behavior (roles == ["system", "system"]) and now pin the fixed behavior.

Not verified

  • Nothing here was exercised against a live server. The 500 behaviour is taken from the Qwen3.8 chat_template.jinja (which raises on a non-first system message) and from Prism ML's KNOWN_ISSUES; I have not yet reproduced it against llama-server. That is part of the next measured run.
  • Non-Qwen models are unaffected except for the changes to add_assistant_message / _parse_tool_call, which only touch empty arguments.

…easoning tier

Ternary-Bonsai-2-27B's KNOWN_ISSUES page documents chat-template failures that
also apply to any Qwen3.8 build (the template is shared). Checking Godspeed
against them found three exposures.

- Resumed sessions appended a mid-conversation `system` message
  (Conversation.add_system_message, called from the TUI resume bootstrap).
  Qwen3.5+ templates raise "System message must be at the beginning" -> HTTP 500.
  It now merges into the single leading system prompt; once messages exist it
  adds a labelled `user` note instead.
- Empty / None tool-call arguments were stored as-is in history, and the
  templates reject them (HTTP 500/400). add_assistant_message now stores "{}".
- _parse_tool_call called json.loads("") on an empty argument string and dropped
  a valid zero-argument call as malformed. Empty/None now parse as no arguments.
  Malformed JSON is still rejected.
- The derived reasoning-effort tiers picked "low" for thinking_budget <= 2048 and
  for the "minimal" alias, but Prism ML measured "low" using about as many
  reasoning tokens as the default xhigh on Qwen3.8. Derived tiers now pick
  "medium" (budget <= 8192) or "xhigh"; an explicit `reasoning_effort: low` is
  still honoured. Follows up #228.

Tests: tests/test_qwen38_template_safety.py (new), and the two resume tests that
asserted the old two-system-message behavior now pin the fixed behavior.
@github-actions

Copy link
Copy Markdown

🤖 Godspeed Review

LLM review skipped (no API key configured).

Security

No secrets detected in changed files.

@t-timms
t-timms merged commit 4e04755 into main Sep 24, 2026
9 checks passed
@t-timms
t-timms deleted the fix/qwen38-template-500s-and-effort-tiers branch September 24, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant