Skip to content

[TRTLLM-14814][feat] Kimi K3 serving parsers, chat template, and speculative decoding (suffix automaton + DFlash scaffold) - #17327

Merged
brnguyen2 merged 15 commits into
NVIDIA:mainfrom
brnguyen2:k3/14812-14814-serving-specdec
Aug 8, 2026
Merged

[TRTLLM-14814][feat] Kimi K3 serving parsers, chat template, and speculative decoding (suffix automaton + DFlash scaffold)#17327
brnguyen2 merged 15 commits into
NVIDIA:mainfrom
brnguyen2:k3/14812-14814-serving-specdec

Conversation

@brnguyen2

@brnguyen2 brnguyen2 commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Description

Stages the Kimi K3 serving and speculative-decoding layers on top of the model PR:

TRTLLM-14812 — reasoning parser, tool parser, chat template (ec71a9cc67): K3 reasoning parser, K3 tool parser + factory registration, OpenAI-server special-token decoding config for the parsers, and tokenizer-native chat-template dispatch, with unit tests for each.

TRTLLM-14814 — speculative decoding (174f9f6a37): suffix-automaton spec-dec for K3 with acceptance statistics, the DFlash draft-model scaffold (Markov-head helpers in modeling_speculative.py; the trained K3 DFlash draft checkpoint is still in progress and not required by this PR), KDA replay-cache seeding for generation-side restarts, and the TRTLLM-14706 graph-safe latent-cache append fix it depends on. Unit tests plus an SA logits-parity harness.

Base

Notes

  • Disaggregated-serving SA tests and config belong to TRTLLM-14815 and are not included.
  • No L0/QA test-list changes in this PR; list enablement follows once the new tests are green in a full pipeline.

Test Coverage

  • tests/unittest/llmapi/test_reasoning_parser.py
  • tests/unittest/apps/test_tool_parsers.py
  • tests/unittest/inputs/test_chat_template_dispatch.py
  • tests/unittest/_torch/speculative/hw_agnostic (new SA/DFlash unit files; auto-collected by the CPU/H100 stages)
  • tests/unittest/_torch/speculative/kimi_k3_sa_harness.py + test_kimi_k3_specdec.py (multi-GPU parity; list enablement deferred)

PR Checklist

Dev Engineer Review

  • Added Kimi K3 reasoning and XTML tool parsers.
  • Added parser-specific raw-token decoding and tokenizer-native chat-template dispatch.
  • Added DFlash and DSpark speculative-decoding support.
  • Added acceptance statistics, suffix-automaton initialization, KDA replay-cache seeding, and CUDA-graph-safe MLA latent-cache appending.
  • Added a four-GPU suffix-automaton logits-parity harness.
  • Internal validation passed 652 relevant unit tests and four-GPU logits parity.
  • GSM8K improved from 96.89 baseline to 97.19 with speculation.
  • Mean acceptance length matched the reference: 1.319 versus 1.318.
  • Serving separated reasoning_content correctly.
  • No test-list, QA, or waiver changes were included.
  • A scoped issue remains for named or forced tool_choice: raw model text can appear in tool_calls[0].arguments instead of extracted JSON arguments. Auto tool choice was not validated.

QA Engineer Review

  • Added unit tests for Kimi K3 reasoning and tool parsing, native chat-template dispatch, DFlash acceptance statistics, DSpark semantics, suffix-automaton initialization, and KDA replay-cache seeding.
  • Added integration tests for Kimi K3 speculative decoding and four-GPU logits parity:
    • test_kimi_k3_sa_specdec_logits_parity
    • test_kimi_k3_disagg_parity_selftest
  • The added test functions are not registered in tests/integration/test_lists/test-db/ or tests/integration/test_lists/qa/.
  • No test-list, test-db/, qa/, or waives.txt changes were included.
  • CI and manual-QA coverage require follow-up.
  • Verdict: needs follow-up.

@brnguyen2

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64149 [ run ] triggered by Bot. Commit: 174f9f6 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64149 [ run ] completed with state FAILURE. Commit: 174f9f6
/LLM/main/L0_MergeRequest_PR pipeline #52068 completed with status: 'FAILURE'

