Skip to content

Tool-arg grammar: Qwen/Llama JSON-syntax constraints (#374 follow-up) #376

Description

@pekkah

Summary

Extend the schema/grammar-constrained tool-argument decoding from #374 (PR #375) to the Qwen and Llama families, which emit JSON tool-call arguments rather than Gemma's bespoke <|"|>-quoted form.

Context

#374 added IToolCallAdapter.BuildArgumentConstraint(tools, vocab) (default null) plus a Gemma-specific byte-level pushdown automaton (GemmaToolArgumentConstraint). The hook is the generalization seam: each adapter owns its wire format. Gemma is wired end-to-end; everyone else returns null (generates unconstrained).

Scope

  • A JsonToolArgumentConstraint (reusable across QwenToolCallAdapter / LlamaToolCallAdapter / QwenCoderToolCallAdapter / DeepSeekToolCallAdapter) targeting standard JSON: {"key": "value", ...} with double-quoted keys/strings, bare numbers/booleans/null, [...] arrays, nested {...} objects, and enum restriction.
  • Each adapter's BuildArgumentConstraint override returns it for its envelope (Qwen <tool_call>{json}</tool_call>, Qwen3-Coder <function=NAME> XML wrapper — note: Coder uses <parameter=…> XML, not JSON, so it may need its own matcher; Llama <|python_tag|>{json}, DeepSeek name<|tool_sep|>{json}).
  • Reuse the existing ToolSchema/CompiledObject/CompiledNode/GrammarVocabulary infra and the same correctness invariants (only declared keys, required-once, value shapes, enum; free string content; default-off byte-identical; allocation-free hot path).
  • The JSON form needs the early-engage trick too (the model can emit a merged {} token) and double-quote handling (JSON " vs Gemma's <|"|> special token — the structural quote is a regular byte here, so string content must be matched char-level with escape handling, or kept permissive between the quotes).

Tests

Mirror ToolGrammarMockTests with a fake JSON tokenizer + model-gated conformance on a real Qwen/Llama GGUF (required-key, foreign-key rejection, enum, array, nested).

Follow-up to #374 / #375.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions