Repository navigation
fix(parsers): DeepSeek V4.1 grammar and recovery - #493
Merged
Merged
Conversation
|
📊 Parser conformance viewer validated — view in CI summary |
keivenchang
marked this pull request as ready for review
October 28, 2026 05:16
luckyq
approved these changes
Oct 28, 2026
luckyq
left a comment
Contributor
There was a problem hiding this comment.
Summary: Adds the DeepSeek V4.1 spaced-DSML structural-tag grammar (deepseek_v4_1_xml) via a private V4/V41 dialect enum and makes the V4.1 unified parser recover later valid calls after a malformed invocation; no blocking or non-blocking findings at head 20ee48bff2f4.
Checked (diff read + code trace at 20ee48bff2f4; tests not run locally)
- V4 dialect constants (
BLOCK_START/BLOCK_END/INVOKE_START_PREFIX/INVOKE_END/BLOCK_SEPARATOR,BARE_INVOKE_BEGINvia constsplit_at) reproduce the previous literals exactly → V4 grammar output unchanged; toolchain pin 1.96.1 covers constsplit_at. tool_call_excludes()[1..]ordering consistent across both dialects; generic consumers (build_text_exclusion,reasoning_content) use the full slice.JsonSchemaStyle::DeepseekV41Xmlserializes asdeepseek_v4_1_xml, accepted by upstream XGrammar (structural_tag.pyLiteral,cpp/structural_tag.cc); no wire→native conversion, so the missing V41 variant indynamo-structural-tagis unreachable.structural_tag_builder_for_family("deepseek_v41")falls through tounified_only_builder.- Invoke-boundary
InvalidParameter { scan_from }: closes at firstINVOKE_END,next_scan_startadvances on a char boundary, ParameterHeader/ParameterValue flush paths still usemalformed_end; no infinite loop or quadratic rescan. - Scanner deferred-error path (
parse_complete_invoke,finish_ordered_into,uncommitted_block): keeps the first error, does not advancenext_index, surfaces at finish if unrecovered; guided-JSON rejection test covers the promised-JSON path. - Legacy
deepseek_v4ToolParser defers only for spaced V4.1 invokes (dsml.rs:428); V4 invokes unchanged. - 0.8.4 capture diff: provenance metadata for all 276 records + the one intended semantic change (
gpt_oss_invalid_tool_body_then_empty_callnow emitsget_weather). - Behavioral note, by design and tested: non-EOF malformed V4.1 invocations now error at
finish()instead of on the closing push, so text after an unrecovered malformed block streams before the error.
This was referenced Oct 28, 2026
keivenchang
force-pushed
the
keivenchang/DIS-3280__deepseek-v41-grammar
branch
from
October 28, 2026 19:40
20ee48b to
d7cebdf
Compare
4 tasks done
keivenchang
changed the base branch from
main
to
keivenchang/DIS-3115__capture-ci-fix
October 28, 2026 21:27
keivenchang
force-pushed
the
keivenchang/DIS-3280__deepseek-v41-grammar
branch
from
October 28, 2026 21:38
d7cebdf to
dce2993
Compare
1 task done
Signed-off-by: Keiven Chang <keivenchang@users.noreply.github.com>
…ations Signed-off-by: Keiven Chang <keivenchang@users.noreply.github.com>
Signed-off-by: Keiven Chang <keivenchang@users.noreply.github.com>
Signed-off-by: Keiven Chang <keivenchang@users.noreply.github.com>
Signed-off-by: Keiven Chang <keivenchang@users.noreply.github.com>
Signed-off-by: Keiven Chang <keivenchang@users.noreply.github.com>
Signed-off-by: Keiven Chang <keivenchang@users.noreply.github.com>
Signed-off-by: Keiven Chang <keivenchang@users.noreply.github.com>
keivenchang
force-pushed
the
keivenchang/DIS-3280__deepseek-v41-grammar
branch
from
October 29, 2026 00:35
dce2993 to
e3aa4dc
Compare
Contributor
Author
|
Replying to #493 (review): Thanks for checking the V4/V4.1 grammar split and malformed-invocation recovery. Final head |
This was referenced Nov 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Adds DeepSeek V4.1 grammar construction and malformed-call recovery and preserves V4 grammar output. Shared native/guided argument handling also preserves raw JSON numbers with default Serde scalar compatibility.
Details
DeepSeekDsmlFormatthrough a private dialect selector, parser-owned marker constants and matching XGrammar argument styles. V4.1 uses the unified-only builder lookup; the family selector remains the only public dialect choice.Example (before -> after)
Before:

