[Rust Frontend] Fix Qwen parser auto-detection (#51169)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Sage Ahrac <sagiahrak@gmail.com>
This commit is contained in:
Sage
2026-08-20 09:39:05 +00:00
committed by GitHub
co-authored by mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Bugen Zhao
parent 30e2394c83
commit 727274a75b
4 changed files with 57 additions and 15 deletions
+2 -1
View File
@@ -85,7 +85,8 @@ impl ReasoningParserFactory {
.register_pattern("deepseek-v3", names::DEEPSEEK_V3)
.register_pattern("gemma-4", names::GEMMA4)
.register_pattern("gemma4", names::GEMMA4)
.register_pattern("qwen", names::QWEN3)
.register_pattern("qwq", names::DEEPSEEK_R1)
.register_pattern("qwen3", names::QWEN3)
.register_pattern("glm-5", names::GLM45)
.register_pattern("glm-4.7", names::GLM45)
.register_pattern("glm-4.6", names::GLM45)
@@ -37,6 +37,23 @@ fn factory_resolves_deepseek_v4_to_qwen3_alias() {
);
}
#[test]
fn factory_distinguishes_qwen_model_families() {
let factory = ReasoningParserFactory::new();
assert_eq!(
factory.resolve_name_for_model("Qwen/QwQ-32B"),
Some(names::DEEPSEEK_R1)
);
assert_eq!(
factory.resolve_name_for_model("Qwen/Qwen3-8B"),
Some(names::QWEN3)
);
assert_eq!(
factory.resolve_name_for_model("Qwen/Qwen2.5-0.5B-Instruct"),
None
);
}
#[test]
fn factory_routes_step3p5_models_to_dedicated_parser() {
let factory = ReasoningParserFactory::new();
+3 -2
View File
@@ -94,9 +94,10 @@ impl ToolParserFactory {
.register_pattern("mistral-", names::MISTRAL)
.register_pattern("mixtral-", names::MISTRAL)
.register_pattern("qwen3-coder", names::QWEN3_CODER)
.register_pattern("qwen2.5-coder", names::QWEN3_CODER)
.register_pattern("qwen3.5", names::QWEN3_CODER)
.register_pattern("qwen", names::QWEN3_XML)
.register_pattern("qwq", names::HERMES)
.register_pattern("qwen2.5", names::HERMES)
.register_pattern("qwen3", names::QWEN3_XML)
.register_pattern("hermes", names::HERMES)
.register_pattern("hy3", names::HY_V3)
.register_pattern("hy_v3", names::HY_V3)
+35 -12
View File
@@ -80,22 +80,45 @@ fn factory_creates_registered_parser_for_model() {
factory.create_for_model("my-fake-model-v1", &[]).unwrap();
}
#[test]
fn factory_distinguishes_qwen_tool_formats() {
let factory = ToolParserFactory::new();
for (model, expected) in [
("Qwen/Qwen3.5-0.8B", Some(names::QWEN3_CODER)),
("Qwen/Qwen3-0.6B", Some(names::QWEN3_XML)),
("Qwen/Qwen3-Coder-30B", Some(names::QWEN3_CODER)),
("Qwen/QwQ-32B", Some(names::HERMES)),
("Qwen/Qwen2.5-0.5B-Instruct", Some(names::HERMES)),
("Qwen/Qwen2-1.5B-Instruct", None),
] {
assert_eq!(factory.resolve_name_for_model(model), expected, "{model}");
}
}
#[test]
fn factory_parses_qwen2_5_coder_template_with_hermes() {
let factory = ToolParserFactory::new();
let tool_call = r#"<tool_call>
{"name":"get_weather","arguments":{"location":"Tokyo"}}
</tool_call>"#;
let mut parser = factory.create_for_model("Qwen/Qwen2.5-Coder-7B-Instruct", &[]).unwrap();
let mut output = ToolParserOutput::default();
parser.parse_into(tool_call, &mut output).unwrap();
output.append(parser.finish().unwrap());
let output = output.coalesce();
assert!(output.normal_text().is_empty());
assert_eq!(output.calls().len(), 1);
assert_eq!(output.calls()[0].name.as_deref(), Some("get_weather"));
assert_eq!(output.calls()[0].arguments, r#"{"location":"Tokyo"}"#);
}
#[test]
fn factory_new_resolves_default_patterns() {
let factory = ToolParserFactory::new();
assert_eq!(
factory.resolve_name_for_model("Qwen/Qwen3.5-0.8B"),
Some(names::QWEN3_CODER)
);
assert_eq!(
factory.resolve_name_for_model("Qwen/Qwen3-0.6B"),
Some(names::QWEN3_XML)
);
assert_eq!(
factory.resolve_name_for_model("Qwen/Qwen3-Coder-30B"),
Some(names::QWEN3_CODER)
);
assert_eq!(
factory.resolve_name_for_model("meta-llama-4-maverick"),
Some(names::LLAMA4_JSON)