Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
3677842f
Unverified
Commit
3677842f
authored
Sep 20, 2025
by
Devon Rifkin
Committed by
GitHub
Sep 20, 2025
Browse files
Merge pull request #12358 from ollama/drifkin/qwen3-coder-ampersands
parsers: fix `&`s in qwen3coder parameter values
parents
dba39b2e
242df70a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
87 additions
and
2 deletions
+87
-2
model/parsers/qwen3coder.go
model/parsers/qwen3coder.go
+39
-2
model/parsers/qwen3coder_test.go
model/parsers/qwen3coder_test.go
+48
-0
No files found.
model/parsers/qwen3coder.go
View file @
3677842f
...
...
@@ -393,18 +393,55 @@ func parseValue(raw string, paramType api.PropertyType) any {
return
raw
}
var
qwenTagRegex
=
regexp
.
MustCompile
(
`<(\w+)=([^>]+)>`
)
var
(
qwenTagRegex
=
regexp
.
MustCompile
(
`<(\w+)=([^>]+)>`
)
qwenXMLTagRegex
=
regexp
.
MustCompile
(
`</?(?:function|parameter)(?:\s+name="[^"]*")?>`
)
)
// transformToXML transforms a raw qwen tool call with xml-like tags into valid
// xml so that it can be parsed by any xml parser
func
transformToXML
(
raw
string
)
string
{
// take the form `<tag=abc>` and transform it to `<tag name="abc">`, taking
// care to properly escape the string that becomes the attribute value
return
qwenTagRegex
.
ReplaceAllStringFunc
(
raw
,
func
(
match
string
)
string
{
transformed
:=
qwenTagRegex
.
ReplaceAllStringFunc
(
raw
,
func
(
match
string
)
string
{
groups
:=
qwenTagRegex
.
FindStringSubmatch
(
match
)
tag
:=
groups
[
1
]
var
escapedValue
strings
.
Builder
xml
.
EscapeText
(
&
escapedValue
,
[]
byte
(
groups
[
2
]))
return
fmt
.
Sprintf
(
`<%s name="%s">`
,
tag
,
escapedValue
.
String
())
})
// Walk the resulting string, escaping any character data that sits between the
// xml tags we just emitted
var
out
strings
.
Builder
lastIdx
:=
0
for
_
,
loc
:=
range
qwenXMLTagRegex
.
FindAllStringIndex
(
transformed
,
-
1
)
{
if
loc
[
0
]
>
lastIdx
{
escapeTextNode
(
&
out
,
transformed
[
lastIdx
:
loc
[
0
]])
}
out
.
WriteString
(
transformed
[
loc
[
0
]
:
loc
[
1
]])
lastIdx
=
loc
[
1
]
}
if
lastIdx
<
len
(
transformed
)
{
escapeTextNode
(
&
out
,
transformed
[
lastIdx
:
])
}
return
out
.
String
()
}
// escapeTextNode escapes XML character data without altering other characters
// like newlines or tabs (which is why we don't use xml.EscapeText for this)
func
escapeTextNode
(
sb
*
strings
.
Builder
,
s
string
)
{
for
_
,
r
:=
range
s
{
switch
r
{
case
'&'
:
sb
.
WriteString
(
"&"
)
case
'<'
:
sb
.
WriteString
(
"<"
)
case
'>'
:
sb
.
WriteString
(
">"
)
default
:
sb
.
WriteRune
(
r
)
}
}
}
model/parsers/qwen3coder_test.go
View file @
3677842f
...
...
@@ -312,6 +312,41 @@ true
},
},
},
// regression test for <https://github.com/ollama/ollama/issues/12357>
{
name
:
"ampersands in parameter values"
,
tools
:
[]
api
.
Tool
{},
rawToolCall
:
`<function=exec>
<parameter=command>
ls && echo "done"
</parameter>
</function>`
,
wantToolCall
:
api
.
ToolCall
{
Function
:
api
.
ToolCallFunction
{
Name
:
"exec"
,
Arguments
:
map
[
string
]
any
{
"command"
:
"ls && echo
\"
done
\"
"
,
},
},
},
},
{
name
:
"angle brackets in parameter values"
,
tools
:
[]
api
.
Tool
{},
rawToolCall
:
`<function=exec>
<parameter=command>
ls && echo "a > b and a < b"
</parameter>
</function>`
,
wantToolCall
:
api
.
ToolCall
{
Function
:
api
.
ToolCallFunction
{
Name
:
"exec"
,
Arguments
:
map
[
string
]
any
{
"command"
:
"ls && echo
\"
a > b and a < b
\"
"
,
},
},
},
},
}
for
i
,
step
:=
range
steps
{
...
...
@@ -798,6 +833,19 @@ celsius
</parameter>
</function>`
,
},
{
desc
:
"ampersands in parameter values"
,
raw
:
`<function=get_current_temperature>
<parameter=location>
San Francisco & San Jose
</parameter>
</function>`
,
want
:
`<function name="get_current_temperature">
<parameter name="location">
San Francisco & San Jose
</parameter>
</function>`
,
},
}
for
_
,
tc
:=
range
cases
{
...
...
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