After:

Verification
Rebased onto
mainafter PR #501 merged at00df0c5f6a039dd2d6622efb0216445b8a7ca527.At
e3aa4dceac6f03840203bb280a3fc82e2e0f1ae0(tree055bc04c77e4f8dc29cd5a13d8f75f4378b7eda8), the parser suite passed 1,091 tests, the opt-in numeric matrix passed 10, and the full conformance package passed 117. Formatting and both Clippy checks passed. The two default-ignored structural-tag tests were executed separately with XGrammar 0.2.8: 234 Harmony and 138 XML/DSML cases passed. The PR-specific corpus passed 352 acceptance/rejection samples across 54 grammars, including forced cross-dialect rejection and wrong-style negative controls. One pre-existing unrelated GLM optional verifier remains ignored. Python capture-capability tests passed 14 cases.Final-revision receipts compared 3,345 recorded cases with zero differences. Native and rendered GOLDEN comparisons each checked 3,525 cases and retained 2 nonblocking differences. All three nonempty receipts match this commit and tree; the strict reporter also rejected six missing/empty/stale/severity/mismatch mutations.
Recovery coverage includes malformed bodies, invalid JSON/headers, duplicate parameters, same/subsequent blocks, None/Response/Reasoning entry states, native/guided routing, every UTF-8 split, output before finish, EOF errors, reset/reuse and legacy projection. Numeric coverage includes large integers/fractions, underflow/overflow, embedded closing markers, native Kimi2/Kimi3/Muse/GLM, named/required guided calls, all three policies and immediate trailing text. Capture production and rendering share indexed raw assembly, with sparse/out-of-order call and malformed-value regressions.
Refreshed all 276 existing DeepSeek V4.1 latest cases from qualified unreleased source
0.8.7+source.3c17eddcb31b168332f580c8b61744d66e94816776cfb117d77ebe2e8685013f, with zero parser errors. The captured parser and collector source is public ancestor3094cb2655dd95b407dbcb34fa66fa61ef81424a; all 261 complete call arguments exactly match raw deltas. The other 801 YAML files, authored inputs and GOLDEN expectations are unchanged. The two retained Kimi K3 GOLDEN warnings remain existing exceptions.Regenerated the latest report with
conformance-publish --root . --output <output> --revision e3aa4dceac6f03840203bb280a3fc82e2e0f1ae0 --candidate-tree 055bc04c77e4f8dc29cd5a13d8f75f4378b7eda8 --cache-dir <cache>, copied it toconformance/CONFORMANCE_v2.html, and verified generated/canonical/HTTP byte equality in real Chromium. The report displays 2,796 cells and 0.8.7; grouped DS4.15-malformed_json_then_two_valid_callsshows Matches golden. Rendered HTML stays local. Backend support for the emitted XGrammar style requires separate deployment qualification. Hosted CI run 40795017708 passed on this exact public head and matching mirror: all 22 validation jobs succeeded, with Pages deployment skipped for the PR. DCO, PR-title validation and release preview also passed.Review scope and follow-up
I’ll address P0/P1 findings in this PR. Let’s handle P2/P3 in follow-up PRs, tracked in DIS-3280. For AI reviewers, report reproducible P0/P1 findings here; record P2/P3 as follow-up work without requesting changes for them on this PR.
Parser release, the dependent Dynamo integration and deployment backend qualification remain follow-up work under that ticket.
Public Dynamo integration is tracked in ai-dynamo/dynamo#17254. Remaining work: release this library change, update Dynamo's dependency, expose grammar availability separately from parser availability, and add Dynamo regression coverage.
Where should the reviewer start?
parsers/v2/src/structural_tag/builders/deepseek_dsml.rs,parsers/v2/src/structural_tag/builders/mod.rs,parsers/v2/tests/deepseek_structural_tag.rs,parsers/v2/src/unified/deepseek_v41.rs,parsers/v2/src/tool_calling/scan.rsDependent Dynamo integration
Draft Dynamo #17541 implements the capability/preflight APIs and Dynamo regressions tracked in Dynamo #17254. It remains DO NOT REVIEW until this change is released; the development Git pin must then become a published crates.io version before merge.