[Rust Frontend] Fix macro-based content format detection (#49042)

Signed-off-by: reidliu41 <reid201711@gmail.com>

Reid committed Jul 20, 2026 at 17:39 UTC 818cf61e9149c3fdff302cddbb2d026090160aea
2 files changed +34 -3
rust/src/chat/src/renderer/hf/format.rs
+14 -3
@@ -236,9 +236,10 @@ fn has_content_item_loop(root: &Stmt<'_>) -> bool {
236
237 loops.into_iter().any(|loop_ast| {
238 matches!(loop_ast.target, Expr::Var(_))
239 - && message_varnames
240 - .iter()
241 - .any(|varname| is_var_or_elems_access(&loop_ast.iter, varname, Some("content")))
239 + && (is_var_access(&loop_ast.iter, "content")
240 + || message_varnames.iter().any(|varname| {
241 + is_var_or_elems_access(&loop_ast.iter, varname, Some("content"))
242 + }))
243 })
244 }
245
@@ -315,6 +316,16 @@ mod tests {
316 );
317 }
318
319 + #[test]
320 + fn detects_openai_template_with_content_parameter_loop() {
321 + assert_eq!(
322 + detect(
323 + "{% macro render(content) %}{% for item in content %}{{ item }}{% endfor %}{% endmacro %}{% for message in messages %}{{ render(message.content) }}{% endfor %}"
324 + ),
325 + ChatTemplateContentFormat::OpenAi
326 + );
327 + }
328 +
329 #[test]
330 fn detects_openai_template_with_messages_alias() {
331 assert_eq!(
rust/src/chat/src/renderer/hf/mod.rs
+20
@@ -1309,6 +1309,26 @@ mod tests {
1309 .assert_eq(&rendered);
1310 }
1311
1312 + #[test]
1313 + fn qwen35_template_auto_detects_openai_multimodal_content() {
1314 + let mut request = image_request();
1315 + request.chat_options.generation_prompt_mode = GenerationPromptMode::NoGenerationPrompt;
1316 +
1317 + let rendered = render_mm(
1318 + QWEN3_5_0_8B_TEMPLATE,
1319 + &request,
1320 + ChatTemplateContentFormatOption::Auto,
1321 + )
1322 + .unwrap();
1323 +
1324 + expect![[r#"
1325 + Text(
1326 + "<|im_start|>user\na<|vision_start|><|image_pad|><|vision_end|>b<|im_end|>\n",
1327 + )
1328 + "#]]
1329 + .assert_debug_eq(&rendered.prompt);
1330 + }
1331 +
1332 #[test]
1333 fn qwen35_template_renders_closed_empty_reasoning_span_when_thinking_disabled() {
1334 let mut request = sample_request(vec![ChatMessage::text(ChatRole::User, "hello")]);