You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(tools): recover Qwen calls without losing ordinary text - #2055
Some Qwen replies omit the outer <tool_call> wrapper. Recover the inner function blocks only when they make up the entire reply and refer to declared tools with valid required arguments.
The existing streaming suppressor cannot safely handle that recovery: seeing <function= is not enough to decide whether it is a call or a code example. Buffer ambiguous syntax until parsing finishes, then emit either tool calls or the original text. Apply the same behavior to OpenAI and Anthropic responses.
Also preserve rejected wrapped calls as text, reject duplicate or malformed parameters, and restore nullable/union JSON types without accepting the wrong top-level type. This is not a full JSON Schema validator. Invalid non-string required entries return 400 before generation.
Validation
env -u OMP_NUM_THREADS make -C c -j4 check: clean portable CPU build and C tests passed; initial Python suite passed.
After the last schema regression was added, env -u OMP_NUM_THREADS make -C c test-python: 2,411 tests ran, 305 skipped, no failures.
python3 -m unittest -v tests.test_qwen_tool_validation: all 10 tests passed. Includes real HTTP handlers with deterministic chunked engine output, OpenAI/Anthropic, streaming/non-streaming, valid calls, rejected calls, code examples, and malformed schemas.
Qwen template tests with Jinja installed: all 9 passed.
Apple Silicon/macOS, upstream dev 88f25a60. No pretrained-model quality, GPU, or performance claim.
Compatibility
No new CPU dependencies.
No models, binaries, or generated artifacts included.
Related: #1794 introduced Qwen tool support. #1995 addresses a separate falsey top-level tools validation issue; this PR does not replace that change.
Some Qwen replies omit the outer <tool_call> wrapper. Recover the inner function blocks only when they make up the entire reply and refer to declared tools with valid required arguments.
The existing streaming suppressor cannot safely handle that recovery: seeing <function= is not enough to decide whether it is a call or a code example. Buffer ambiguous syntax until parsing finishes, then emit either tool calls or the original text. Apply the same behavior to OpenAI and Anthropic responses.
Also preserve rejected wrapped calls as text, reject duplicate or malformed parameters, and restore nullable/union JSON types without accepting the wrong top-level type. This is not a full JSON Schema validator. Invalid non-string required entries return 400 before generation.
Validation
env -u OMP_NUM_THREADS make -C c -j4 check: clean portable CPU build and C tests passed; initial Python suite passed.
After the last schema regression was added, env -u OMP_NUM_THREADS make -C c test-python: 2,411 tests ran, 305 skipped, no failures.
python3 -m unittest -v tests.test_qwen_tool_validation: all 10 tests passed. Includes real HTTP handlers with deterministic chunked engine output, OpenAI/Anthropic, streaming/non-streaming, valid calls, rejected calls, code examples, and malformed schemas.
Qwen template tests with Jinja installed: all 9 passed.
Apple Silicon/macOS, upstream dev 88f25a60. No pretrained-model quality, GPU, or performance claim.
Compatibility
No new CPU dependencies.
No models, binaries, or generated artifacts included.
Related: #1794 introduced Qwen tool support. #1995 addresses a separate falsey top-level tools validation issue; this PR does not replace that change.
Some Qwen replies omit the outer <tool_call> wrapper. Recover the inner function blocks only when they make up the entire reply and refer to declared tools with valid required arguments.
The existing streaming suppressor cannot safely handle that recovery: seeing <function= is not enough to decide whether it is a call or a code example. Buffer ambiguous syntax until parsing finishes, then emit either tool calls or the original text. Apply the same behavior to OpenAI and Anthropic responses.
Also preserve rejected wrapped calls as text, reject duplicate or malformed parameters, and restore nullable/union JSON types without accepting the wrong top-level type. This is not a full JSON Schema validator. Invalid non-string required entries return 400 before generation.
Validation
env -u OMP_NUM_THREADS make -C c -j4 check: clean portable CPU build and C tests passed; initial Python suite passed.
After the last schema regression was added, env -u OMP_NUM_THREADS make -C c test-python: 2,411 tests ran, 305 skipped, no failures.
python3 -m unittest -v tests.test_qwen_tool_validation: all 10 tests passed. Includes real HTTP handlers with deterministic chunked engine output, OpenAI/Anthropic, streaming/non-streaming, valid calls, rejected calls, code examples, and malformed schemas.
Qwen template tests with Jinja installed: all 9 passed.
Apple Silicon/macOS, upstream dev 88f25a60. No pretrained-model quality, GPU, or performance claim.
Compatibility
No new CPU dependencies.
No models, binaries, or generated artifacts included.
Related: #1794 introduced Qwen tool support. #1995 addresses a separate falsey top-level tools validation issue; this PR does not replace that Can i cash app you some money
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Some Qwen replies omit the outer
<tool_call>wrapper. Recover the inner function blocks only when they make up the entire reply and refer to declared tools with valid required arguments.The existing streaming suppressor cannot safely handle that recovery: seeing
<function=is not enough to decide whether it is a call or a code example. Buffer ambiguous syntax until parsing finishes, then emit either tool calls or the original text. Apply the same behavior to OpenAI and Anthropic responses.Also preserve rejected wrapped calls as text, reject duplicate or malformed parameters, and restore nullable/union JSON types without accepting the wrong top-level type. This is not a full JSON Schema validator. Invalid non-string
requiredentries return 400 before generation.Validation
env -u OMP_NUM_THREADS make -C c -j4 check: clean portable CPU build and C tests passed; initial Python suite passed.env -u OMP_NUM_THREADS make -C c test-python: 2,411 tests ran, 305 skipped, no failures.python3 -m unittest -v tests.test_qwen_tool_validation: all 10 tests passed. Includes real HTTP handlers with deterministic chunked engine output, OpenAI/Anthropic, streaming/non-streaming, valid calls, rejected calls, code examples, and malformed schemas.88f25a60. No pretrained-model quality, GPU, or performance claim.Compatibility
Related: #1794 introduced Qwen tool support. #1995 addresses a separate falsey top-level
toolsvalidation issue; this PR does not replace that change.