feat: rlm renderer for the RLM chat format#107
Draft
mikasenghaas wants to merge 2 commits into
Draft
Conversation
…emplate)
Minimal role-tag-only format for the rlm harness: one message, one tag
block, ten single-token delimiters (renamed reserved Nemotron-3 slots
18-27), </assistant> as eos. Thinking is structurally never dropped
(retention "all"; bridge extends without re-rendering). The single tool
ipython renders inline as <ipython>{code}</ipython>; tool results are
<output>...</output> turns. tools= is validation-only: exactly
[ipython] is accepted and renders nothing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Real scaleswe rlm traces store tool_calls as flat JSON strings
({"id","name","arguments"}) and carry mid-conversation system messages
from compaction; the chat template renders both, so the renderer must
too. Validated over 200 real dataset samples (197 render, 3 data-noise
tool-name typos raise as intended).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the
rlmrenderer for the minimal RLM chat format (PrimeIntellect/RLM-Chat-Template, private), designed for the rlm harness.Format
<SPECIAL_18>–<SPECIAL_27>slots renamed — no vocab resize for Nemotron Super base).</assistant>(id 23) is eos/stop."all"(config validator rejects anything else); assistant content renders verbatim on every turn and the bridge extends without re-rendering. Areasoning_contentfield is restored as<think>{reasoning}</think>before content rather than dropped (the only deliberate divergence from the jinja template, which cannot know the field exists).<ipython>{code}</ipython>; results are<output>turns (role: "tool"). Exactly one call per assistant turn (mirrors the harness'sparallel_tool_calls=False+ one-call error inrlm/engine.py).tools= semantics, end to end
The HF chat template raises on any
tools=(deliberate: no schema text ever enters the prompt). This is safe becauseapply_chat_templateis not in the serving path:tools=[IPYTHON_SCHEMA]on every chat-completion (rlm/tools/registry.py— "always just ipython") → verifiers interceptiondialect.parse_requestextractstools→ renderersclient.generate(..., tools=tools)→ this renderer'srender(messages, tools=...). The renderer therefore accepts exactly[ipython]as validation-only (renders nothing); any other name or extra tool raises.apply_chat_template(tools=...)use (e.g. naive SFT preprocessing), where failing loudly is the correct signal that this format renders no schemas.Wiring
renderers/rlm.py—RlmRenderer(render/render_ids/parse_response/get_stop_token_ids/bridge_to_next_turn, per-token attribution matching the nemotron-3 conventions: assistant body+close sampled/content, scaffold tags neither).RlmRendererConfig(name="rlm") in configs + discriminated union; lazy registry,_populate_registry,MODEL_RENDERER_MAP["PrimeIntellect/RLM-Chat-Template"].PrimeIntellect/SyntheticData-GLM5.2-scaleswe-reward0 / scaleswe_rlm_glm51render through the renderer (197 clean; 3 raise on genuine data noise — a'ipy'tool-name typo). Tool calls in these traces arrive as flat JSON strings (verifiers trace shape) and compaction produces mid-list system messages; both are accepted, matching the jinja template's behavior.tests/test_rlm.py— 16 tests: byte parity with the jinja template at every prefix (with/without generation prompt), thinking retention, reasoning_content restoration, tools validation, tool-call rejection paths, parse round-trip (OK span + unclosed block), stop ids, bridge exact-extension + assistant rejection, config validation, content-mask invariants. The tokenizer fixture reconstructs the template repo from the public Nemotron-3 Super tokenizer, so CI needs no private-hub token. All pass locally (15 passed).🤖 Generated with Claude Code
Note
Add
RlmRendererfor the RLM chat format with inline ipython tool supportRlmRenderer, a deterministic renderer for the RLM chat format using single-token role tags (<system>,<user>,<assistant>,<ipython>, etc.).<ipython>code</ipython>; rejects other tool types or multiple calls.<think>...</think>(thinking retention is forced to"all").parse_responseextracts content and ipython code blocks intoParsedToolCallentries, handling both closed and unclosed blocks;bridge_to_next_turntrims to a closed assistant turn before appending new messages."rlm"and routes thePrimeIntellect/RLM-Chat-Templatemodel to it automatically.Macroscope summarized b62d804. (Automatic summaries will resume when PR exits draft mode or review begins).