Skip to content

[https://nvbugs/6240584][fix] Attempt json.loads before early-return in tool parser#14777

Open
tensorrt-cicd wants to merge 2 commits into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6240584
Open

[https://nvbugs/6240584][fix] Attempt json.loads before early-return in tool parser#14777
tensorrt-cicd wants to merge 2 commits into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6240584

Conversation

@tensorrt-cicd

@tensorrt-cicd tensorrt-cicd commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Root cause: detect_and_parse hard-gates on <tool_call>\n and returns calls=[] for any input lacking that tag, even when the text is valid bare JSON the base class's parse_base_json could handle.
  • Fix: Before the early-return, attempt json.loads(text.strip()) and feed the result through self.parse_base_json(parsed, tools); on success return those calls with empty normal_text. Streaming path and has_tool_call are untouched.
  • Automated fix generated by repair-bot

Test plan

  • Verify fix on the same GPU type as the original failure
  • Check for regressions in related tests

Links

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced Qwen 3 tool call parsing to handle bare JSON tool calls emitted without wrapper tokens, with automatic fallback to standard parsing behavior if JSON decoding fails.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The PR adds a fallback JSON parsing path to Qwen3ToolParser.detect_and_parse that handles Qwen 3 chat templates emitting bare tool calls without <tool_call> wrapper markers. When the wrapper is absent, the parser attempts to parse the full stripped input as JSON and extract tool calls; on success, calls are returned with normal text cleared; on JSON or extraction errors, the original behavior is preserved.

Changes

Qwen3 Bare JSON Tool Call Recovery

Layer / File(s) Summary
Bare JSON tool call recovery path
tensorrt_llm/serve/tool_parser/qwen3_tool_parser.py
When <tool_call> wrapper markers are absent, detect_and_parse now attempts to parse the full stripped input as JSON and extract tool calls directly; successful extraction returns calls immediately with cleared normal text, while JSON or parsing failures silently fall back to returning the input as normal text with no calls.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description covers root cause, the fix, and test plan as required. However, it lacks some PR checklist items (API compatibility, dependencies, CODEOWNERS, documentation) that should be explicitly confirmed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the main fix: trying json.loads before the early return in the Qwen3 tool parser.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@JunyiXu-nv
JunyiXu-nv force-pushed the repair-bot-bug6240584 branch from 4bb40c8 to 6a579e6 Compare July 2, 2026 05:15
@JunyiXu-nv JunyiXu-nv changed the title [https://nvbugs/6240584][fix] Before the early-return, attempt json.loads(text.strip()) and feed the result [https://nvbugs/6240584][fix] Attempt json.loads before early-return in tool parser Jul 2, 2026
@JunyiXu-nv

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #57124 [ run ] triggered by Bot. Commit: 6a579e6 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #57124 [ run ] completed with state SUCCESS. Commit: 6a579e6
/LLM/main/L0_MergeRequest_PR pipeline #45911 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@JunyiXu-nv

Copy link
Copy Markdown
Collaborator

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #57520 [ run ] triggered by Bot. Commit: 6a579e6 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #57520 [ run ] completed with state SUCCESS. Commit: 6a579e6
/LLM/main/L0_MergeRequest_PR pipeline #46250 completed with status: 'SUCCESS'

CI Report

Link to invocation

@JunyiXu-nv

Copy link
Copy Markdown
Collaborator

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #57893 [ run ] triggered by Bot. Commit: 6a579e6 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #57893 [ run ] completed with state SUCCESS. Commit: 6a579e6
/LLM/main/L0_MergeRequest_PR pipeline #46588 completed with status: 'SUCCESS'

CI Report

Link to invocation

@JunyiXu-nv

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #57930 [ run ] triggered by Bot. Commit: 13c2198 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #57930 [ run ] completed with state FAILURE. Commit: 13c2198
/LLM/main/L0_MergeRequest_PR pipeline #46618 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

tensorrt-cicd and others added 2 commits July 23, 2026 11:34
… in detect_and_parse

Some Qwen3 chat templates (notably Qwen3.6 FP8 served with
--reasoning_parser qwen3_5 --tool_parser qwen3) emit tool calls as bare
JSON objects without the <tool_call>...</tool_call> wrapper once the
reasoning parser strips the </think> block. detect_and_parse() previously
returned calls=[] unconditionally whenever the bot_token ("<tool_call>\n")
was missing, so those tool calls leaked out as message.content with
finish_reason="stop".

Try json.loads + parse_base_json before falling through to the original
normal_text return. Streaming (parse_streaming_increment) and
has_tool_call() are intentionally unchanged.

Signed-off-by: tensorrt-cicd <90828364+tensorrt-cicd@users.noreply.github.com>
…SON fallback

This stacks on the initial fix in this PR and closes four gaps:

1) detect_and_parse: tighten exception handling. Replace
   `except (JSONDecodeError, AttributeError)` with an explicit
   `isinstance(parsed, (dict, list))` guard so bare JSON scalars
   (e.g. "42", null) fall through cleanly without relying on
   AttributeError.

2) parse_streaming_increment: extend the streaming path with the same
   bare-JSON fallback. When the stream never contains `<tool_call>`
   but the accumulated buffer parses as a JSON object matching
   `{"name": ..., "arguments"/"parameters": ...}`, emit the tool
   call using the base-class streaming pattern (name-first with empty
   params, then arguments). Unblocks streaming clients on Qwen3.6 FP8
   which otherwise saw the tool call leak into `delta.content` with
   `finish_reason="stop"`. Wrapped happy path is preserved by
   routing to the existing base implementation once `<tool_call>` is
   detected.

3) has_tool_call() semantics unchanged. It still strictly gates on
   `<tool_call>` for callers using it as a wrapper detector; the
   bare-JSON fallback lives inside detect_and_parse /
   parse_streaming_increment.

4) Tests. Unit tests exercise the bare-JSON fallback on
   detect_and_parse (dict, list, `parameters` key, non-JSON text,
   JSON scalar, malformed JSON) and on parse_streaming_increment
   (single chunk, split chunks, no content leak, non-JSON flush,
   wrapped-form regression). An integration test wires the qwen3_5
   reasoning parser plus qwen3 tool parser through the postprocess
   pipeline using the exact bug-report input
   `<think>...</think>\\n{...}` and asserts `has_tool_call[0]` is
   True (so downstream flips `finish_reason` to `tool_calls`).

Non-goals honored: no changes to other tool parsers, no changes to
openai_protocol.py or the API stability YAML.

Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
@JunyiXu-nv
JunyiXu-nv force-pushed the repair-bot-bug6240584 branch from 13c2198 to c752d0c Compare July 23, 2026 03:35
@JunyiXu-nv
JunyiXu-nv requested a review from a team as a code owner July 23, 2026 03:35
@JunyiXu-nv

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #61185 [ run ] triggered by Bot. Commit: c752d0c Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator Author

PR_Github #61185 [ run ] completed with state FAILURE. Commit: c752d0c
/LLM/main/L0_MergeRequest_PR pipeline #49434 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants