Skip to content

Fix structured tool-result rendering for Qwen templates - #529

Draft
leehack wants to merge 1 commit into
mainfrom
fix/typed-tool-result-template-content
Draft

leehack wants to merge 1 commit into
mainfrom
fix/typed-tool-result-template-content

Conversation

@leehack

@leehack leehack commented Sep 18, 2026

Copy link
Copy Markdown
Owner

Summary

Qwen3.5's template rejects a typed tool result containing a Dart Map with Unexpected content type, preventing the follow-up inference after a successful tool call. Normalize structured results to JSON text at the shared template-input boundary; preserve string results, source objects, and the public message JSON representation.

Fixes #528.

Production-readiness scope

  • User-facing scope: JSON-compatible tool results (objects, arrays, scalars, and null) render through shared chat-template handlers. Multimodal template contexts receive a text part.
  • Supported platforms/paths: Shared Dart rendering on VM and Chrome; exact Qwen3.5-0.8B GGUF CPU tool cycles verified on macOS.
  • Unsupported or intentionally unavailable paths: No new backend/platform capability is claimed. Results must be JSON-compatible; ordinary image/audio messages retain existing behavior.
  • Out of scope / follow-ups: Gemma4/FunctionGemma custom serializers, native artifacts, runtime pins, accelerator qualification, and suite PR Add portable validation suite and guarded Firebase/GCE runners #515 are unchanged. Parser follow-up Qwen3.5 XML parser loses schema strings and exposes undeclared tool calls #530 blocks acceptance of the stricter expanded schema/rollback coverage; it predates this input fix and remains separate.

Completeness checklist

  • Declared scope fully implemented.
  • Unsupported combinations remain outside the declared scope.
  • Tool-calling guide and Unreleased changelogs updated; no public API signature or support-matrix changes.
  • Regression coverage includes the exact affected template, structured payload shapes, escaping/Unicode, string/source preservation, and ordinary media controls.
  • No credentials, signed URLs, or machine-local evidence paths added to tracked content.
  • Newly exposed parser follow-up tracked in Qwen3.5 XML parser loses schema strings and exposes undeclared tool calls #530; no claim that its failing acceptance axes pass.

Test Plan

  • dart run tool/prepare_workspace.dart
  • dart format --output=none --set-exit-if-changed .
  • dart analyze
  • dart test -p vm -j 1 --exclude-tags local-only — 2,254 pass, three existing skips.
  • dart test -p chrome --exclude-tags local-only — 960 pass.
  • tool/testing/run_template_parity_suites.sh — template units, pinned upstream chat/parser suites, and compiled grammar acceptance/rejection pass.
  • Coverage-enabled VM rerun and LCOV threshold — 81.06% (13,681/16,878), above 70%.
  • tool/docs/validate_links.sh — production docs build and links pass with Node 20.

Matrix Evidence

Matrix row Scope covered Platform / model / backend Result Evidence / notes
structured-output-adversarial Shared template boundary; exact Qwen template; Map/list/scalar/null, escaping/Unicode; unchanged media/string/source controls VM / Chrome PASS Targeted VM26, Chrome25; pinned parser and15 compiled grammar tests pass. Grammar/parser implementation unchanged.
high-risk-exact-head-independent-qa Production call sites, deletion mutation, exact committed diff Head 2acefdc54fd29348ac89c84408a4ae8a639d22e2 / base 6c01a69af5bd13b338763f5f63cf16e482aa9fd6 PASS local audit Independent53 targeted/custom-handler tests pass; removing conversion kills structured-result regressions.
Issue528 affected-family smoke Public tool call → typed Map result → follow-up; ordinary recovery macOS / Qwen3.5-0.8B-Q4_0 GGUF / explicit CPU PASS Both auto and required emit get_weather(city Montréal), follow-up returns exactly17 with stop/no tool deltas, recovery succeeds. Model SHA256 57d1997790d1744fba5b40a7317df71ea5e2acee28c47e78f0cce39c0703f8cf; temperature0, seed1, thinkingfalse, context1024, threads4, gpuLayers0. No timing/accelerator claim.

Review Notes

  • Independent exact-commit audit accepted; zero blocking findings. Real-model evidence was inspected by the auditor, not independently rerun.
  • All14 hosted checks passed at 2acefdc54fd29348ac89c84408a4ae8a639d22e2; live PR identity and zero review threads reverified. Code audit accepted. Expanded local strict typed-history tests independently reproduce pre-existing Qwen3.5 XML parser loses schema strings and exposes undeclared tool calls #530 failures (schema string123 becomes integer123; undeclared function produces a tool delta). Those unfinished test additions are not pushed; existing PR CI does not validate them. The readiness evaluator remains rejected and draft status is retained.
  • Draft retained while PR-level readiness evidence is finalized; no merge/publication authorization.

High-risk regression review

  • Classification: high-risk — structuredOutput.
  • Implementation task: issue528 isolated runtime fix.
  • Independent blocking QA task: codex-adversarial-tool-result-2acefdc5, separate audit agent; accepted exact committed diff.
  • Exact head / current base: 2acefdc54fd29348ac89c84408a4ae8a639d22e2 / 6c01a69af5bd13b338763f5f63cf16e482aa9fd6.
  • Production-branch deletion, bypass, or miswire proof: Independent isolated deletion mutant fails structured Map/list/scalar/null assertions; exact Qwen production template-selection test fails without conversion.
  • Affected-family real-model/artifact evidence: Exact Qwen3.5-0.8B GGUF CPU auto/required typed-result cycles pass; exact template fixture and hashes are checked in.
  • Explicit unavailable-family or other N/A evidence: No all-platform, GPU/NPU, or LiteRT qualification claim. Gemma custom serialization unchanged and independently regression-tested. Strict grammar/parser implementations unchanged; existing pinned compiled and parser suites pass.
  • Known PR-caused P1 regressions: 0.
  • Unresolved review threads: 0, verified with a live GraphQL query.
  • Readiness evaluator: rejected / unchangedEvidencePath. All six structured-output axes require changed tests (schema lines175–204; evaluator lines971–1030 and1087–1092). Existing compiled grammar, reconstruction, rollback, tool-choice/thinking, and upstream parity tests pass but are unchanged; new input-serialization tests do not replace those axes. The release-metadata exception does not apply. Draft retained; meaningful additional typed-history regressions were attempted, but their schema reconstruction and rollback assertions expose pre-existing Qwen3.5 XML parser loses schema strings and exposes undeclared tool calls #530. Those strict assertions remain failing and must be addressed through a separate parser fix before the expanded acceptance evidence can pass. No gate bypass or externally enforced readiness claim.

@github-actions

Copy link
Copy Markdown
Contributor

Chat app preview deployed for 2acefdc.

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.

Normalize structured typed tool results for Qwen chat templates

1 participant