-
Notifications
You must be signed in to change notification settings - Fork 227
Add escaping of whitespaces in qwen3coder tool output #3691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0b9b92d
to
cca1f42
Compare
6b13486
to
8b7f8f6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds whitespace escaping functionality to the Qwen3Coder tool output parser and improves handling of improperly formatted tool calls that begin with <function=...>
tags instead of the expected <tool_call>
tags.
- Introduces an
escapeString
function to properly escape newlines in tool call arguments - Adds support for parsing tool calls that start with
<function=...>
directly (without<tool_call>
) - Updates test cases to reflect the new escaped output format and additional parsing scenarios
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
File | Description |
---|---|
qwen3coder_tool_parser.cpp | Implements whitespace escaping function and enhanced parsing logic for malformed tool calls |
qwen3coder_tool_parser.hpp | Adds <function= tag to special parsing start tags set |
qwen3coder_output_parser_test.cpp | Updates tests for escaped output and adds test for improper tag handling |
spelling-whitelist.txt | Removes specific line reference for test file spelling issues |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
this->lastProcessedPosition = pos + Qwen3CoderToolParser::TOOL_START_TAG.length(); | ||
this->currentState = State::InsideToolCall; | ||
this->toolCallPositions.begin.push(pos); | ||
// normally we expect <tool_call> tag but we observerd that sometimes model generates <function=...> directly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// normally we expect <tool_call> tag but we observerd that sometimes model generates <function=...> directly | |
// normally we expect <tool_call> tag but we observed that sometimes model generates <function=...> directly |
this->currentState = State::InsideToolCall; | ||
this->toolCallPositions.begin.push(posTool); | ||
} else { | ||
// found <function=...> first, we will assume <tool_call> is missing and we will add it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"we will add it" - do you inject "<tool_call>" somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
misleading comment - i will remove it.
} else if (posTool < posFunc) { | ||
// found <tool_call> first | ||
this->lastProcessedPosition = posTool + Qwen3CoderToolParser::TOOL_START_TAG.length(); | ||
this->currentState = State::InsideToolCall; | ||
this->toolCallPositions.begin.push(posTool); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it cover well cases when posTool == std::string::npos
or posFunc == std::string::npos
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then posTool != posFunc so we hit either else if
or else
Without escaping several multi turn scenarios in BFCL had problem parsing model response. While this escaping is shallow (does not differentiate at which level of JSON/array we are) it improves results, and we don't have for now examples of this being to eager with escaping.
Additionally:
-> treat improper begining of tool (
<function=...>
) as an additional start of tool section. Several issues in BFCL were due to improper model output (lack of<tool_call>
), but there were <function=...>
Ticket:CVS-174650