Skip to content

feat: add DeepSeek-V4.1-Flash renderer - #192

Draft
samsja wants to merge 6 commits into
mainfrom
feat/deepseek-v4.1-renderer
Draft

samsja wants to merge 6 commits into
mainfrom
feat/deepseek-v4.1-renderer

Conversation

@samsja

@samsja samsja commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds a deepseek-v4.1 renderer for DeepSeek-V4.1-Flash, moved here from prime-rl's example custom renderer (PrimeIntellect-ai/prime-rl#4057) so configs can select it by name (including on hosted training, where a repo-relative import_path does not resolve).

For plain chats, V4.1's reference encoder (encoding/encoding.py in the checkpoint) is V4's with three changes, applied on top of DeepSeekV4Renderer:

  • a <|System|> token leads the conversation whenever it opens with a reasoning-effort prefix or a system message;
  • the reasoning effort is a numeric budget, Reasoning Effort: {budget} (range 1-100, ...), thinking mode only, default high (75); low / high / max map to 50 / 75 / 100;
  • thinking mode is the default.

A leading inline <think>...</think> in an assistant's content moves into reasoning_content, as other renderers do.

Not supported yet: tool calls (V4.1 renamed the DSML tags) and mid-conversation system messages; both raise NotImplementedError. bridge_to_next_turn returns None (full re-render) since V4's extension path would emit V4's tags.

Selected by name only (name = "deepseek-v4.1"): it is not in MODEL_RENDERER_MAP, because auto-mapped renderers must pass the shared parity suites, which need tool support.

Test plan

  • tests/test_deepseek_v41.py: token-for-token parity with the checkpoint's shipped encoding/encoding.py (downloaded from the Hub) over 4 conversations × thinking on/off × effort low/high/max/30; config discriminator and effort range; inline-reasoning split; tool and mid-conversation system rejection.
  • pytest tests/test_deepseek_v41.py tests/test_deepseek_v4.py tests/test_renderer_config.py tests/test_reasoning_boundaries.py: 989 passed.

🤖 Generated with Claude Code

Note

Add DeepSeekV41Renderer for DeepSeek-V4.1-Flash

  • Adds a new renderer subclassing DeepSeekV4Renderer in deepseek_v41.py, with thinking enabled by default and a reasoning_effort field accepting low, high, max, or integers 1–100 (named levels map to budgets 50, 75, 100).
  • Registers deepseek-v4.1 in the renderer name registry, the lazy renderer map, and the RendererConfig discriminated union in configs.py and base.py.
  • Rendering rejects non-empty tool lists and system messages after the first message (NotImplementedError), and splits a leading inline think block in assistant messages into separate reasoning content.
  • Tests in test_deepseek_v41.py check output parity with the checkpoint encoder across 32 combinations of conversation, thinking mode, and reasoning effort, plus config validation and rejection cases.
  • Risk: bridge_to_next_turn on DeepSeekV41Renderer always returns None, so incremental turn bridging is unavailable for this model.

Macroscope summarized c949a28. (Automatic summaries will resume when PR exits draft mode or review begins).

samsja and others added 2 commits October 15, 2026 01:42
V4's encoder with V4.1's System token, numeric reasoning-effort budget and
thinking-by-default, for plain chats (no tools, no mid-conversation system
messages). Selected by name; tested against the checkpoint's shipped
encoding/encoding.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copy messages instead of unpacking them into a TypedDict literal, reject
non-text system content, and drop unneeded type-ignore comments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
samsja added a commit to PrimeIntellect-ai/prime-rl that referenced this pull request Oct 15, 2026
…-V4.1-Flash

Bump deps/renderers to PrimeIntellect-ai/renderers#192, which ships the V4.1
renderer, and drop the example's custom renderer file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
samsja and others added 4 commits October 21, 2026 08:49
The V4.1 renderer now renders tools, assistant tool calls and tool results
like the checkpoint's encoding/encoding.py, and parses completions with
vLLM's deepseek_v41 DSML format:

- DSML tags are space-prefixed: <|DSML| calls>, <|DSML| invoke>,
  <|DSML| parameter>, in the tools block, the rendered calls and the parser.
- Tools attach to a leading system message, or to an empty one that the
  <|System|> token opens.
- A user turn holding only tool results does not start a new turn, so
  dropped historical reasoning stops at the last real user message.
- JSON-string arguments may be double-encoded; arguments that do not decode
  to an object render as a single "arguments" parameter.
- The prefix-extension bridge is enabled again.

DeepSeekV4Renderer gains small hooks for these (tag names, grammar, preamble,
turn start, tool target, argument decoding); its output is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant