Skip to content

[#17146][fix] Fix Laguna's reasoning parser - #17151

Open
1MrazorT1 wants to merge 2 commits into
NVIDIA:mainfrom
1MrazorT1:fix/poolside_v1_reasoning_parser
Open

[#17146][fix] Fix Laguna's reasoning parser#17151
1MrazorT1 wants to merge 2 commits into
NVIDIA:mainfrom
1MrazorT1:fix/poolside_v1_reasoning_parser

Conversation

@1MrazorT1

@1MrazorT1 1MrazorT1 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Dev Engineer Review

  • Added PoolsideV1ReasoningParser for poolside_v1 and laguna.
  • Defaults thinking to enabled when no chat-template flag is provided.
  • Uses DeepSeek-V4 behavior and removes the standalone laguna registration from DeepSeekR1Parser.
  • Updated automatic model detection and telemetry metadata consistently.
  • Updated the telemetry documentation and golden manifest with valid parser values.
  • Updated the CLI stability reference for minimax_m3.
  • No performance or error-handling concerns are evident from the reviewed changes.
  • The implementation preserves explicit thinking and enable_thinking behavior.
  • XS and M1 templates may still require explicit enable_thinking=true.

QA Engineer Review

  • Updated tests/unittest/llmapi/test_reasoning_parser.py.
  • Added coverage for:
    • Thinking enabled.
    • Thinking disabled.
    • Missing and arbitrary chat-template options.
    • Streaming behavior.
    • Non-streaming and streaming </think> handling.
    • Laguna auto-detection as poolside_v1.
    • poolside_v1 and laguna parser aliases.
  • The test functions are unit tests and are not listed in tests/integration/test_lists/.
  • Reported result: 141 tests passed.
  • Verdict: sufficient.

Fixes #17146 .

Description

This PR contains the fix for Laguna's reasoning parser mentioned in the issue #17146.

This will serve as a continuation to what I have already established in the issue's description.

After looking at other implementations of parsers within the same file, I found out that DeepSeekV4's is the most suitable to fit Laguna's chat template, (with a small caveat that I will detail later on):

def __init__(
    self,
    *,
    chat_template_kwargs: Optional[dict[str, Any]] = None,
) -> None:
    super().__init__(chat_template_kwargs=chat_template_kwargs)
    chat_template_kwargs = chat_template_kwargs or {}
    thinking = bool(
        chat_template_kwargs.get("thinking", False)
        or chat_template_kwargs.get("enable_thinking", False))
    if thinking:
        self._parser = DeepSeekR1Parser(
            reasoning_at_start=True,
            chat_template_kwargs=chat_template_kwargs,
        )
    else:
        self._parser = IdentityReasoningParser(
            chat_template_kwargs=chat_template_kwargs)

As we established in the issue, DeepSeekR1's parser with reasoning_at_start=True is fully functional as a Laguna parser in thinking mode, however, it fails for non thinking mode by putting actual model content in reasoning content.
This DeepSeekV4 parser fixes this issue by correctly using DeepSeekR1's parser with reasoning_at_start=True when the model is reasoning, and when the model is not reasoning, the parser defaults to IdentityReasoningParser which correctly copies actual content into the correct content field.

Let's test this: first, I registered Laguna's reasoning parser as a DeepSeekV4 one, then, after starting up the server, let's test both enable_thinking=True and enable_thinking=False:

  • for enable_thinking=True:
    • Run:
curl -sX 'POST' 'http://127.0.0.1:8000/v1/chat/completions' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"model": "Laguna", "messages": [{"role": "user", "content": "est ce que les jumeaux sont à risque de hypothyroidie ? do not reason alot, and give a brief answer"}], "chat_template_kwargs": {"enable_thinking": true}}' | jq ".choices[0].message"
  • Output:
{
  "role": "assistant",
  "content": "Oui, les jumeaux, surtout les jumeaux identiques (monozygotes), sont à un risque accru d'hypothyroïdie, car cette condition a une composante génétique (souvent liée à des maladies auto-immunes comme le chuti thyroïdien de Hashimoto). Les jumeaux partagent donc des gènes identiques ou similaires, ce qui augmente la probabilité qu'ils développent des troubles thyroïdiens. Cependant, les facteurs environnementaux (infections, stress, etc.) jouent également un rôle. Les études montrent une concordance plus élevée chez les jumeaux identiques (30-50 %) que chez les jumeaux fraternels (10-20 %).",
  "reasoning_content": "Okay, the user is asking if twins are at higher risk for hypothyroidism. First, I need to recall what I know about hypothyroidism and twins. Hypothyroidism is when the thyroid gland doesn't produce enough hormones. It's often caused by autoimmune conditions like Hashimoto's thyroiditis, (etc)",
  "reasoning": null,
  "tool_calls": []
}
  • for enable_thinking=False:
    • Run:
curl -sX 'POST' 'http://127.0.0.1:8000/v1/chat/completions' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"model": "Laguna", "messages": [{"role": "user", "content": "est ce que les jumeaux sont à risque de hypothyroidie ? Give a brief answer"}], "chat_template_kwargs": {"enable_thinking": false}}' | jq ".choices[0].message"
  • Output:
{
  "role": "assistant",
  "content": "Les jumeaux ne sont pas intrinsèquement à un risque accru d'**hypothyroïdie** par rapport aux enfants d'inUkosa simple naissance. Toutefois, certains facteurs liés à la naissance prématurée ou à un faible poids de naissance (plus fréquents chez les jumeaux) peuvent augmenter temporairement le risque. Par exemple :  \n1. **Naissance prématurée** : Le cerveau hypothalamo-hypophyso-dimégétique et les thyroïdes pourraient être moins matures, entraînant une surootérieure.  \n2. **Surcharge en thyroxine (T4)** : La mère peut transmettre des anticorps stimulant la thyroïde (TSI), provoquant une thyroïdite passagère chez le nouveau-né.  \n\n**Conclusion** : Un dépistage thyroidien néonatal est généralement effectué, mais une surveillance complémentaire peut être nécessaire chez les jumeaux si des facteurs de risque (prématurité, pathologies maternelles) sont présents. En l'absence de ces facteurs, le risque est similaire à celui des mono gaz.",
  "reasoning_content": "",
  "reasoning": null,
  "tool_calls": []
}

We can see that the parser worked correctly on both explicitly set thinking flags.

However, recall that I had mentioned that DeepSeekV4's reasoning parser has a caveat for Laguna, and it appears when the user does not explicitly set a enable_thinking flag at all, here's the test:

curl -sX 'POST' 'http://127.0.0.1:8000/v1/chat/completions' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"model": "Laguna", "messages": [{"role": "user", "content": "est ce que les jumeaux sont à risque de hypothyroidie ? Give a brief answer"}]}' | jq ".choices[0].message"

Output:

{
  "role": "assistant",
  "content": "Okay, the user is asking if twins are at risk for hypothyroidism. Let me start by recalling what I know about hypothyroidism and twins. I remember that thyroid issues can have both genetic and environmental factors. Since twins share genetic material, maybe there's a higher risk for one twin if the other has it. But wait, monozygotic (identical) twins share 100% of their genes, while dizygotic (fraternal) twins share about 50%, like regular siblings. \n\nI think studies show that if one identical twin has hypothyroidism, the other has a higher chance compared to fraternal twins. But how much higher? I should check the concordance rates. For hypothyroidism, especially autoimmune types like Hashimoto's, the genetic component is significant. So maybe the risk is higher in identical twins. But it's not 100%, so environment and other factors still play a role. \n\nAlso, conditions like Down syndrome or other genetic disorders that are more common in twins might be linked to thyroid issues. Wait, Down syndrome is actually more common in twins? No, actually, the incidence of Down syndrome is similar in twins as in singletons. But if a twin has a genetic condition that affects the thyroid, that could be a factor. \n\nAnother angle: during pregnancy, if the mother has thyroid problems, it might affect the twins' thyroid development. But that's more about maternal health rather than the twins themselves being at higher risk. \n\nSo putting it all together: yes, twins, especially identical twins, have a higher risk of hypothyroidism due to shared genetics. But the exact risk depends on the type of hypothyroidism and other factors. I should mention both genetic and environmental influences, and maybe note that if one twin is diagnosed, the other should be monitored.</think>Oui, les jumeaux, surtout les jumeaux identiques (monozygotes), sont à un **risque plus élevé** d'hypothyroïdie, en raison d'une composante génétique forte. Si un jumeau développe une hypothyroïdie (notamment une forme auto-immune comme l'athyrïdie de Hashimoto), l'autre jumeau a une probabilité accrue de présenter la même pathologie, bien que cela ne soit pas systématique. \n\nLes facteurs environnementaux et les spécificités de la grossesse (ex. : troubles thyroïdiens maternels) peuvent également jouer un rôle. Il est donc recommandé de surveiller la thyroïde des deux jumeaux si l'un d'eux est diagnostiqué.",
  "reasoning_content": "",
  "reasoning": null,
  "tool_calls": []
}

We can see that, not setting the flag at all, gets us back all the way to square one: reasoning_content + </think> + content are all coexisting in the same content block.

The root cause of this is the following: when looking at Laguna S2.1 chat template, we can see that it enables thinking by default:

{%- set enable_thinking = enable_thinking | default(true) -%}

And this is tracing all the way down to:

{%- if add_generation_prompt -%}
  {{- "<assistant>" -}}
  {#- ───── Include reasoning mode directive ───── -#}
  {%- if enable_thinking -%}
    {{- '<think>' -}}
  {%- else -%}
    {{- '</think>' -}}
  {%- endif -%}
{%- endif -%}

Which means that the model is thinking by default when that flag is not set, and when it is not set, DeepSeekV4's reasoning parser has no way of knowing it:

thinking = bool(chat_template_kwargs.get("thinking", False) or chat_template_kwargs.get("enable_thinking", False))

And that way, the parser defaults to non thinking mode whereas the model is actually thinking.
To fix this, thinking must default to true when the user is not sending a enable_thinking flag. Which is the logic that the code changes in this PR is following.

Defaulting thinking to true is a decision I have made to match the documentation and generation_config.json files that Poolside ships their models with. All their model cards and mention that they enable thinking by default, and every generation_config.json adds explicitly default_chat_template_kwargs": {"enable_thinking": true}.

I have however noticed an inconsistency with their M1 and XS models' jinja templates: they default thinking to false despite the verifiable facts that I have just mentioned, that is fine for vLLM because it overrides it and defaults it back to true thanks to their generation_config.json, but this is not the case for TensorRT-LLM since it does not read such files. And that is the reason one I have opened a PR in these models aiming to fix that inconsistency, and so that everything will be coherent.

Now the only limitation is that XS and M1 models output will end up in reasoning content when enable_thinking is not precised, until Poolside accepts the changes on their Jinja templates or unless the user passes "chat_template_kwargs": {"enable_thinking": true}".

Test Coverage

141 unit tests in tests/unittest/llmapi/test_reasoning_parser.py are passing correctly, and among them newly written tests for the new parser.

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.

  • PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.

  • Test cases are provided for new code paths (see test instructions)

  • If PR introduces API changes, an appropriate PR label is added - either api-compatible or api-breaking. For api-breaking, include BREAKING in the PR title.

  • Any new dependencies have been scanned for license and vulnerabilities

  • CODEOWNERS updated if ownership changes

  • Documentation updated as needed

  • Update tava architecture diagram if there is a significant design change in PR.

  • The reviewers assigned automatically/manually are appropriate for the PR.

  • Please check this after reviewing the above items as appropriate for this PR.

GitHub Bot Help

To see a list of available CI bot commands, please comment /bot help.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The PR adds PoolsideV1ReasoningParser, registers poolside_v1 and laguna, updates Laguna auto-detection, adds parser tests, and synchronizes telemetry and CLI metadata.

Changes

Poolside V1 reasoning support

Layer / File(s) Summary
Parser registration and parsing behavior
tensorrt_llm/llmapi/reasoning_parser.py
Adds PoolsideV1ReasoningParser, registers both aliases, defaults unspecified thinking mode to enabled, and delegates parsing to DeepSeek V4 behavior.
Parser behavior and alias validation
tests/unittest/llmapi/test_reasoning_parser.py
Tests thinking options, streaming delimiters, reasoning extraction, Laguna detection, and parser aliases.
Telemetry and interface metadata alignment
tensorrt_llm/llmapi/llm_args.py, tensorrt_llm/usage/llm_args_golden_manifest.json, docs/source/developer-guide/telemetry.md, tests/unittest/api_stability/references/trtllm_serve_cli.yaml
Updates parser allowlists, telemetry field metadata, the captured-field count, sampling-mode values, and CLI parser choices.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: api-compatible

Suggested reviewers: qijune, arysef

Sequence Diagram(s)

sequenceDiagram
  participant ChatRequest
  participant PoolsideV1ReasoningParser
  participant DeepSeekV4ReasoningParser
  ChatRequest->>PoolsideV1ReasoningParser: provide template options and generated text
  PoolsideV1ReasoningParser->>PoolsideV1ReasoningParser: default enable_thinking when unspecified
  PoolsideV1ReasoningParser->>DeepSeekV4ReasoningParser: delegate parsing
  DeepSeekV4ReasoningParser-->>ChatRequest: return reasoning and content
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes unrelated telemetry entries and a minimax_m3 CLI reference update beyond the Laguna parser fix. Remove unrelated telemetry changes and the minimax_m3 CLI reference update, or explain why each change is required for issue #17146.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the bug fix for Laguna’s reasoning parser and follows the repository’s required format.
Description check ✅ Passed The description explains the issue, solution, testing, limitations, and checklist status with sufficient detail.
Linked Issues check ✅ Passed The parser changes and tests address issue #17146 by separating reasoning, handling non-thinking mode, and preventing leaked markers.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
tests/unittest/llmapi/test_reasoning_parser.py (1)

739-744: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use snake_case for the local variable.

Rename Poolside_v1 to poolside_v1.

Proposed fix
-    Poolside_v1 = ReasoningParserFactory.create_reasoning_parser("poolside_v1")
+    poolside_v1 = ReasoningParserFactory.create_reasoning_parser("poolside_v1")
     laguna = ReasoningParserFactory.create_reasoning_parser("laguna")
-    assert isinstance(Poolside_v1, PoolsideV1ReasoningParser)
+    assert isinstance(poolside_v1, PoolsideV1ReasoningParser)

As per coding guidelines, Python variables must use snake_case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/llmapi/test_reasoning_parser.py` around lines 739 - 744,
Rename the local variable Poolside_v1 to poolside_v1 in
test_poolside_v1_alias_same_parser, and update its corresponding assertion to
use the snake_case name.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/unittest/api_stability/references/trtllm_serve_cli.yaml`:
- Line 371: Synchronize the reasoning_parser telemetry metadata with the
registered choices shown in the CLI reference: add deepseek_v4, minimax_m3, and
nemotron-v3 to the corresponding TelemetryField.categorical allowlist and
telemetry table, then regenerate
tensorrt_llm/usage/llm_args_golden_manifest.json. Preserve the existing
API-stability reference and ordering conventions.

In `@tests/unittest/llmapi/test_reasoning_parser.py`:
- Around line 110-116: Update
test_poolside_v1_reasoning_parser_extracts_when_not_thinking to parameterize
both enable_thinking=False and thinking=False, ensuring either explicit option
disables the default thinking mode. Replace the unnecessary f-string in the
reasoning_parser.parse call with a regular string literal to remove Ruff F541.
- Around line 92-133: Register the reasoning-parser unittest module containing
test_poolside_v1_reasoning_parser_extracts_when_thinking and
test_poolside_v1_reasoning_parser_streams_when_thinking in the manual-QA
integration test list. Preserve the existing test-list registration structure
and avoid adding duplicate entries.

---

Nitpick comments:
In `@tests/unittest/llmapi/test_reasoning_parser.py`:
- Around line 739-744: Rename the local variable Poolside_v1 to poolside_v1 in
test_poolside_v1_alias_same_parser, and update its corresponding assertion to
use the snake_case name.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b1d96cba-008b-4bd1-9886-08a68e1458aa

📥 Commits

Reviewing files that changed from the base of the PR and between 946f9c5 and d861772.

📒 Files selected for processing (6)
  • docs/source/developer-guide/telemetry.md
  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/llmapi/reasoning_parser.py
  • tensorrt_llm/usage/llm_args_golden_manifest.json
  • tests/unittest/api_stability/references/trtllm_serve_cli.yaml
  • tests/unittest/llmapi/test_reasoning_parser.py

- "--post_processor_hook"
reasoning_parser:
type: Choice(['auto', 'deepseek-r1', 'deepseek_v4', 'gemma4', 'kimi_k2', 'kimi_k25', 'laguna', 'minimax_m2', 'minimax_m2_append_think', 'minimax_m3', 'nano-v3', 'nemotron-v3', 'qwen3', 'qwen3_5'])
type: Choice(['auto', 'deepseek-r1', 'deepseek_v4', 'gemma4', 'kimi_k2', 'kimi_k25', 'laguna', 'minimax_m2', 'minimax_m2_append_think', 'minimax_m3', 'nano-v3', 'nemotron-v3', 'poolside_v1', 'qwen3', 'qwen3_5'])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 3 \
  'reasoning_parser|minimax_m3|deepseek_v4|nemotron-v3' \
  tensorrt_llm docs tests

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- reasoning_parser references ---'
rg -n -C 5 \
  'reasoning_parser|TelemetryField\.categorical|deepseek_v4|nemotron-v3|minimax_m3' \
  tensorrt_llm/llmapi/llm_args.py \
  docs/source/developer-guide/telemetry.md \
  tensorrt_llm/usage/llm_args_golden_manifest.json \
  tests/unittest/api_stability/references/trtllm_serve_cli.yaml

printf '%s\n' '--- relevant file sections ---'
sed -n '330,390p' tests/unittest/api_stability/references/trtllm_serve_cli.yaml
rg -n -C 12 'reasoning_parser' tensorrt_llm/llmapi/llm_args.py
rg -n -C 8 'reasoning_parser' docs/source/developer-guide/telemetry.md
rg -n -C 8 'reasoning_parser' tensorrt_llm/usage/llm_args_golden_manifest.json

Repository: NVIDIA/TensorRT-LLM

Length of output: 32151


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- parser dispatch and validation ---'
rg -n -C 6 \
  'reasoning_parser|nemotron-v3|minimax_m3|deepseek_v4' \
  tensorrt_llm \
  --glob '*.py' \
  --glob '!tests/**'

printf '%s\n' '--- CLI choice generation ---'
rg -n -C 8 \
  'Choice\(.*reasoning_parser|reasoning_parser.*Choice|serve.*reasoning_parser|reasoning_parser.*choices' \
  tensorrt_llm scripts tests \
  --glob '*.py' \
  --glob '*.yaml'

printf '%s\n' '--- telemetry implementation and manifest generator ---'
rg -n -C 10 \
  'class TelemetryField|categorical\(|golden_manifest|allowed_values|allowlist' \
  tensorrt_llm/usage scripts tensorrt_llm/llmapi/llm_args.py \
  --glob '*.py'

printf '%s\n' '--- all exact parser-value references ---'
rg -n \
  "'(minimax_m3|deepseek_v4|nemotron-v3)'|\"(minimax_m3|deepseek_v4|nemotron-v3)\"" \
  tensorrt_llm tests docs \
  --glob '*.py' \
  --glob '*.yaml' \
  --glob '*.md' \
  --glob '*.json'

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '--- reasoning_parser definitions and consumers ---'
rg -n -C 10 'reasoning_parser' \
  tensorrt_llm/llmapi/llm_args.py \
  tensorrt_llm/llmapi \
  tensorrt_llm/serve \
  tensorrt_llm/entrypoints \
  scripts \
  tests \
  --glob '*.py' \
  --glob '*.yaml' \
  --glob '*.json' 2>/dev/null || true

printf '%s\n' '--- exact values outside generated/reference files ---'
rg -n \
  'minimax_m3|deepseek_v4|nemotron-v3' \
  tensorrt_llm/llmapi/llm_args.py \
  tensorrt_llm/serve \
  tensorrt_llm/entrypoints \
  scripts \
  --glob '*.py' 2>/dev/null || true

printf '%s\n' '--- telemetry implementation and generator files ---'
rg -l \
  'class TelemetryField|def categorical|generate_llm_args_golden_manifest|allowed_values' \
  tensorrt_llm scripts \
  --glob '*.py' 2>/dev/null | sort

printf '%s\n' '--- manifest entry ---'
sed -n '1225,1260p' tensorrt_llm/usage/llm_args_golden_manifest.json

printf '%s\n' '--- source field ---'
sed -n '4468,4485p' tensorrt_llm/llmapi/llm_args.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


Synchronize reasoning_parser telemetry metadata. deepseek_v4, minimax_m3, and nemotron-v3 are registered parser choices but are absent from the telemetry allowlist, golden manifest, and telemetry table. Add them to TelemetryField.categorical(...), regenerate tensorrt_llm/usage/llm_args_golden_manifest.json, and update the table. Test coverage: no test functions changed; this file is an API-stability reference.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/api_stability/references/trtllm_serve_cli.yaml` at line 371,
Synchronize the reasoning_parser telemetry metadata with the registered choices
shown in the CLI reference: add deepseek_v4, minimax_m3, and nemotron-v3 to the
corresponding TelemetryField.categorical allowlist and telemetry table, then
regenerate tensorrt_llm/usage/llm_args_golden_manifest.json. Preserve the
existing API-stability reference and ordering conventions.

Comment on lines +92 to +133
@pytest.mark.parametrize("chat_template_kwargs", [{
"thinking": True
}, {
"enable_thinking": True
}, None, {}, {
"random_key": "random_value"
}])
def test_poolside_v1_reasoning_parser_extracts_when_thinking(
chat_template_kwargs: dict):
reasoning_parser = ReasoningParserFactory.create_reasoning_parser(
"poolside_v1", chat_template_kwargs)

result = reasoning_parser.parse(f"hidden{R1_END}visible")

assert result.content == "visible"
assert result.reasoning_content == "hidden"


@pytest.mark.parametrize("chat_template_kwargs", [{"enable_thinking": False}])
def test_poolside_v1_reasoning_parser_extracts_when_not_thinking(
chat_template_kwargs: dict):
reasoning_parser = ReasoningParserFactory.create_reasoning_parser(
"poolside_v1", chat_template_kwargs)

result = reasoning_parser.parse(f"visible")

assert result.content == "visible"
assert result.reasoning_content == ""


def test_poolside_v1_reasoning_parser_streams_when_thinking():
reasoning_parser = ReasoningParserFactory.create_reasoning_parser(
"poolside_v1", {"enable_thinking": True})

deltas = ["hid", f"den{R1_END}visible", " tail"]
results = [reasoning_parser.parse_delta(delta) for delta in deltas]

assert [result.content for result in results] == ["", "visible", " tail"]
assert [result.reasoning_content
for result in results] == ["hid", "den", ""]


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -t f . tests/integration/test_lists | sort
rg -n -i -C 2 'test_reasoning_parser|llmapi/test_reasoning_parser' \
  tests/integration/test_lists || true

Repository: NVIDIA/TensorRT-LLM

Length of output: 5335


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- changed-file summary ---'
git diff --stat

echo '--- target test file diff ---'
git diff -- tests/unittest/llmapi/test_reasoning_parser.py

echo '--- test-list registrations ---'
rg -n -i -C 3 'test_reasoning_parser|llmapi/test_reasoning_parser' \
  tests/integration/test_lists || true

echo '--- test names in the target file ---'
rg -n '^def test_|^async def test_' tests/unittest/llmapi/test_reasoning_parser.py

echo '--- relevant target-file sections ---'
cat -n tests/unittest/llmapi/test_reasoning_parser.py | sed -n '1,170p'
cat -n tests/unittest/llmapi/test_reasoning_parser.py | sed -n '300,365p'
cat -n tests/unittest/llmapi/test_reasoning_parser.py | sed -n '700,760p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 16692


🏁 Script executed:

#!/bin/bash
set -euo pipefail

git diff --stat
git diff -- tests/unittest/llmapi/test_reasoning_parser.py
rg -n -i -C 3 'test_reasoning_parser|llmapi/test_reasoning_parser' tests/integration/test_lists || true
rg -n '^def test_|^async def test_' tests/unittest/llmapi/test_reasoning_parser.py
cat -n tests/unittest/llmapi/test_reasoning_parser.py | sed -n '1,170p'
cat -n tests/unittest/llmapi/test_reasoning_parser.py | sed -n '300,365p'
cat -n tests/unittest/llmapi/test_reasoning_parser.py | sed -n '700,760p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 16525


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- QA list documentation ---'
cat -n tests/integration/test_lists/qa/README.md | sed -n '1,220p'

echo '--- QA references to unit-test paths and reasoning parser ---'
rg -n -i -C 2 'unittest/|reasoning_parser|llmapi' tests/integration/test_lists/qa || true

echo '--- test-db references to the target file ---'
rg -n -i -C 2 'unittest/llmapi/test_reasoning_parser.py' \
  tests/integration/test_lists/test-db

echo '--- available coverage artifacts ---'
fd -t f -i 'cbts_touchmap.sqlite' . || true
fd -t f -i '*coverage*' tests/integration tests/unittest . 2>/dev/null | head -100 || true

Repository: NVIDIA/TensorRT-LLM

Length of output: 10160


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cat -n tests/integration/test_lists/qa/README.md | sed -n '1,220p'
rg -n -i -C 2 'unittest/|reasoning_parser|llmapi' \
  tests/integration/test_lists/qa || true
rg -n -i -C 2 'unittest/llmapi/test_reasoning_parser.py' \
  tests/integration/test_lists/test-db
fd -t f -i 'cbts_touchmap.sqlite' . || true
fd -t f -i '*coverage*' tests/integration tests/unittest . 2>/dev/null | head -100 || true

Repository: NVIDIA/TensorRT-LLM

Length of output: 9985


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- parser implementation ---'
rg -n -C 8 'class PoolsideV1ReasoningParser|chat_template_kwargs|enable_thinking|thinking' \
  tensorrt_llm tests/unittest/llmapi/test_reasoning_parser.py | head -240

echo '--- QA list context around unit-test entries ---'
cat -n tests/integration/test_lists/qa/llm_function_core.txt | sed -n '775,805p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 25474


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 'class PoolsideV1ReasoningParser|chat_template_kwargs|enable_thinking|thinking' \
  tensorrt_llm tests/unittest/llmapi/test_reasoning_parser.py | head -240
cat -n tests/integration/test_lists/qa/llm_function_core.txt | sed -n '775,805p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 25395


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- matching test files and integration definitions ---'
fd -t f -i 'test_reasoning_parser.py' .
fd -t f -i '_test_openai_embeddings.py' .
fd -t d 'unittest' tests/integration/defs tests 2>/dev/null | head -40 || true

echo '--- test-db list scope ---'
cat -n tests/integration/test_lists/test-db/l0_a10.yml | sed -n '125,160p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 2345


🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -t f -i 'test_reasoning_parser.py' .
fd -t f -i '_test_openai_embeddings.py' .
fd -t d 'unittest' tests/integration/defs tests 2>/dev/null | head -40 || true
cat -n tests/integration/test_lists/test-db/l0_a10.yml | sed -n '125,160p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 2262


Add unittest/llmapi/test_reasoning_parser.py to tests/integration/test_lists/qa/llm_function_core.txt.

  • CI registration already exists in tests/integration/test_lists/test-db/l0_a10.yml.
  • Added tests cover thinking, streaming, alias resolution, and auto-detection.
  • Existing cases at lines 367–378 and 405–408 cover enable_thinking=False.
  • Coverage verdict: sufficient after manual-QA registration.
🧰 Tools
🪛 Ruff (0.16.0)

[error] 116-116: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/llmapi/test_reasoning_parser.py` around lines 92 - 133,
Register the reasoning-parser unittest module containing
test_poolside_v1_reasoning_parser_extracts_when_thinking and
test_poolside_v1_reasoning_parser_streams_when_thinking in the manual-QA
integration test list. Preserve the existing test-list registration structure
and avoid adding duplicate entries.

Source: Path instructions

Comment on lines +110 to +116
@pytest.mark.parametrize("chat_template_kwargs", [{"enable_thinking": False}])
def test_poolside_v1_reasoning_parser_extracts_when_not_thinking(
chat_template_kwargs: dict):
reasoning_parser = ReasoningParserFactory.create_reasoning_parser(
"poolside_v1", chat_template_kwargs)

result = reasoning_parser.parse(f"visible")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cover explicit thinking=False and remove the lint error.

Line 110 covers only enable_thinking=False. Add thinking=False to verify that this explicit option prevents the default thinking mode. Line 116 has an unnecessary f-string and triggers Ruff F541.

Proposed fix
-@pytest.mark.parametrize("chat_template_kwargs", [{"enable_thinking": False}])
+@pytest.mark.parametrize("chat_template_kwargs", [
+    {"thinking": False},
+    {"enable_thinking": False},
+])
 def test_poolside_v1_reasoning_parser_extracts_when_not_thinking(
         chat_template_kwargs: dict):
@@
-    result = reasoning_parser.parse(f"visible")
+    result = reasoning_parser.parse("visible")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@pytest.mark.parametrize("chat_template_kwargs", [{"enable_thinking": False}])
def test_poolside_v1_reasoning_parser_extracts_when_not_thinking(
chat_template_kwargs: dict):
reasoning_parser = ReasoningParserFactory.create_reasoning_parser(
"poolside_v1", chat_template_kwargs)
result = reasoning_parser.parse(f"visible")
`@pytest.mark.parametrize`("chat_template_kwargs", [
{"thinking": False},
{"enable_thinking": False},
])
def test_poolside_v1_reasoning_parser_extracts_when_not_thinking(
chat_template_kwargs: dict):
reasoning_parser = ReasoningParserFactory.create_reasoning_parser(
"poolside_v1", chat_template_kwargs)
result = reasoning_parser.parse("visible")
🧰 Tools
🪛 Ruff (0.16.0)

[error] 116-116: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/llmapi/test_reasoning_parser.py` around lines 110 - 116,
Update test_poolside_v1_reasoning_parser_extracts_when_not_thinking to
parameterize both enable_thinking=False and thinking=False, ensuring either
explicit option disables the default thinking mode. Replace the unnecessary
f-string in the reasoning_parser.parse call with a regular string literal to
remove Ruff F541.

Source: Linters/SAST tools

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.

[Bug]: Poolside's Laguna models' reasoning parser is broken: the </think> block leaks into the model's answer

1 participant