[Rust Frontend] Upgrade MiniJinja to 2.22 & remove method lookup workaround (#51235)
Signed-off-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Bugen Zhao committed
Aug 11, 2026 at 10:23 UTC
d8c70f22434afcbd6644aa43d3f23aecb6e5a09f
5 files changed
+12
-98
rust/Cargo.lock
+4
-5
@@ -2402,9 +2402,9 @@ dependencies = [
2402
2403
[[package]]
2404
name = "minijinja"
2405
-version = "2.18.0"
2405
+version = "2.22.0"
2406
source = "registry+https://github.com/rust-lang/crates.io-index"
2407
-checksum = "328251e58ad8e415be6198888fc207502727dc77945806421ab34f35bf012e7d"
2407
+checksum = "ef84a52be188a1d4124bd717903fdde96ca4705f2b56adfe2d91fcc57fcb6987"
2408
dependencies = [
2409
"indexmap 2.13.0",
2410
"memo-map",
@@ -2414,9 +2414,9 @@ dependencies = [
2414
2415
[[package]]
2416
name = "minijinja-contrib"
2417
-version = "2.18.0"
2417
+version = "2.22.0"
2418
source = "registry+https://github.com/rust-lang/crates.io-index"
2419
-checksum = "8c6302e47d2b51f9fc978268ff7f5a014de5caa2ad48440309fd10ee711480d7"
2419
+checksum = "fd6e279dc925840c2d9ebc1e9f85410611d01292561297463ba3e516c3ad94dd"
2420
dependencies = [
2421
"minijinja",
2422
"serde",
@@ -5520,7 +5520,6 @@ dependencies = [
5520
"expect-test",
5521
"futures",
5522
"half",
5523
- "indexmap 2.13.0",
5523
"itertools 0.14.0",
5524
"llm-multimodal",
5525
"minijinja",
rust/Cargo.toml
+2
-2
@@ -61,8 +61,8 @@ itertools = "0.14.0"
61
libc = "0.2.177"
62
llm-multimodal = { git = "https://github.com/smg-project/llm-multimodal", rev = "15adba5e025d8636ba4a334fb379b1371f6196a1", default-features = false, features = ["native-tls"] }
63
mimalloc = "0.1.52"
64
-minijinja = { version = "2.0", features = ["unstable_machinery", "json", "builtins", "loader", "loop_controls", "preserve_order"] }
65
-minijinja-contrib = { version = "2.0", features = ["pycompat"] }
64
+minijinja = { version = "2.22", features = ["unstable_machinery", "json", "builtins", "loader", "loop_controls", "preserve_order"] }
65
+minijinja-contrib = { version = "2.22", features = ["pycompat"] }
66
native-tls-vendored = { package = "native-tls", version = "0.2.18", features = ["vendored"] }
67
ndarray = { version = "0.17", features = ["serde"] }
68
openai-harmony = { package = "oss-harmony", git = "https://github.com/oss-harmony/harmony", tag = "v0.0.11", default-features = false }
rust/src/chat/Cargo.toml
-1
@@ -10,7 +10,6 @@ asynk-strim-attr.workspace = true
10
easy-ext.workspace = true
11
futures.workspace = true
12
half.workspace = true
13
-indexmap.workspace = true
13
itertools.workspace = true
14
llm-multimodal.workspace = true
15
minijinja.workspace = true
rust/src/chat/src/renderer/hf/mod.rs
+6
-10
@@ -16,7 +16,6 @@ use self::format::{
16
ChatTemplateContentFormat, ChatTemplateContentFormatOption as ContentFormatOption,
17
};
18
use self::template::{CompiledChatTemplate, TemplateContext};
19
-use self::value::{TemplateValue, to_template_value};
19
use super::{ChatRenderer, RenderedPrompt, effective_template_kwargs};
20
use crate::error::Result;
21
use crate::request::{ChatContent, ChatContentPart, ChatMessage, ChatRequest};
@@ -28,7 +27,6 @@ mod error;
27
mod format;
28
mod template;
29
mod tojson;
31
-mod value;
30
31
pub use template::{load_chat_template, resolve_chat_template};
32
@@ -277,7 +275,7 @@ struct TemplateToolCall {
275
#[derive(Debug, Serialize)]
276
struct TemplateToolFunction {
277
name: String,
280
- arguments: TemplateValue,
278
+ arguments: JsonValue,
279
}
280
281
#[derive(Debug, Serialize)]
@@ -291,7 +289,7 @@ pub(super) struct TemplateTool {
289
struct TemplateToolDefinition {
290
name: String,
291
description: Option<String>,
294
- parameters: TemplateValue,
292
+ parameters: JsonValue,
293
strict: Option<bool>,
294
}
295
@@ -384,8 +382,6 @@ fn to_template_tool_calls(
382
error.as_report()
383
))
384
})?;
387
- let arguments = to_template_value(arguments);
388
-
385
tool_calls.push(TemplateToolCall {
386
id: tool_call.id.clone(),
387
r#type: "function",
@@ -564,7 +560,7 @@ fn to_template_tools(tools: &[ChatTool]) -> Vec<TemplateTool> {
560
function: TemplateToolDefinition {
561
name: tool.name.clone(),
562
description: tool.description.clone(),
567
- parameters: to_template_value(tool.parameters.clone()),
563
+ parameters: tool.parameters.clone(),
564
strict: tool.strict,
565
},
566
})
@@ -1008,7 +1004,7 @@ mod tests {
1004
.apply_chat_template(&request)
1005
.unwrap();
1006
1011
- assert_eq!(rendered.prompt, Prompt::Text("<bos>|true".to_string()));
1007
+ assert_eq!(rendered.prompt, Prompt::Text("<bos>|True".to_string()));
1008
}
1009
1010
#[test]
@@ -1093,7 +1089,7 @@ mod tests {
1089
1090
let rendered = renderer.render(&request).unwrap().prompt;
1091
1096
- assert_eq!(rendered, Prompt::Text("true|x".to_string()));
1092
+ assert_eq!(rendered, Prompt::Text("True|x".to_string()));
1093
}
1094
1095
#[test]
@@ -1146,7 +1142,7 @@ mod tests {
1142
1143
let rendered = renderer.render(&request).unwrap();
1144
1149
- assert_eq!(rendered.prompt, Prompt::Text("none|true".to_string()));
1145
+ assert_eq!(rendered.prompt, Prompt::Text("none|True".to_string()));
1146
assert_eq!(
1147
rendered.effective_template_kwargs.get("reasoning_effort"),
1148
Some(&Value::String("none".to_string()))
rust/src/chat/src/renderer/hf/value.rs
deleted
-80
@@ -1,80 +0,0 @@
1
-// SPDX-License-Identifier: Apache-2.0
2
-// SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
-
4
-use std::sync::Arc;
5
-
6
-use indexmap::IndexMap;
7
-use minijinja::value::{Enumerator, Object, ObjectExt, ObjectRepr};
8
-use minijinja::{Error as TemplateError, ErrorKind as TemplateErrorKind, State};
9
-use serde::Serialize;
10
-use serde_json::Value as JsonValue;
11
-
12
-/// A wrapper around `minijinja::Value` that can be constructed with `to_template_value` and used
13
-/// as a value in the chat template.
14
-#[derive(Debug, Serialize)]
15
-#[serde(transparent)]
16
-pub(super) struct TemplateValue(minijinja::Value);
17
-
18
-pub(super) fn to_template_value(value: JsonValue) -> TemplateValue {
19
- TemplateValue(match value {
20
- JsonValue::Array(values) => values
21
- .into_iter()
22
- .map(to_template_value)
23
- .map(|value| value.0)
24
- .collect::<minijinja::Value>(),
25
- JsonValue::Object(values) => minijinja::Value::from_object(TemplateMap(
26
- values
27
- .into_iter()
28
- .map(|(key, value)| (key, to_template_value(value).0))
29
- .collect(),
30
- )),
31
- // For primitive values, directly convert them to `minijinja::Value` using `from_serialize`.
32
- value => minijinja::Value::from_serialize(value),
33
- })
34
-}
35
-
36
-/// A custom map type that always returns `UnknownMethod` for method calls, so that pycompat can
37
-/// always handle dict methods through the unknown-method callback.
38
-///
39
-/// Use `IndexMap` to preserve the original key order when iterating.
40
-///
41
-/// MiniJinja's default map can resolve a same-named field before Python dict methods. HF templates
42
-/// commonly call `dict.items()`, which would fail if the map had an `items` field.
43
-/// See issue: https://github.com/mitsuhiko/minijinja/issues/903
44
-#[derive(Debug)]
45
-struct TemplateMap(IndexMap<String, minijinja::Value>);
46
-
47
-impl Object for TemplateMap {
48
- fn repr(self: &Arc<Self>) -> ObjectRepr {
49
- ObjectRepr::Map
50
- }
51
-
52
- fn get_value(self: &Arc<Self>, key: &minijinja::Value) -> Option<minijinja::Value> {
53
- self.0.get(key.as_str()?).cloned()
54
- }
55
-
56
- fn get_value_by_str(self: &Arc<Self>, key: &str) -> Option<minijinja::Value> {
57
- self.0.get(key).cloned()
58
- }
59
-
60
- fn enumerate(self: &Arc<Self>) -> Enumerator {
61
- self.mapped_rev_enumerator(|this| {
62
- Box::new(this.0.keys().map(|key| minijinja::Value::from(key.as_str())))
63
- })
64
- }
65
-
66
- fn enumerator_len(self: &Arc<Self>) -> Option<usize> {
67
- Some(self.0.len())
68
- }
69
-
70
- fn call_method(
71
- self: &Arc<Self>,
72
- _state: &State<'_, '_>,
73
- _method: &str,
74
- _args: &[minijinja::Value],
75
- ) -> std::result::Result<minijinja::Value, TemplateError> {
76
- // Always return `UnknownMethod` for method calls,
77
- // so that pycompat can handle dict methods through the unknown-method callback.
78
- Err(TemplateError::from(TemplateErrorKind::UnknownMethod))
79
- }
80
-}