Skip to content

Enable tool call type coersion - #477

Merged
Mingholy merged 3 commits into
QwenLM:mainfrom
poita66:main
Sep 18, 2025
Merged

Mingholy merged 3 commits into
QwenLM:mainfrom
poita66:main

Conversation

@poita66

@poita66 poita66 commented Aug 28, 2025

Copy link
Copy Markdown
Contributor

TLDR

Some models struggle to produce tool calls that conform to a strict JSON schema. Ajv has built-in support for coercing types to the expected ones. This PR just enables that functionality

Dive Deeper

A tool call might have something like an offset provided as a string when it's supposed to be a number, or a boolean value wrapped in a string.

Input (incorrect):

{
  "path": "foo.txt",
  "offset": "200",
  "limit": "100"
}

Corrected by coercion:

{
  "path": "foo.txt",
  "offset": 200,
  "limit": 100
}

Ajv can automatically provide this coercion and update the values in the passed object.

https://ajv.js.org/guide/modifying-data.html#coercing-data-types

However I had to manually handle the cases when Qwen would provide "False" instead of "false" or false, but this is only done as a fallback.

Reviewer Test Plan

Testing this can be tricky because we need to somehow get the model to use the wrong types in tool calls.

I managed this with the following prompt:

Use shell tool with `is_background: "False"` to run ls

Testing without this patch, this prompt fails the first tool call

Testing Matrix

🍏 🪟 🐧
npm run ❓ ❓ ✔️
npx ❓ ❓ ❓
Docker ❓ ❓ ❓
Podman ❓ - -
Seatbelt ❓ - -

Linked issues / bugs

Hopefully resolves #472

@github-actions github-actions Bot added bug status/need-information More information is needed to resolve this issue. labels Aug 28, 2025
@PhilipAD

PhilipAD commented Sep 3, 2025

Copy link
Copy Markdown

LGTM, tested using Qwen/Qwen3-Coder-30B-A3B-Instruct local and I dont get issues in #472

@Mingholy

Mingholy commented Sep 8, 2025

Copy link
Copy Markdown
Collaborator

Sorry for the late response.
Would you please update the glob.test.ts to resolve the CI issues? The failing cases have a strict parameter type check, but we should be able to relax parameter type checks to support relatively small models as much as possible.

@github-actions github-actions Bot added status/in-review This issue is currently in review. and removed enhancement status/need-information More information is needed to resolve this issue. labels Sep 15, 2025
@poita66

poita66 commented Sep 16, 2025

Copy link
Copy Markdown
Contributor Author

Would you please update the glob.test.ts to resolve the CI issues?

Done!

@Mingholy
Mingholy merged commit 724c249 into QwenLM:main Sep 18, 2025
8 of 9 checks passed
@qq471231311

Copy link
Copy Markdown

在最新版qwen-code v0.1.1版本还是存在这个问题,我在使用 Qwen/Qwen3-Coder-30B-A3B-Instruct 模型时,也遇到了完全相同的验证错误(is_background must be a boolean 和 Parameter "todos" must be an array),这个模型倾向于为工具调用参数输出字符串化的布尔值(例如 "false")和数组(例如 "[...]")。
我通过将你 PR 中的核心修改应用到最新的源码上来解决了这个问题:
在 packages/core/src/utils/schemaValidator.ts 中:
用 new AjvClass({ coerceTypes: true }); 来初始化 Ajv。
增加一个辅助函数来处理 Python 风格的布尔值 ('True'/'False')。
再增加一个辅助函数,在验证前对任何字符串化的数组进行 JSON.parse。

@liuyaboixixi

Copy link
Copy Markdown

现在 0.4.1 还是有这个问题

@AnnoyingTechnology

Copy link
Copy Markdown

The issue is still present in 0.6.0 with Qwen Coder 30B A3B.

(base) redacted@redacted:~/redacted$ qwen --version
0.6.0
(base) redacted@redacted:~/redacted$ qwen
[...]

> do a simple tool call, like saying hello

✦ Hello! How can I help you today?

> in bash please

 ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
 │ x  Shell {"command":"echo \"Hello\"","is_background":"false"}                                                               │
 │                                                                                                                             │
 │    params/is_background must be boolean                                                                                     │
 ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
 ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
 │ x  Shell {"command":"echo \"Hello\"","is_background":"false"}                                                               │
 │                                                                                                                             │
 │    params/is_background must be boolean                                                                                     │
 ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
 ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
 │ x  Shell {"command":"echo 'Hello'","is_background":"false"}                                                                 │
 │                                                                                                                             │
 │    params/is_background must be boolean                                                                                     │
 ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
 ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
 │ x  Shell {"command":"echo Hello","is_background":"false"}                                                                   │
 │                                                                                                                             │
 │    params/is_background must be boolean                                                                                     │
 ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
 ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
 │ x  Shell {"command":"echo 'Hello'","is_background":"false"}                                                                 │
 │                                                                                                                             │
 │    params/is_background must be boolean                                                                                     │
 ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I apologize for the confusion. Let's try a different approach to execute a simple bash command.

✦ I apologize for the repeated issues with the tool. Let's just proceed with our task without executing bash commands.
  Let me know what you'd like to do next!

xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
* feat: enable tool call type coercion

* fix: tests for type coercion

---------

Co-authored-by: Mingholy <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status/in-review This issue is currently in review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

is_background missing property and isn't boolean

6 participants