Add Qwen3-Next Coder parser fallback and adjust routing to qwen_coder#228
Add Qwen3-Next Coder parser fallback and adjust routing to qwen_coder#228guoqingbao wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5065a09a75
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if ["boolean", "bool", "binary"].contains(¶m_type.as_str()) { | ||
| return Value::Bool(raw.eq_ignore_ascii_case("true")); |
There was a problem hiding this comment.
Stop coercing malformed boolean parameters to false
The boolean conversion branch always returns false for any value other than exact case-insensitive "true", so outputs like "true ", "1", or other malformed-but-recoverable booleans are silently rewritten instead of preserved. In this fallback parser that is meant to recover from imperfect model output, this can corrupt tool arguments in production (especially when the model emits extra whitespace), while other numeric branches already fall back to strings on parse failure.
Useful? React with 👍 / 👎.
| let end_parameter = p_val_rest.find("</parameter>"); | ||
| let next_parameter = p_val_rest.find("<parameter="); | ||
|
|
There was a problem hiding this comment.
Detect next function tag when slicing parameter values
Parameter boundary detection only looks for </parameter> and the next <parameter=, so when fallback input is malformed (e.g., missing </parameter> before a subsequent <function=...>), the current parameter value can swallow function markup and downstream calls get merged or skipped. This matters here because the new fallback is explicitly used when normal parsers fail on imperfect Qwen3-Next outputs, so this boundary case is part of its expected operating envelope.
Useful? React with 👍 / 👎.
|
Ehh... #16 191.5 Compiling vllm-rs v0.9.2 (/vllm.rs)
#16 193.1 error[E0560]: struct `tool_parser::ToolCall` has no field named `tool_index`
#16 193.1 --> src/server/parser.rs:699:21
#16 193.1 |
#16 193.1 699 | tool_index,
#16 193.1 | ^^^^^^^^^^ `tool_parser::ToolCall` does not have this field
#16 193.1 |
#16 193.1 = note: available fields are: `function`
#16 193.1
#16 193.1 error[E0560]: struct `tool_parser::ToolCall` has no field named `name`
#16 193.1 --> src/server/parser.rs:700:21
#16 193.1 |
#16 193.1 700 | name: func_name.to_string(),
#16 193.1 | ^^^^ `tool_parser::ToolCall` does not have this field
#16 193.1 |
#16 193.1 = note: available fields are: `function`
#16 193.1
#16 193.1 error[E0560]: struct `tool_parser::ToolCall` has no field named `parameters`
#16 193.1 --> src/server/parser.rs:701:21
#16 193.1 |
#16 193.1 701 | parameters: Value::Object(params).to_string(),
#16 193.1 | ^^^^^^^^^^ `tool_parser::ToolCall` does not have this field
#16 193.1 |
#16 193.1 = note: available fields are: `function`
#16 193.1
#16 194.7 For more information about this error, try `rustc --explain E0560`.
#16 194.7 error: could not compile `vllm-rs` (lib) due to 3 previous errors
#16 ERROR: process "/bin/sh -c set -eux; FEATURES=\"${BUILD_FEATURES:-$WITH_FEATURES}\"; ./build.sh --release --features \"${FEATURES}\"; cargo build --release --features \"$(echo \"${FEATURES}\" | sed 's|,python||g')\"" did not complete successfully: exit code: 101
------
> [base 7/9] RUN set -eux; FEATURES="${BUILD_FEATURES:-cutlass,python,cuda,nccl,flashinfer}"; ./build.sh --release --features "${FEATURES}"; cargo build --release --features "$(echo "${FEATURES}" | sed 's|,python||g')":
193.1 error[E0560]: struct `tool_parser::ToolCall` has no field named `parameters`
193.1 --> src/server/parser.rs:701:21
193.1 |
193.1 701 | parameters: Value::Object(params).to_string(),
193.1 | ^^^^^^^^^^ `tool_parser::ToolCall` does not have this field
193.1 |
193.1 = note: available fields are: `function`
193.1
194.7 For more information about this error, try `rustc --explain E0560`.
194.7 error: could not compile `vllm-rs` (lib) due to 3 previous errors
------
Dockerfile.prod:52
--------------------
51 | COPY . .
52 | >>> RUN set -eux; \
53 | >>> FEATURES="${BUILD_FEATURES:-$WITH_FEATURES}"; \
54 | >>> ./build.sh --release --features "${FEATURES}"; \
55 | >>> cargo build --release --features "$(echo "${FEATURES}" | sed 's|,python||g')"
56 | RUN set -eux; \
--------------------
ERROR: failed to solve: process "/bin/sh -c set -eux; FEATURES=\"${BUILD_FEATURES:-$WITH_FEATURES}\"; ./build.sh --release --features \"${FEATURES}\"; cargo build --release --features \"$(echo \"${FEATURES}\" | sed 's|,python||g')\"" did not complete successfully: exit code: 101 |
|
Aaah, breaking all my diffs here :-p So for example, here's gemma3-27B trying to call tools: 2026-02-14T03:41:12.378627Z WARN vllm_rs::server::server: Tools enabled for request
2026-02-14T03:41:12.530440Z WARN vllm_rs::core::engine: [Stream] New request [Seq_id 2, 599 tokens] received! (session_id: None)
2026-02-14T03:41:12.530485Z INFO vllm_rs::core::block_manager: Prefix cache hit seq 2 (576 cached tokens, 9 blocks)
2026-02-14T03:41:13.402435Z INFO vllm_rs::core::engine: Prefilling [seq_id 2]: 600 tokens in 0.96s (624.35 tokens/s, cache included)
2026-02-14T03:41:16.086989Z INFO vllm_rs::server::parser: Tool call buffering end, reached > (236813)
2026-02-14T03:41:16.168391Z INFO vllm_rs::core::block_manager: Prefix cache insert seq 2 (667 tokens, 10 blocks)
2026-02-14T03:41:16.168423Z WARN vllm_rs::tools::helpers: Tool 'list_directory' not found in schema map. Available tools: ["fs_cat", "fs_ls"]
2026-02-14T03:41:16.168435Z WARN vllm_rs::server::server: [Seq 2] Dropped 1 invalid tool call(s)
2026-02-14T03:41:16.168442Z INFO vllm_rs::tools::helpers: Invalid tool call(s): list_directory(args={"path":"."})
2026-02-14T03:41:16.168448Z WARN vllm_rs::server::server: --- Performance Metrics ---
2026-02-14T03:41:16.168451Z INFO vllm_rs::server::server: [Seq 2] ⏱️ Prompt: 599 tokens in 0.96s (623.31 t/s)
2026-02-14T03:41:16.168456Z INFO vllm_rs::server::server: [Seq 2] ⏱️ Decoded: 68 tokens in 2.77s (24.58 t/s)the tools made available are |
|
So, structurally, this is a decent representation of the problem:
Compared to:
vLLM-RS’s
Evidence from Code:
|
|
Working on a revised engine/scheduler/parser call chain to handle the delta piece and avoid preemptive cutting of the stream state - should have something ~shortly 😄 |
Motivation
<function=...><parameter=...>style tool-call tags which the existingqwenrouting does not parse correctly.Description
qwen_coderparser viauses_qwen_coder_parser,is_qwen2_5_coder_model, andis_qwen3_next_coder_model_nameheuristics.parse_qwen3_next_coder_callsthat scans<tool_call>blocks for<function=name>...</function>and parses<parameter=name>value</parameter>with robust boundary handling (next parameter, next function, or stream tail).convert_qwen3_next_parameter_valueto convertnull, integers, floats, booleans, JSON objects/arrays, and fall back to strings using tool schema fromqwen3_next_tool_param_config.parse_complete_with_fallback(runs when other parsers produce no calls for detected Qwen3-Next Coder inputs) and added theserde_json::Mapimport and several unit tests undersrc/server/parser.rsto lock routing and parsing behavior.Testing
cargo fmt --allwhich completed successfully.test_qwen3_next_parser_fallback_function_parameter_formatviacargo test, but the test run failed due to an external dependency fetch error (attention-rsGit fetch blocked by network/403 in this environment), preventing full automated test execution.test_qwen_coder_parser_only_for_qwen_2_5_coderandtest_qwen3_next_parser_fallback_function_parameter_format.Codex Task