Skip to content

fix(reasoning): honor Poolside template thinking defaults - #32540

Merged
JustinTong0323 merged 6 commits into
sgl-project:mainfrom
Oxygen56:codex/fix-poolside-template-default
Jul 29, 2026
Merged

JustinTong0323 merged 6 commits into
sgl-project:mainfrom
Oxygen56:codex/fix-poolside-template-default

Conversation

@Oxygen56

@Oxygen56 Oxygen56 commented Jul 27, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Fixes #32536.

Laguna-S-2.1 and Laguna-XS-2.1 share the poolside_v1 reasoning parser but use opposite Jinja defaults for enable_thinking. Template detection did not recognize the enable_thinking | default(...) form, so Laguna-S-2.1 fell back to the XS-specific parser default and left reasoning disabled for ordinary requests.

Modifications

  • Detect boolean enable_thinking | default(true/false) assignments when resolving a chat template's reasoning mode.
  • Keep default(value, boolean=true) forms excluded because they do not have the same toggle semantics.
  • Add regression coverage for both Poolside template defaults and update the existing Poolside rule-matrix expectation.

Accuracy Tests

This does not change model numerics. Verification performed:

  • Real poolside/Laguna-S-2.1 tokenizer template resolves to default_enabled=True.
  • Real poolside/Laguna-XS-2.1 tokenizer template resolves to default_enabled=False.
  • 13 CPU-only template-detection unit tests passed in a dependency-isolated harness.
  • python3 -m py_compile python/sglang/srt/parser/template_detection.py test/registered/unit/parser/test_template_manager.py passed.
  • uvx pre-commit run --files python/sglang/srt/parser/template_detection.py test/registered/unit/parser/test_template_manager.py passed.

Speed Tests and Profiling

N/A. This adds two startup-time regex checks over the chat template and does not affect model execution.

Checklist

Review and Merge Process

  1. Ping Merge Oncalls to start the process. See the PR Merge Process.
  2. Get approvals from CODEOWNERS and other reviewers.
  3. Trigger CI tests with comments or contact authorized users to do so.
    • Common commands include /tag-and-rerun-ci, /tag-run-ci-label, /rerun-failed-ci
  4. After green CI and required approvals, ask Merge Oncalls or people with Write permission to merge the PR.

CI States

Latest PR Test (Base): ❌ Run #30444413151
Latest PR Test (Extra): ❌ Run #30444412849

@Oxygen56
Oxygen56 requested a review from JustinTong0323 as a code owner July 27, 2026 14:49
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

… detection

- Re-key the Poolside template signature on the shared tool preamble instead
  of the enable_thinking default: with default(true) newly detected, the real
  Laguna-S-2.1 template no longer matched _is_poolside_v1 and --tool-call-parser
  auto silently resolved to qwen, which cannot parse the XML-KV tool format.
- Centralize the default-filter regexes in _has_toggle_default_assignment:
  strip Jinja comments before matching (a commented-out default(false) shadowed
  a live default(true)), accept the documented d alias, keep two-argument
  boolean-mode forms excluded, and cover the thinking toggle symmetrically.
- Add tests shaped like the real Laguna-S-2.1 template (no XS prose) asserting
  both the reasoning and tool-call parsers, plus the filter variants.
@Jiminator

Jiminator commented Jul 28, 2026 •

Copy link
Copy Markdown
Collaborator

Pushed 68e2e5a to fix a side effect of the new detection: _is_poolside_v1 treated default_enabled=False as part of the Poolside signature, so once this PR detects default(true), the real poolside/Laguna-S-2.1 template (which lacks the XS-style prose the other branch requires) fell through to qwen3/qwen under auto — and the qwen tool-call parser can't read Poolside's XML-KV format.

  • _is_poolside_v1 now keys on the tool preamble both Laguna template families share instead of the thinking default (which is per-revision mutable); S-2.1 resolves poolside_v1/poolside_v1 again.
  • Folded the two new regexes into a _has_toggle_default_assignment helper: strips {#...#} comments before matching, accepts the d alias, keeps default(x, boolean=true) excluded, and covers the thinking toggle symmetrically.
  • Added tests shaped like the real S-2.1 template (no XS prose) asserting both parsers; they fail without this commit.

Verification: 38 tests / 50 subtests pass, pre-commit clean; a sweep of 205 real HF chat templates shows exactly one resolution change (Laguna-S-2.1 → poolside_v1); live e2e on real S-2.1 weights (TP=4, --tool-call-parser auto) confirms reasoning separates on default requests and tool calls parse.

@Jiminator Jiminator self-assigned this Jul 28, 2026
@Jiminator Jiminator added the run-ci CI: run the baseline test suite on this PR label Jul 28, 2026

@JustinTong0323 JustinTong0323 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The new default-filter matcher still misses valid toggle forms.

literal = "true|True" if default else "false|False"
pattern = (
rf"set\s+{param}\s*=\s*{param}\s*\|\s*"
rf"(?:default|d)\s*\(\s*(?:{literal})\s*\)"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Two-argument default() forms are excluded too broadly: default(true, false) is equivalent to the one-argument toggle, and default(false, true) still preserves False -> False and True -> True; rejecting them leaves reasoning_config=None and can reintroduce reasoning-marker leakage. Parse the Jinja Filter node and cover all four boolean/default combinations, excluding only forms that actually collapse the toggle such as default(true, true).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Done in 9600889 — switched to parsing the Filter node (with a parse-only {% generation %} extension so transformers templates build an AST). All four combinations now classify by semantics: default(x, false) ≡ default(x), default(false, true) detects as a default-off toggle, and only collapsing forms (default(true, true) / boolean=true) stay excluded. Side benefits: comments/{% raw %}/string literals can no longer shadow a live assignment, and the filter is recognized outside set (the older gemma-4 revs use {%- if enable_thinking | default(false) -%} and now detect correctly — parser resolution unchanged, verified across the same 205-template sweep). Tests updated to cover each combination.

Address review: replace the regex with Jinja Filter-node parsing so all
boolean/default combinations are classified by semantics — default(x, false)
equals default(x), default(false, true) is a working default-off toggle, and
only collapsing forms like default(true, true) stay excluded. Comments,
{% raw %} blocks, and string literals can no longer shadow a live assignment,
and the filter is recognized outside set-assignments (gemma-4 style
'if enable_thinking | default(false)'). A parse-only {% generation %}
extension keeps transformers chat templates parseable.
detect_reasoning_pattern evaluates rules unguarded, and jinja parsing can
raise beyond TemplateError (e.g. RecursionError on a pathologically nested
template), which would take down template loading at startup. Degrade to no
detection instead, mirroring detect_inline_system_support, and add a
regression test.

@JustinTong0323 JustinTong0323 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@JustinTong0323
JustinTong0323 enabled auto-merge (squash) July 29, 2026 12:12
@JustinTong0323
JustinTong0323 merged commit ffd4705 into sgl-project:main Jul 29, 2026
194 of 205 checks passed
saturn-acc pushed a commit to saturn-acc/sglang that referenced this pull request Aug 16, 2026
…t#32540)

Co-authored-by: Jiminator <69131491+Jiminator@users.noreply.github.com>
Atituiset pushed a commit to Atituiset/sglang that referenced this pull request Sep 10, 2026
…t#32540)

Co-authored-by: Jiminator <69131491+Jiminator@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-ci CI: run the baseline test suite on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] poolside_v1 reasoning parser doesn't separate reasoning for Laguna-S-2.1 (thinking-on template default)

3 participants