chat : improve parsing of complex types in qwen3-coder (#28742)

* chat : improve schema support in qwen3 parser

* cont : clean up grammar a bit
This commit is contained in:
Aldehir Rojas
2026-09-12 19:08:52 -05:00
committed by GitHub
parent 8e330954ad
commit 790cf51aab
2 changed files with 87 additions and 3 deletions
+59
View File
@@ -846,6 +846,25 @@ static common_chat_tool nullable_int_tool{
})",
};
static common_chat_tool string_union_tool{
/* .name = */ "set_union",
/* .description = */ "Set values whose types are unions with string",
/* .parameters = */ R"({
"type": "object",
"properties": {
"value": {
"type": ["string", "object"],
"description": "A string or object value"
},
"amount": {
"type": ["string", "integer"],
"description": "A string or integer value"
}
},
"required": ["value", "amount"]
})",
};
static common_chat_tool enum_no_type_tool{
/* .name = */ "set_unit",
/* .description = */ "Set a temperature unit",
@@ -3805,6 +3824,46 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
})
.run();
// nullable string given null - parses as JSON null, not the string "null"
tst.test(
"<tool_call>\n"
"<function=set_nullable_str>\n"
"<parameter=name>\nnull\n</parameter>\n"
"</function>\n"
"</tool_call>")
.tools({ nullable_string_tool })
.expect_tool_calls({
{ "set_nullable_str", R"({"name": null})", {} },
})
.run();
// unions with string - JSON values of the other types are typed, everything else is a string
tst.test(
"<tool_call>\n"
"<function=set_union>\n"
"<parameter=value>\n{\"a\": 1}\n</parameter>\n"
"<parameter=amount>\n2 dollars\n</parameter>\n"
"</function>\n"
"</tool_call>")
.tools({ string_union_tool })
.expect_tool_calls({
{ "set_union", R"({"value": {"a": 1}, "amount": "2 dollars"})", {} },
})
.run();
tst.test(
"<tool_call>\n"
"<function=set_union>\n"
"<parameter=value>\n{not valid json\n</parameter>\n"
"<parameter=amount>\n42\n</parameter>\n"
"</function>\n"
"</tool_call>")
.tools({ string_union_tool })
.expect_tool_calls({
{ "set_union", R"({"value": "{not valid json", "amount": 42})", {} },
})
.run();
// enum without explicit type key - should infer string from enum values
tst.test(
"<tool_call>\n"