Skip to content

feat: expose resolved renderer prefix stability - #184

Merged
hallerite merged 4 commits into
mainfrom
feat/prefix-stability
Oct 9, 2026
Merged

hallerite merged 4 commits into
mainfrom
feat/prefix-stability

Conversation

@hallerite

@hallerite hallerite commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

Expose renderer.is_prefix_stable after renderer configuration and chat-template kwargs are resolved. The flag describes whether full renders ending in an assistant remain token prefixes when messages are appended, with a fixed preamble and tools. Unknown custom templates are conservatively false.

Configuration-sensitive renderers account for history reasoning retention, last-assistant wrappers, effort hints, and training mode. DeepSeek V4 and Inkling are conservatively false because supported message controls and reused tool-call IDs can rewrite earlier output.

A manual, opt-in audit uses tests/fixtures/prefix_stability.json: 36 executable instability witnesses and 21 stable controls sharing six conversations. Each case stores the renderer/config, messages to append, and an explanation. Tests compare actual token prefixes and show the first differing tokens plus a decoded diff on failure. Coverage checks include every registered built-in renderer; opaque DefaultRenderer is tested as unknown. Finite stable controls are not a proof for arbitrary inputs.

Run explicitly with uv run pytest tests/audit_prefix_stability.py -q. The audit is excluded from normal pytest discovery and CI, and reuses the existing shared tokenizer cache.

Validation: manual audit 59 passed in 9.80s; collection-only verification confirms the normal suite excludes the audit. Ruff lint/format and git diff --check passed. The full suite was not rerun locally.

Closes #41.

Rebased onto origin/main at 376f54f (Python 3.11 typing update). The focused manual audit and Ruff checks pass after the rebase; all four PR commits are signed.

Note

Add is_prefix_stable property to the renderer protocol and all built-in renderers

  • Adds an is_prefix_stable boolean property to the runtime-checkable Renderer protocol in base.py and implements it in every built-in renderer, classifying whether a full re-render preserves a completed conversation prefix.
  • Some renderers return a constant value (e.g. DeepSeekV3Renderer is stable; Qwen3Renderer is not). Others derive the value from configuration, such as GLM5Renderer (clear_thinking, enable_thinking), Qwen35Renderer (preserve_thinking), Hy3Renderer (raw_last_assistant, is_training), and Nemotron3Renderer (truncate_history_thinking, effort hint).
  • Adds an opt-in prefix-stability audit in audit_prefix_stability.py driven by a witness corpus in prefix_stability.json. The audit renders original and appended conversations, checks each renderer's reported value against the corpus, and fails if any registered built-in renderer lacks a corpus case. Failures include token-level and decoded-text prefix diagnostics.
  • Documents the guarantee, known stable/unstable cases, and the audit workflow in README.md. SFT behavior is unchanged and still produces one sample per conversation.
  • Risk: third-party or custom renderers that do not define is_prefix_stable will fail the runtime protocol check if it is used for isinstance-style validation.

Macroscope summarized 0e4694a.


Note

Low Risk
Additive API and documentation; behavior of render() and bridges is unchanged. Custom renderers without the property may need getattr if consumers use strict protocol checks.

Overview
Adds renderer.is_prefix_stable to the Renderer protocol so callers (especially SFT) can tell whether a full re-render of a conversation that ends on an assistant keeps the same token prefix when more turns are appended (add_generation_prompt=False, fixed tools/config). DefaultRenderer always reports False; each hand-coded renderer sets a constant or derives the flag from template knobs (e.g. GLM-5 clear_thinking, Qwen3.6/3.8 preserve_thinking, Hy3 training/preserved thinking, Nemotron effort/truncation).

README documents the guarantee, how it differs from thinking_retention / bridge_to_next_turn, and conservative getattr(..., False) for custom renderers.

Opt-in audit (tests/audit_prefix_stability.py + tests/fixtures/prefix_stability.json): parametrized witnesses compare token prefixes before/after append and assert they match each renderer’s declared stability; includes registry coverage and a Qwen3.8 chat_template_kwargs check. Not run in default CI — manual uv run pytest tests/audit_prefix_stability.py -q.

Reviewed by Cursor Bugbot for commit 0e4694a. Bugbot is set up for automated code reviews on this repo. Configure here.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 9, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Approvability

Verdict: Approved at 6d8c744

Macroscope's review found this PR approvable — This is an additive renderer metadata contract with configuration-aware boolean properties; existing rendering, bridging, and SFT behavior remain unchanged. Documentation and an opt-in audit corpus cover the new contract, with only the documented need for custom implementations to expose the property as a compatibility consideration.

Notes:

  • Macroscope's correctness review did not run, so approvability was decided on eligibility alone.

No code changes detected at 0e4694a. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 9, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 9, 2026
@hallerite
hallerite force-pushed the feat/prefix-stability branch from 6d8c744 to 0e4694a Compare October 9, 2026 09:35
@hallerite
hallerite merged commit 41f9290 into main Oct 9, 2026
11 checks passed
@hallerite
hallerite deleted the feat/prefix-stability branch October 9, 2026 09:44
hallerite added a commit to PrimeIntellect-ai/prime-rl that referenced this pull request Oct 9, 2026
Warn when SFT constructs a renderer that does not guarantee prefix
stability. The warning explains that each conversation is rendered once
into one training sample, that N assistant turns are not expanded into N
samples, and that earlier reasoning may be omitted by the template.
Cached renderers warn only on construction; stable renderers stay quiet.
Custom renderers without the capability are conservatively treated as
unknown.

Pin `deps/renderers` to merged main revision `41f9290`, which includes
PrimeIntellect-ai/renderers#184. It provides the
resolved capability and the manual, opt-in witness audit. Sample
construction is unchanged.

Validation: all **73 SFT dataset tests passed**, including
stable/unstable renderer selection and cache-warning behavior. Prime-rl
unit-test CI passed on the preceding revision; this update changes only
the renderer gitlink to the merged revision. Dependency requirements are
unchanged apart from renderer Python >=3.11, compatible with prime-rl
Python 3.12. The manually invoked renderer audit passes **59 tests** and
is excluded from normal CI discovery.
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.

feat: renderer self-describes prefix-stability for SFT / RL / inference consumers

1 participant