CI Report

⚠️ Multi-GPU Label Required:
Multi-GPU tests require the ci: full pre-merge approved label on this PR. Ask a member of NVIDIA/trt-llm-ci-approvers to add the label, then re-trigger CI with the same bot command (no rebase needed).

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@brnguyen2

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64252 [ run ] triggered by Bot. Commit: 8c6ea85 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64252 [ run ] completed with state FAILURE. Commit: 8c6ea85
/LLM/main/L0_MergeRequest_PR pipeline #52157 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@brnguyen2

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64342 [ run ] triggered by Bot. Commit: 877f3c1 Link to invocation

@brnguyen2

Copy link
Copy Markdown
Collaborator Author

Internal validation summary for this PR's SA and parser claims (full-size Kimi K3 checkpoint, Blackwell nodes, branch head 174f9f6 — before the latest test-scaffolding fix commit, which does not affect these paths):

  • Unit sweep over the PR's parser/specdec suites plus the K3 unit tests: 652 passed, 0 unexpected failures.
  • Suffix-automaton vs baseline logits-parity integration run (4 GPUs): PASS.
  • GSM8K on the full checkpoint: baseline 96.89 flex/strict; with suffix-automaton speculation 97.19 (at/above baseline), mean acceptance length 1.319 vs 1.318 reference across 1319 samples — no acceptance collapse.
  • Serving smoke: reasoning_content separation works end to end.

One scoped issue found, not blocking SA/parser correctness above: with a named/forced tool_choice, the server returns finish_reason=stop with the raw model text (preamble plus K3 tool markup) in tool_calls[0].arguments instead of the extracted JSON arguments. Auto tool_choice was not exercised. This is being tracked as a follow-up ticket against the K3 tool-parser forced-choice path.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64342 [ run ] completed with state SUCCESS. Commit: 877f3c1
/LLM/main/L0_MergeRequest_PR pipeline #52235 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@brnguyen2
brnguyen2 marked this pull request as ready for review August 6, 2026 23:56
@brnguyen2
brnguyen2 requested review from a team as code owners August 6, 2026 23:56
…k-decode path

The TRTLLM-14814 DSpark scaffold added a guard in
DFlashForCausalLM.__init__ rejecting any dflash_config with causal=true.
Legacy DFlash drafter configs (e.g. Laguna) also declare causal=true;
their causality is implemented by the legacy decode path
(_sliding_layers_causal in the Laguna subclass), so the unconditional
guard broke construction of pre-existing drafters
(TestLagunaXS_2_1::test_{bf16,fp8,nvfp4}_dflash).

Only reject causal=true when the config actually selects the dspark
convention: projector_type == 'dspark' or any dspark feature field
(shift_label, use_swa, markov_rank, use_confidence_head) enabled.

Add hw-agnostic unit tests: legacy causal config constructs; dspark +
causal (via feature flags or projector_type alone) still raises.

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
…follow-up PRs

test_kimi_k3_dflash_scaffold.py loaded
examples/kimi_k3/make_synthetic_dflash_drafter.py at module level, so on
branches without that generator (it ships with the examples PR) the whole
module failed at collection — taking down every unittest stage that
collects unittest/_torch/speculative/hw_agnostic (l0_cpu and the l0_h100
sampler/speculative stage). Load it conditionally and skip the
generator-schema tests when it is absent; the DFlashDecodingConfig,
KimiLinearModel, and DFlashSpecMetadata tests keep running.

test_kimi_k3_disagg_parity_selftest subprocess-runs
kimi_k3_disagg_parity.py, which ships with the disagg parity PR; skip the
self-test while the harness is absent.

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
…arsers

The new kimi_k3 reasoning parser and tool parser register into
ReasoningParserFactory / ToolParserFactory, which feed the trtllm-serve
--reasoning_parser / --tool_parser Click Choice lists pinned by
tests/unittest/api_stability/references/trtllm_serve_cli.yaml. Add
kimi_k3 to both recorded choice lists.

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
- kimi_k3_sa_harness.py: validate KIMI_K3_SPEC_PARITY values, check
  baseline/prompt-set length match, and guard baseline-side logprob
  alignment before indexing in _compare_logits_parity
