Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenDAS
dynamo
Commits
0ba80f6a
Unverified
Commit
0ba80f6a
authored
Apr 06, 2026
by
Neal Vaidya
Committed by
GitHub
Apr 06, 2026
Browse files
fix: Handle anyOf/oneOf parameter schemas in Qwen3Coder tool parser (#7847)
Signed-off-by:
Neal Vaidya
<
nealv@nvidia.com
>
parent
6e0d62d7
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
71 additions
and
5 deletions
+71
-5
lib/parsers/src/tool_calling/xml/parser.rs
lib/parsers/src/tool_calling/xml/parser.rs
+71
-5
No files found.
lib/parsers/src/tool_calling/xml/parser.rs
View file @
0ba80f6a
...
@@ -341,13 +341,25 @@ fn convert_param_value(
...
@@ -341,13 +341,25 @@ fn convert_param_value(
return
Value
::
String
(
param_value
);
return
Value
::
String
(
param_value
);
}
}
// Get the type from schema
// Get the type from schema.
let
param_type
=
param_config
// If a parameter uses "anyOf"/"oneOf" instead of a direct "type", there is no
.get
(
param_name
)
// top-level "type" key. Treat it as "object" so the value goes through JSON
// parsing rather than being returned as a double-encoded string.
let
param_schema
=
param_config
.get
(
param_name
);
let
param_type
=
param_schema
.and_then
(|
v
|
v
.get
(
"type"
))
.and_then
(|
v
|
v
.get
(
"type"
))
.and_then
(|
t
|
t
.as_str
())
.and_then
(|
t
|
t
.as_str
())
.unwrap_or
(
"string"
)
.map
(|
t
|
t
.to_lowercase
())
.to_lowercase
();
.unwrap_or_else
(||
{
if
param_schema
.map
(|
v
|
v
.get
(
"anyOf"
)
.is_some
()
||
v
.get
(
"oneOf"
)
.is_some
())
.unwrap_or
(
false
)
{
"object"
.to_string
()
}
else
{
"string"
.to_string
()
}
});
// The follow `match` block follows this rough pattern for each block:
// The follow `match` block follows this rough pattern for each block:
// 1. Match `param_type` against predefined string representations of each type,
// 1. Match `param_type` against predefined string representations of each type,
...
@@ -924,6 +936,60 @@ rust programming
...
@@ -924,6 +936,60 @@ rust programming
assert_eq!
(
args
[
"bool_param"
],
false
);
assert_eq!
(
args
[
"bool_param"
],
false
);
}
}
#[test]
fn
test_anyof_param_parsed_as_object_not_string
()
{
// When a tool parameter uses "anyOf" instead of a direct "type", the value
// should be JSON-parsed (treated as object), not double-encoded as a string.
// Regression test for: https://github.com/vllm-project/vllm/pull/36032
let
tools
=
vec!
[
ToolDefinition
{
name
:
"get_weather"
.to_string
(),
parameters
:
Some
(
serde_json
::
json!
({
"type"
:
"object"
,
"required"
:
[
"location"
],
"properties"
:
{
"location"
:
{
"anyOf"
:
[
{
"type"
:
"object"
,
"properties"
:
{
"city"
:
{
"type"
:
"string"
}},
"required"
:
[
"city"
]
},
{
"type"
:
"object"
,
"properties"
:
{
"lat"
:
{
"type"
:
"number"
},
"lon"
:
{
"type"
:
"number"
}
},
"required"
:
[
"lat"
,
"lon"
]
}
]
}
}
})),
}];
let
input
=
r#"<tool_call>
<function=get_weather>
<parameter=location>
{"city": "Paris"}
</parameter>
</function>
</tool_call>"#
;
let
(
calls
,
_
)
=
try_tool_call_parse_xml
(
input
,
&
XmlParserConfig
::
default
(),
Some
(
&
tools
))
.unwrap
();
assert_eq!
(
calls
.len
(),
1
);
let
args
:
serde_json
::
Value
=
serde_json
::
from_str
(
&
calls
[
0
]
.function.arguments
)
.unwrap
();
// Must be a proper object, not a double-encoded string like "{\"city\": \"Paris\"}"
assert
!
(
args
[
"location"
]
.is_object
(),
"Expected location to be an object, got: {}"
,
args
[
"location"
]
);
assert_eq!
(
args
[
"location"
][
"city"
],
"Paris"
);
}
#[test]
#[test]
fn
test_no_schema_fallback_behavior
()
{
fn
test_no_schema_fallback_behavior
()
{
// Without schema, behavior should match old safe_parse_value logic
// Without schema, behavior should match old safe_parse_value logic
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment