Repository navigation
feat: exclude control markers from Kimi-K3 tool-argument strings - #915
Merged
Seven-Streams merged 4 commits intoSep 21, 2026
Merged
Conversation
Signed-off-by: zhuhaoran <zhuhaoran.zhr@alibaba-inc.com>
This reverts commit d62c120. The change is re-applied in separate commits so that the FSM state-limit fix, the Unicode character class fix, the regular-grammar flattener, the excludes feature, and the Kimi-K3 wiring can be reviewed independently.
The Kimi-K3 builtin now supplies JSONSchemaFormat.excludes with <|open|>, <|close|>, and <|sep|> for every tool-argument schema in auto, required, and forced tool modes, so a control marker inside a raw string argument is rejected at the mask instead of being swallowed as text. The existing exclude_special_tokens=False option disables this filter; free-text reasoning/response exclusions keep their current scope. The builtin test that accepted a complete <|close|>response<|sep|> inside a string argument now expects rejection, and new tests cover the default exclusions and opt-out across the three tool-choice modes, raw and nested JSON strings, and complete valid argument/call endings. Also add the kimi_k3_xml style to the TypeScript JSONSchemaFormat type, which was missed when the style was introduced. Extracted from mlc-ai#901.
Seven-Streams
requested review from
CharlieFRuan and
Ubospica
as code owners
September 21, 2026 18:56
…ing rules Per mlc-ai#912, excludes apply to the string values without pattern/format and to property names; minLength/maxLength are dropped with a warning and const/enum alternatives containing an excluded substring are removed. Say so in the structural tag docs, the JSONSchemaFormat docstring and the Kimi-K3 builtin docstrings, which still claimed every string value.
Seven-Streams
force-pushed
the
split901/5-kimi-k3-excludes
branch
from
September 21, 2026 19:43
aa342e4 to
9274b9f
Compare
Open
3 of 5 tasks
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.
Extracted from #901 by @izhuhaoran, last piece after #906, #909, #910 and #912. The branch keeps the original commit and its revert at the bottom for attribution; the net diff against
mainis thefeat(kimi_k3): exclude control markers from tool-argument stringscommit plus a docs commit that states the exclusion rules of #912 as a list.What changes
The Kimi-K3 builtin now passes
excludes=["<|open|>", "<|cloase|>", "<|sep|>"]to theJSONSchemaFormatof every tool-argument schema, inauto,requiredand forced tool modes. A control marker inside a raw string argument is rejected at the mask instead of being swallowed as text, which is the original #901 bad case: the model emitted<|close|>response<|sep|>inside an openresponseargument and started another tools/call block. The existingexclude_special_tokens=Falseoption disables this together with the free-text exclusions; the free-text reasoning/response scope is unchanged.Per #912, the exclusions apply to argument strings without
pattern/formatand to property names, nested JSON strings included;minLength/maxLengthon such strings are dropped with a warning. Argument and call wrappers are outside the scope, so<|close|>argument<|sep|>still terminates a value.web/src/structural_tag.tsgains thekimi_k3_xmlmember of theJSONSchemaFormat.styleunion, missed when the style was introduced in #806.Validation
tests/python/test_builtin_structural_tag.py: the instance that accepted a complete<|close|>response<|sep|>inside a string argument now expects rejection (malformed-argument-end-in-string);test_kimi_k3_exclude_special_tokenschecks the three exclusions on every tool-argument schema across the three tool-choice modes and the opt-out;test_kimi_k3_tool_argument_exclusionscovers raw and nested JSON string values with and without the option, including complete valid argument and call endings.test_builtin_structural_tag,test_json_schema_excludes,test_structural_tag_converter: 1733 passed. The C++ tree is identical tomain. Fulltests/pythonwithHF_TOKEN: 4946 passed, 3 skipped; the only failures are the CUDA kernel tests that JIT-build a torch extension, which fail identically onmainin this environment (CUDA 11.1 toolkit).