- modeling_speculative.py: explicit slice | None annotation for
  vocab_slice (RUF013)
- test_dflash_accept_stats.py: catch ImportError instead of Exception
  in the torch-less fallback loader; use tmp_path instead of /tmp

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
…d KV managers

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
…TODO

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
…e graph-safe append

The clamp keeps padded/warmup rows in bounds but targets a real block 0;
TRTLLM-15199 tracks excluding invalid rows or reserving a scratch block.

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
…aceholders and K3 MoE backend pinning

- modeling_speculative.py: explain why the DSpark markov/confidence head
  attributes are plain None placeholders instead of pre-allocated
  parameters (checkpoint-dependent shapes, absent on most checkpoints).
- kimi_k3_sa_harness.py / test_kimi_k3_specdec.py: KimiK3MoERuntime pins
  the routed MoE backend to TRTLLM, so the KIMI_K3_MOE_BACKEND=VANILLA
  default was a no-op; drop it and correct the comments (parity is
  unaffected since baseline and spec runs share the same backend).

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
…rimental

The recorder is opt-in and DFlash/DSpark-specific; log a warning at
activation so enabling it with other speculative decoding methods is
visibly unsupported rather than silently recording nothing.

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
…rop chat-completions dependency note, mark SA speculation supported for aggregated serving

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
@brnguyen2
brnguyen2 force-pushed the k3/14812-14814-serving-specdec branch from 45f2312 to f9376ca Compare August 8, 2026 02:19
@brnguyen2
brnguyen2 requested a review from a team as a code owner August 8, 2026 02:19
@brnguyen2
brnguyen2 requested a review from nv-guomingz August 8, 2026 02:19
@brnguyen2

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64750 [ run ] triggered by Bot. Commit: f9376ca Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64735 [ run ] completed with state ABORTED. Commit: 45f2312

Link to invocation

@brnguyen2

Copy link
Copy Markdown
Collaborator Author

/bot skip --comment "Union-green across runs on this head and its immediate predecessor. Current run (pipeline 52600, commit f9376ca): SBSA single-GPU 28/28 green, A100X green, 214/218 x86 stages green; sole red is DGX_H100-PyTorch-5, which the test harness itself classified as transient infra (monitor lost contact with a live job: "this is not a test failure") - that stage passed on the previous head 45f2312 (pipeline 52568), whose only delta to this head is a rebase onto main plus a doc-only commit. 52568 additionally had all six DGX_H100 shards green; its single red (A100X NIXL test) is an intermittent failure that passed on a same-commit rerun elsewhere and is green on this run. DGX_H100-PyTorch-4 multimodal failures in 52600 were node-level CUDA errors (cudaErrorMapBufferObjectFailed) in a subsystem this PR does not touch and auto-retried green."

@brnguyen2

Copy link
Copy Markdown
Collaborator Author

/bot skip --comment "Re-issuing skip for the rebased head fac670d (content unchanged vs f9376ca, which this skip rationale was established for): union-green across pipeline 52600 (SBSA 28/28, A100X green, 214/218 x86 stages; sole red harness-classified as transient infra and green on the prior head) and pipeline 52568 (all six DGX_H100 shards green; single red an intermittent test that passed on a same-commit rerun and in 52600)."

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64762 [ skip ] triggered by Bot. Commit: fac670d Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64750 [ run ] completed with state ABORTED. Commit: f9376ca

Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64763 [ skip ] triggered by Bot. Commit: fac670d Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64762 [ skip ] completed with state ABORTED. Commit: fac670d

Link to invocation

@brnguyen2
brnguyen2 enabled auto-merge (squash) August 8, 2026 05:55
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64763 [ skip ] completed with state SUCCESS. Commit: fac670d
Skipping testing for commit fac670d

Link to invocation

@brnguyen2
brnguyen2 merged commit 937bacc into NVIDIA:main Aug 8, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-compatible Accepted LLM API contract change that is backwards-compatible

Projects

None yet

Development

Successfully merging this pull request may close these issues.