Repository navigation
[Rust Frontend] Build the Kimi K3 full-output grammar from its parser mode - #59190
Conversation
ce1219c to
2c427d7
Compare
1650e5d to
8b15f5d
Compare
8b15f5d to
ea7763b
Compare
|
/ci run |
|
✅ Triggered Buildkite CI #92074 for commit |
ea7763b to
c54a65c
Compare
c54a65c to
d178ebb
Compare
d178ebb to
a116b4a
Compare
a116b4a to
690f651
Compare
|
This pull request has merge conflicts that must be resolved before it can be |
690f651 to
f144328
Compare
48e4647 to
8392a1b
Compare
|
This pull request has merge conflicts that must be resolved before it can be |
CI selector (shadow): no narrower answer, every step runs: 194 test steps (270 jobs) instead of 7 (7 jobs)Shadow mode: this changes nothing about what CI runs. It shows what the evidence-based selector would pick for this PR, next to today's rules. How it works. Feedback welcome: reply here if it would skip a step this change needs, or runs something unrelated.
Why: rust: rust/src/chat/tests/grammar_replay/Kimi-K3.json: root crate bucket; 16 gate-env steps + 12 hardware-image steps; + the PyO3 bridge claim (vllm/tool_parsers/rust_tool_parser.py) Selector would run (194)
Would skip (today's rules run them) (0)none Would add (today's rules do not run them) (187)
AMD mirrors: would skip (0)none AMD mirrors: would add (156)
8 changed files · base |
8392a1b to
4583c7f
Compare
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
/ci run --allow-stale |
|
✅ Triggered Buildkite CI #93558 for commit
|
… mode Kimi K3 grammars only covered the output after reasoning, through a structural-tag builder whose `reasoning` option stood for both the request's thinking mode and the grammar's start. Build the whole generation from the parser's initialized mode instead, so the engine constrains it from token zero: - a prompt-opened `think` or `response` channel continues its body, and a prompt that opened no channel may emit a `think` channel; - after `think`, `auto` needs a response, tools, or both, while `required` and named choices need tools, optionally after a response; - named choices and `parallel_tool_calls=false` allow one call. Tools may now follow reasoning directly, which the builder rejected. Remove `KimiK3StructuralTagBuilder`; its call tag and XTML argument syntax move into the new grammar module. Tool-choice normalization for model-owned grammars lives in `output_grammar`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
`xgrammar-structural-tag` 0.4.1 exposes the tool-choice normalization that `build_structural_tag` applies before calling a builder. Use it for model-owned grammars instead of the local copy, which only covered `auto`, `required`, and named choices and missed the crate's validation and allowed-tools handling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Render the K3 topology snapshots with `output_grammar::test_utils::outline` instead of a K3-only one-line renderer. Call bodies are elided to `..` first, since the argument tests cover them, so the snapshots show the channel structure with its real markers, text exclusions, and call repetition options. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
2de412c to
028a54d
Compare
|
/ci run |
|
❌ This PR is 57 commits behind upstream |
|
/ci run --allow-stale |
|
✅ Triggered Buildkite CI #93919 for commit
|
|
/ci run --allow-stale |
|
✅ Triggered Buildkite CI #94139 for commit
|
Purpose
Kimi K3 grammars only cover the output after reasoning.
KimiK3StructuralTagBuildertakes areasoningoption that stands for both the request's thinking mode and the grammar's starting point, so the engine's reasoning gate decides when the grammar activates. The builder also requires a response channel on every path, which rejects tool calls directly after reasoning.Step 3 of the parser-owned output grammar rollout, following the grammar replay harness (#59143), the argument grammar split (#59395), and the shared schema root (#59408), all merged. The Kimi K3 parser already derives its starting channel from the prompt. This PR builds the whole generation's grammar from that initialized mode, so the engine constrains K3 from token zero (
reasoning_ended = Some(true)). The open-PR search found no other Rust K3 full-output grammar work; token-aware K3 parsing (#58358, merged) is a separate track.New
unified/kimi_k3/grammar.rsbuilds the topology fromKimiK3Mode:thinkclosesresponseclosesautoresponse [tools], ortools[tools]required[response] toolstools[response] tools, one calltools, one callA prompt-opened
thinkorresponsechannel continues its body. A prompt that opened no channel may first emit a wholethinkchannel. Every path may end with the message close. Named choices andparallel_tool_calls=falseallow one call.Free-text regions keep today's string-level exclusions, which stay within what the token-aware parser ([Rust Frontend] Token-aware marker parsing for Kimi K3 #58358) accepts. Token-level exclusions are a follow-up.
KimiK3StructuralTagBuilderis removed. Its call tag andXtmlArgumentssyntax, with thextml_typemapping from [Rust Frontend] ShareSchemaRootbetween argument coercion and grammars #59408, move intogrammar/arguments.rs. The call tag no longer reads the builder'sany_orderandmax_whitespace_cntoptions, so it uses their defaults, as the serving path already did.Model-owned grammars normalize the request's tools with
xgrammar_structural_tag::normalize_tool_choice, public since 0.4.1 (bumped in [Rust Frontend] Use the MiMo structural-tag builder #59148). This is the same normalizationbuild_structural_tagapplies before a crate builder, so K3 sees the same tools,BuilderToolChoice, and validation errors as builder-backed models.Out of scope: answer constraints (Step 4) and the ordinary-chat grammar skeleton. Requests without a tool grammar still get none.
Test Plan
cd rust cargo nextest run -p vllm-parser kimi_k3 cargo nextest run -p vllm-chat --test roundtrip --test grammar_replay cargo nextest run -p vllm-parser -p vllm-chat cargo clippy --workspace --all-targets --all-features -- -D warningsUnit tests snapshot the grammar for each start mode and tool choice with the shared outline renderer, with call bodies elided to
..(the argument tests cover them). Example: Reasoning plusrequired:Test Result
requirements/common.txtserves.auto: 130 tokens from insidethink, throughresponseandtools, then terminated.required: 124 tokens, withtoolsdirectly afterthink, which the removed builder rejected.vllm-parser+vllm-chat: 947 tests passed. Workspace Clippy and rustfmt passed.AI assistance: implementation and validation assisted by Claude Code.
🤖 Generated with Claude Code