Skip to content

[Rust Frontend] Fix GLM-5.2 chat template rendering parity - #51426

Merged
BugenZhao merged 5 commits into
mainfrom
agent/rust-chat-template
Aug 18, 2026
Merged

BugenZhao merged 5 commits into
mainfrom
agent/rust-chat-template

Conversation

@WoosukKwon

@WoosukKwon WoosukKwon commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Purpose

Fix GLM-5.2 chat-template rendering and align Rust tool serialization with the Python frontend.

The MiniJinja 2.22 update from #51235 is now in main. Relative to current main, this PR:

  • upgrades MiniJinja and MiniJinja Contrib from 2.22 to 2.24;
  • adds a regression test for mid-chain dotted integer lookup such as values.0.name;
  • preserves the OpenAI/Python function-field order: name, description, parameters, then strict when present;
  • preserves Python field-presence semantics: an absent description serializes as null, a null parameters stays null, an absent strict is omitted, and strict: false is retained;
  • adds a real zai-org/GLM-5.2-FP8 render/parse roundtrip covering both reasoning-plus-content and mixed tool-call fixtures.

Version boundary

  • MiniJinja 2.18 rejects GLM-5.2's bundled template at a mid-chain dotted integer lookup with unexpected float, expected identifier or integer.
  • MiniJinja 2.22 accepts the real GLM-5.2 template and is sufficient for model correctness.
  • MiniJinja 2.24, with the existing preserve_order feature, also preserves Serde struct definition order during template iteration. This closes the strict Python prompt-parity gap while allowing the tool projection to remain typed and express field absence with Serde attributes.

Test Plan

cd rust

cargo nextest run -p vllm-chat roundtrip_glm52
cargo nextest run -p vllm-chat chat_template_preserves_openai_tool_field_order
cargo nextest run -p vllm-chat chat_template_preserves_python_optional_tool_fields
cargo nextest run -p vllm-chat 'renderer::hf::'

cargo fmt --all -- --check
cargo clippy -p vllm-chat --all-targets -- -D warnings
git diff --check

The GLM-5.2 roundtrip loads the real tokenizer and bundled chat template, renders fixed conversations, parses the assistant output, appends it to history, and renders the next turn.

Test Result

Red/green evidence:

  • MiniJinja 2.18: the real GLM-5.2 roundtrip fails during template compilation at chat:93.
  • MiniJinja 2.22: the real GLM-5.2 roundtrip passes.
  • MiniJinja 2.22 with the typed tool projection: the field-order regression test fails with description|name|parameters|.
  • MiniJinja 2.24 with the typed tool projection: the field-order test passes with name|description|parameters|.
  • The previous manual-map projection omits description when absent and fails the optional-field regression test.
  • The final typed projection passes the optional-field test with description=null, parameters=null, omitted absent strict, and retained strict=false.

Final validation:

  • roundtrip_glm52: passed on both reasoning-plus-content and mixed tool-call fixtures.
  • Focused field-order and field-presence tests: passed.
  • Hugging Face renderer suite: 76/76 passed.
  • cargo fmt, Clippy with warnings denied, and git diff --check: passed.
  • A real GLM-5.2 tool prompt rendered by Python and Rust matched exactly: 980 characters, 243 tokens, SHA-256 b3d3bfd8964d9bb3998d4e96a7e7c5d8adc36478e0dbdd4d26ecd3ef31acfd28.

AI assistance was used for source analysis, implementation, testing, and drafting this description. The submitter must review every changed line and validate the results before marking this PR ready for review.

BugenZhao and others added 2 commits August 7, 2026 17:08
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Woosuk Kwon <woosuk@inferact.ai>
@mergify mergify Bot added the rust label Aug 7, 2026
@mergify

mergify Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @WoosukKwon.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Aug 11, 2026
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Woosuk Kwon <woosuk@inferact.ai>
@WoosukKwon
WoosukKwon marked this pull request as ready for review August 18, 2026 01:02

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@WoosukKwon WoosukKwon added the ready ONLY add when PR is ready to merge/full CI is needed label Aug 18, 2026
@WoosukKwon

Copy link
Copy Markdown
Collaborator Author

/ci run

@mergify mergify Bot removed the needs-rebase label Aug 18, 2026
@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #84301 for commit fba49b03b23b.

@BugenZhao

Copy link
Copy Markdown
Member

@codex review

@WoosukKwon

Copy link
Copy Markdown
Collaborator Author

@codex review

This was written by Codex btw

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fba49b03b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rust/src/chat/src/renderer/hf/mod.rs Outdated
.map(|tool| {
let mut function = serde_json::Map::new();
function.insert("name".to_string(), JsonValue::String(tool.name.clone()));
if let Some(description) = &tool.description {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve null descriptions in template tools

When a tool omits its optional description, this branch drops description from the template context entirely. The Python frontend uses tool.model_dump() (vllm/renderers/online_renderer.py:180), while FunctionDefinition retains description=None and only removes absent strict/defer_loading (vllm/entrypoints/openai/engine/protocol.py:299-314), so Python supplies description: null. Templates that serialize tools or distinguish undefined from null—such as tool_chat_template_functiongemma.jinja:18—will therefore render different prompts and token sequences, whereas the previous typed serializer preserved null. Insert JsonValue::Null at this canonical position when description is None, while continuing to omit absent strict.

Useful? React with 👍 / 👎.

@BugenZhao

Copy link
Copy Markdown
Member

serializing the Rust tool structs changed the function-field order to description, name, parameters, while the OpenAI request and Python frontend preserve name, description, parameters

Good catch! It turns out the most recent release of minijinja v0.24 has resolved this issue (mitsuhiko/minijinja#920) so we can stick to structs. I'll push some more commits.

@BugenZhao

Copy link
Copy Markdown
Member

@codex review

This was written by Codex btw

My last @codex review was also sent by Codex 🤣

@chatgpt-codex-connector

Copy link
Copy Markdown

😄 Fair point—the latest @codex review request also came from Codex, so there’s no new human-requested action here.

No code changes, commit, or follow-up pull request were created.

View task →

Signed-off-by: Bugen Zhao <i@bugenzhao.com>
@BugenZhao

Copy link
Copy Markdown
Member

/ci run

@BugenZhao
BugenZhao enabled auto-merge (squash) August 18, 2026 02:56
@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #84316 for commit fd7b1785eba3.

@BugenZhao
BugenZhao merged commit e0e5a7f into main Aug 18, 2026
30 checks passed
@BugenZhao
BugenZhao deleted the agent/rust-chat-template branch August 18, 2026 03:16
zufangzhu pushed a commit to zufangzhu/vllm that referenced this pull request Aug 24, 2026
…ect#51426)

Co-authored-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Woosuk Kwon <woosuk@inferact.ai>
Signed-off-by: Zhu, Zufang <zufang.zhu@intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready ONLY add when PR is ready to merge/full CI is needed rust

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants