Skip to content

Tool-arg grammar: Qwen3-Coder XML <function=…> argument constraint (#374/#376 follow-up) #383

Description

@pekkah

Gap

Schema/grammar-constrained tool-call argument decoding (#374) now covers every tool-call JSON wire format — Gemma 4 (#374), and Qwen / Llama-3 / DeepSeek (#376, 54ccf3d). The one remaining family is Qwen3-Coder, which emits arguments as XML, not JSON:

<tool_call>
<function=get_weather>
<parameter=location>
Paris
</parameter>
</function>
</tool_call>

QwenCoderToolCallAdapter (Architecture => "qwen3coder", src/SharpInference.Core/ToolCallAdapter.cs:402) does not override BuildArgumentConstraint, so it inherits the interface default (=> null, :123). Result: with SHARPI_TOOL_GRAMMAR / --tool-grammar enabled on a Qwen3-Coder model, arguments generate unconstrained — the same fidelity gap (#374's premise) that the constraint fixes for every other family. The XML parser side (#95) is already handled; only the constraint is missing.

Proposed

A byte-level PDA sibling of GemmaToolArgumentConstraint / JsonToolArgumentConstraint that walks the Qwen3-Coder XML skeleton instead of JSON braces:

  • Engage on <function=NAME> once NAME matches a known constrainable tool (early-engage analogue, before the first <parameter=...>).
  • Constrain <parameter=KEY> to declared keys, enforce required-once, and constrain each parameter's free-text value region to its declared type where checkable (Coder values are bare text between the open/close tags, so typed-string is free content; number/enum/bool can still be constrained).
  • Reuse the shared ToolSchemaCompiler (CompiledObject/CompiledNode, incl. the Tool-arg grammar: constrain partially-typed tools (Any/open-object values) (#374 follow-up) #378 FreeValue node) so partially-typed Coder tools stay constrained on their typed/required parts.
  • Wire via QwenCoderToolCallAdapter.BuildArgumentConstraint; default-off byte-identical; allocation-free hot path; NativeAOT-clean — same contract as the existing three.

Acceptance

  • Mock-tokenizer tests (fake Coder vocab with merged structural pieces) + a model-gated conformance test on a real Qwen3-Coder GGUF.
  • GPU A/B on qwen3-coder-30b-a3b: a required parameter that drops/malforms unconstrained is enforced with the constraint on.
  • Tests.Core green; sharpi run --tools … --tool-grammar on a Coder model emits a well-formed <function=…> call.

Refs #374, #376 (54ccf3d), #378 (c59ca83), #382 (ab6640e). Parser context: #95.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions