renderers 0.1.10.dev11__tar.gz → 0.1.10.dev15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/.github/workflows/publish-dev.yml +1 -1
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/.github/workflows/publish.yml +1 -1
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/PKG-INFO +4 -4
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/README.md +2 -2
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/docs/renderer-config.md +16 -6
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/pyproject.toml +4 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/__init__.py +8 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/_version.py +2 -2
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/base.py +39 -6
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/configs.py +185 -22
- renderers-0.1.10.dev15/renderers/inkling.py +997 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/parsing.py +132 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/qwen35.py +70 -27
- renderers-0.1.10.dev15/renderers/qwen38.py +66 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/conftest.py +3 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_bridge.py +3 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_client.py +2 -1
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_disabled_thinking_stability.py +5 -0
- renderers-0.1.10.dev15/tests/test_inkling.py +523 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_multimodal.py +142 -7
- renderers-0.1.10.dev15/tests/test_qwen38.py +172 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_renderer_config.py +49 -2
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_renderer_config_parity.py +8 -4
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_roundtrip.py +3 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/uv.lock +48 -50
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/.github/workflows/style.yml +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/.github/workflows/test.yml +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/.gitignore +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/.pre-commit-config.yaml +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/LICENSE +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/examples/README.md +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/examples/sglang/multiturn_generate_sglang.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/examples/sglang/online_multiturn_sglang.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/examples/tinker/multiturn_generate_tinker.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/examples/transformers/multiturn_generate_transformers.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/examples/vllm/multiturn_generate_vllm.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/client.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/deepseek_r1.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/deepseek_v3.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/default.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/gemma4.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/glm45.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/glm5.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/gpt_oss.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/hy3.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/kimi_k2.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/kimi_k25.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/laguna_s21.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/laguna_xs2.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/llama_3.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/minimax_m2.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/nemotron3.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/parsers.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/prime_qwen3.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/qwen3.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/qwen36.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/renderers/qwen3_vl.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_build_helpers.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_deepseek_r1.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_gemma4.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_glm_tool_name_validation.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_gpt_oss_harmony_parity.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_hy3.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_incremental.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_is_content.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_kimi_k25_tool_schema.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_laguna_m1.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_laguna_s21.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_laguna_xs21.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_llama_3.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_load_tokenizer.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_message_indices.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_message_tool_names.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_nemotron3_parity.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_nemotron3_ultra.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_parse_response.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_parse_response_robustness.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_parsers.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_preserve_thinking.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_prime_qwen3_parity.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_qwen35_size_coverage.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_render_ids.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_sampled_mask.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_tokens_per_message.py +0 -0
- {renderers-0.1.10.dev11 → renderers-0.1.10.dev15}/tests/test_tool_arg_type_preservation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: renderers
|
|
3
|
-
Version: 0.1.10.
|
|
3
|
+
Version: 0.1.10.dev15
|
|
4
4
|
Summary: Chat template renderers — deterministic message-to-token conversion for LLM training
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -56,7 +56,7 @@ next_prompt_ids = r.bridge_to_next_turn(
|
|
|
56
56
|
)
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Hand-coded renderers ship for `qwen3`, `qwen3-vl`, `qwen3.5`, `qwen3.6`, `gemma4`, `glm-5`, `glm-5.1`, `glm-4.5`, `minimax-m2`, `deepseek-v3`, `deepseek-r1`, `kimi-k2`, `kimi-k2.5` / `kimi-k2.6`, `laguna-xs.2`, `laguna-xs-2.1`, `laguna-s-2.1`, `laguna-m.1`, `nemotron-3`, `nemotron-3-ultra`, `nemotron-3.5`, `llama-3`, `gpt-oss`, `hy3`, and `prime-qwen3`. Anything else falls back to `DefaultRenderer`, a generic `apply_chat_template` wrapper.
|
|
59
|
+
Hand-coded renderers ship for `qwen3`, `qwen3-vl`, `qwen3.5`, `qwen3.6`, `qwen3.8`, `gemma4`, `glm-5`, `glm-5.1`, `glm-4.5`, `minimax-m2`, `deepseek-v3`, `deepseek-r1`, `kimi-k2`, `kimi-k2.5` / `kimi-k2.6`, `laguna-xs.2`, `laguna-xs-2.1`, `laguna-s-2.1`, `laguna-m.1`, `nemotron-3`, `nemotron-3-ultra`, `nemotron-3.5`, `llama-3`, `gpt-oss`, `hy3`, `inkling` / `inkling-small`, and `prime-qwen3`. Anything else falls back to `DefaultRenderer`, a generic `apply_chat_template` wrapper. `qwen3-vl`, `qwen3.5`, `qwen3.6`, `qwen3.8`, `gemma4`, `kimi-k2.5` / `kimi-k2.6`, and the Inkling checkpoints are multimodal (Inkling handles both image **and** audio).
|
|
60
60
|
|
|
61
61
|
## API
|
|
62
62
|
|
|
@@ -159,7 +159,7 @@ renderer = create_renderer(
|
|
|
159
159
|
|
|
160
160
|
Discriminated union: every per-renderer config is a variant of `RendererConfig`, dispatched on the `name` field. Bogus combinations (e.g. `add_vision_id` under `name="qwen3"`) error at construction with a `pydantic.ValidationError`. Downstream pydantic configs (prime-rl orchestrator, verifiers `ClientConfig`) hold a single field typed as `RendererConfig` and inherit the same strict-per-variant validation.
|
|
161
161
|
|
|
162
|
-
When `chat_template_kwargs` is passed with `config=None` / `AutoRendererConfig`, renderers first resolves the concrete renderer from the model name, then validates
|
|
162
|
+
When `chat_template_kwargs` is passed with `config=None` / `AutoRendererConfig`, renderers first resolves the concrete renderer from the model name, then validates each key against that renderer's explicit template-kwarg allowlist. Renderer-only fields such as `image_cache_max` must be passed through the typed config instead. `Auto + unknown model + chat_template_kwargs` fails loudly; use an explicit typed config or explicit `DefaultRendererConfig` for opaque fallback templates.
|
|
163
163
|
|
|
164
164
|
One shared behaviour flag lives on typed renderer configs: `thinking_retention`, an optional bridge-policy override. Leave it unset to derive bridge behaviour from the chat template and its renderer-exposed kwargs.
|
|
165
165
|
|
|
@@ -40,7 +40,7 @@ next_prompt_ids = r.bridge_to_next_turn(
|
|
|
40
40
|
)
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
Hand-coded renderers ship for `qwen3`, `qwen3-vl`, `qwen3.5`, `qwen3.6`, `gemma4`, `glm-5`, `glm-5.1`, `glm-4.5`, `minimax-m2`, `deepseek-v3`, `deepseek-r1`, `kimi-k2`, `kimi-k2.5` / `kimi-k2.6`, `laguna-xs.2`, `laguna-xs-2.1`, `laguna-s-2.1`, `laguna-m.1`, `nemotron-3`, `nemotron-3-ultra`, `nemotron-3.5`, `llama-3`, `gpt-oss`, `hy3`, and `prime-qwen3`. Anything else falls back to `DefaultRenderer`, a generic `apply_chat_template` wrapper.
|
|
43
|
+
Hand-coded renderers ship for `qwen3`, `qwen3-vl`, `qwen3.5`, `qwen3.6`, `qwen3.8`, `gemma4`, `glm-5`, `glm-5.1`, `glm-4.5`, `minimax-m2`, `deepseek-v3`, `deepseek-r1`, `kimi-k2`, `kimi-k2.5` / `kimi-k2.6`, `laguna-xs.2`, `laguna-xs-2.1`, `laguna-s-2.1`, `laguna-m.1`, `nemotron-3`, `nemotron-3-ultra`, `nemotron-3.5`, `llama-3`, `gpt-oss`, `hy3`, `inkling` / `inkling-small`, and `prime-qwen3`. Anything else falls back to `DefaultRenderer`, a generic `apply_chat_template` wrapper. `qwen3-vl`, `qwen3.5`, `qwen3.6`, `qwen3.8`, `gemma4`, `kimi-k2.5` / `kimi-k2.6`, and the Inkling checkpoints are multimodal (Inkling handles both image **and** audio).
|
|
44
44
|
|
|
45
45
|
## API
|
|
46
46
|
|
|
@@ -143,7 +143,7 @@ renderer = create_renderer(
|
|
|
143
143
|
|
|
144
144
|
Discriminated union: every per-renderer config is a variant of `RendererConfig`, dispatched on the `name` field. Bogus combinations (e.g. `add_vision_id` under `name="qwen3"`) error at construction with a `pydantic.ValidationError`. Downstream pydantic configs (prime-rl orchestrator, verifiers `ClientConfig`) hold a single field typed as `RendererConfig` and inherit the same strict-per-variant validation.
|
|
145
145
|
|
|
146
|
-
When `chat_template_kwargs` is passed with `config=None` / `AutoRendererConfig`, renderers first resolves the concrete renderer from the model name, then validates
|
|
146
|
+
When `chat_template_kwargs` is passed with `config=None` / `AutoRendererConfig`, renderers first resolves the concrete renderer from the model name, then validates each key against that renderer's explicit template-kwarg allowlist. Renderer-only fields such as `image_cache_max` must be passed through the typed config instead. `Auto + unknown model + chat_template_kwargs` fails loudly; use an explicit typed config or explicit `DefaultRendererConfig` for opaque fallback templates.
|
|
147
147
|
|
|
148
148
|
One shared behaviour flag lives on typed renderer configs: `thinking_retention`, an optional bridge-policy override. Leave it unset to derive bridge behaviour from the chat template and its renderer-exposed kwargs.
|
|
149
149
|
|
|
@@ -19,8 +19,10 @@ construction.
|
|
|
19
19
|
|
|
20
20
|
## Per-renderer configs
|
|
21
21
|
|
|
22
|
-
Use `type(config).template_field_names()` to inspect the
|
|
23
|
-
|
|
22
|
+
Use `type(config).template_field_names()` to inspect the explicit allowlist of
|
|
23
|
+
fields accepted through `chat_template_kwargs`. Every renderer-specific field
|
|
24
|
+
is classified as either a template field or a renderer-only field at class
|
|
25
|
+
definition time. Template fields are covered by parity tests against
|
|
24
26
|
`apply_chat_template` in `tests/test_renderer_config_parity.py`.
|
|
25
27
|
|
|
26
28
|
| Renderer | Config class | Template fields | Renderer-only fields |
|
|
@@ -29,6 +31,7 @@ chat-template kwargs. Those fields are covered by parity tests against
|
|
|
29
31
|
| PrimeIntellect Qwen3 | `PrimeQwen3RendererConfig` | - | - |
|
|
30
32
|
| Qwen3.5 | `Qwen35RendererConfig` | `enable_thinking`, `add_vision_id` | `image_cache_max` |
|
|
31
33
|
| Qwen3.6 | `Qwen36RendererConfig` | `enable_thinking`, `add_vision_id`, `preserve_thinking` | `image_cache_max` |
|
|
34
|
+
| Qwen3.8 | `Qwen38RendererConfig` | `enable_thinking`, `add_vision_id`, `preserve_thinking`, `reasoning_effort` | `image_cache_max` |
|
|
32
35
|
| Qwen3-VL | `Qwen3VLRendererConfig` | `add_vision_id` | `image_cache_max` |
|
|
33
36
|
| Gemma 4 | `Gemma4RendererConfig` | `enable_thinking`, `preserve_thinking` | `image_cache_max` |
|
|
34
37
|
| GLM-5 / 5.1 | `GLM5RendererConfig` / `GLM51RendererConfig` | `enable_thinking`, `clear_thinking` | - |
|
|
@@ -37,6 +40,7 @@ chat-template kwargs. Those fields are covered by parity tests against
|
|
|
37
40
|
| Hy3 | `Hy3RendererConfig` | `reasoning_effort`, `preserved_thinking`, `is_training`, `raw_last_assistant`, `fallback_strategy` | - |
|
|
38
41
|
| Kimi K2 | `KimiK2RendererConfig` | - | `enable_thinking` |
|
|
39
42
|
| Kimi K2.5 / 2.6 | `KimiK25RendererConfig` | `thinking` | `image_cache_max` |
|
|
43
|
+
| Inkling / Inkling-Small | `InklingRendererConfig` | `reasoning_effort` | `image_cache_max`, `audio_cache_max` |
|
|
40
44
|
| Laguna XS.2 | `LagunaXS2RendererConfig` | `enable_thinking`, `render_assistant_messages_raw` | - |
|
|
41
45
|
| Laguna M.1 | `LagunaM1RendererConfig` | `enable_thinking`, `render_assistant_messages_raw` | - |
|
|
42
46
|
| Laguna XS-2.1 | `LagunaXS21RendererConfig` | `enable_thinking` | - |
|
|
@@ -80,8 +84,10 @@ pool = create_renderer_pool(
|
|
|
80
84
|
```
|
|
81
85
|
|
|
82
86
|
Renderers resolves auto configs before applying `chat_template_kwargs`, so the
|
|
83
|
-
kwargs validate against the concrete renderer
|
|
84
|
-
that conflict with an explicit
|
|
87
|
+
kwargs validate against the concrete renderer's template-field allowlist.
|
|
88
|
+
Unknown kwargs, renderer-only fields, or kwargs that conflict with an explicit
|
|
89
|
+
`thinking_retention` fail at construction. Renderer-only options remain valid
|
|
90
|
+
when supplied through the typed config itself.
|
|
85
91
|
|
|
86
92
|
Auto-resolution fails loudly for VLMs without an exact registered renderer.
|
|
87
93
|
Text-only unknown models fall back to `DefaultRenderer`, unless
|
|
@@ -90,7 +96,10 @@ cannot implement selective bridge retention, so that combination raises.
|
|
|
90
96
|
`AutoRendererConfig` with `chat_template_kwargs` also raises for unknown models,
|
|
91
97
|
because renderers cannot validate those kwargs without a concrete renderer.
|
|
92
98
|
Use an explicit model-specific config, or `DefaultRendererConfig(...)` when you
|
|
93
|
-
intentionally want opaque `apply_chat_template` kwargs.
|
|
99
|
+
intentionally want opaque `apply_chat_template` kwargs. Even for the default
|
|
100
|
+
renderer, typed fields such as `tool_parser`, `reasoning_parser`, and
|
|
101
|
+
`thinking_retention` must be passed through the config rather than through the
|
|
102
|
+
opaque kwargs mapping.
|
|
94
103
|
|
|
95
104
|
## `thinking_retention`
|
|
96
105
|
|
|
@@ -132,6 +141,7 @@ the knobs its template actually exposes:
|
|
|
132
141
|
| Qwen3 | `enable_thinking=False -> all`, else `tool_cycle` |
|
|
133
142
|
| Qwen3.5 | `enable_thinking=False -> all`, else `tool_cycle` |
|
|
134
143
|
| Qwen3.6 | `preserve_thinking=True -> all`; else `enable_thinking=False -> all`; else `tool_cycle` |
|
|
144
|
+
| Qwen3.8 | `preserve_thinking=True -> all`; else `enable_thinking=False -> all`; else `tool_cycle` |
|
|
135
145
|
| Gemma 4 | `preserve_thinking=True -> all`; else `enable_thinking=False -> all`; else `tool_cycle` |
|
|
136
146
|
| GLM-5 / 5.1 | `clear_thinking=False -> all`; else `enable_thinking=False -> all`; else `tool_cycle` |
|
|
137
147
|
| GLM-4.5 | `enable_thinking=False -> all`, else `tool_cycle` |
|
|
@@ -141,7 +151,7 @@ the knobs its template actually exposes:
|
|
|
141
151
|
| Nemotron-3 / 3.5 | `truncate_history_thinking=False -> all`; else `enable_thinking=False -> all`; else `tool_cycle` |
|
|
142
152
|
| DeepSeek R1 | `template` |
|
|
143
153
|
| MiniMax M2 | `tool_cycle` |
|
|
144
|
-
| DeepSeek V3, Qwen3-VL, Kimi K2, Laguna XS.2 / M.1 / XS-2.1 / S-2.1, Llama 3 | `all` |
|
|
154
|
+
| DeepSeek V3, Qwen3-VL, Kimi K2, Laguna XS.2 / M.1 / XS-2.1 / S-2.1, Llama 3, Inkling | `all` |
|
|
145
155
|
| PrimeIntellect Qwen3 | `all` |
|
|
146
156
|
|
|
147
157
|
Config construction raises when an explicit template knob directly contradicts
|
|
@@ -19,6 +19,10 @@ dependencies = [
|
|
|
19
19
|
"openai>=1.108.1",
|
|
20
20
|
"tiktoken",
|
|
21
21
|
"jinja2",
|
|
22
|
+
# Keep this floor compatible with prime-rl's transformers pin. Inkling's
|
|
23
|
+
# tokenizer and text-only renderer work on older releases; image/audio
|
|
24
|
+
# processing fails lazily with an upgrade message when InklingProcessor is
|
|
25
|
+
# unavailable (native support starts in transformers 5.14).
|
|
22
26
|
"transformers>=4.50.0",
|
|
23
27
|
# Used by GptOssRenderer to render and parse harmony tokens. Vendoring
|
|
24
28
|
# OpenAI's reference implementation keeps us byte-identical with vLLM
|
|
@@ -53,6 +53,7 @@ from renderers.configs import (
|
|
|
53
53
|
Gemma4RendererConfig,
|
|
54
54
|
GptOssRendererConfig,
|
|
55
55
|
Hy3RendererConfig,
|
|
56
|
+
InklingRendererConfig,
|
|
56
57
|
KimiK25RendererConfig,
|
|
57
58
|
KimiK2RendererConfig,
|
|
58
59
|
LagunaM1RendererConfig,
|
|
@@ -67,6 +68,7 @@ from renderers.configs import (
|
|
|
67
68
|
PrimeQwen3RendererConfig,
|
|
68
69
|
Qwen35RendererConfig,
|
|
69
70
|
Qwen36RendererConfig,
|
|
71
|
+
Qwen38RendererConfig,
|
|
70
72
|
Qwen3RendererConfig,
|
|
71
73
|
Qwen3VLRendererConfig,
|
|
72
74
|
RendererConfig,
|
|
@@ -93,6 +95,7 @@ _LAZY_RENDERERS: dict[str, str] = {
|
|
|
93
95
|
"GptOssRenderer": "renderers.gpt_oss",
|
|
94
96
|
"Gemma4Renderer": "renderers.gemma4",
|
|
95
97
|
"Hy3Renderer": "renderers.hy3",
|
|
98
|
+
"InklingRenderer": "renderers.inkling",
|
|
96
99
|
"KimiK25Renderer": "renderers.kimi_k25",
|
|
97
100
|
"KimiK2Renderer": "renderers.kimi_k2",
|
|
98
101
|
"LagunaM1Renderer": "renderers.laguna_xs2",
|
|
@@ -107,6 +110,7 @@ _LAZY_RENDERERS: dict[str, str] = {
|
|
|
107
110
|
"PrimeQwen3Renderer": "renderers.prime_qwen3",
|
|
108
111
|
"Qwen35Renderer": "renderers.qwen35",
|
|
109
112
|
"Qwen36Renderer": "renderers.qwen36",
|
|
113
|
+
"Qwen38Renderer": "renderers.qwen38",
|
|
110
114
|
"Qwen3Renderer": "renderers.qwen3",
|
|
111
115
|
"Qwen3VLRenderer": "renderers.qwen3_vl",
|
|
112
116
|
}
|
|
@@ -151,6 +155,8 @@ __all__ = [
|
|
|
151
155
|
"Hy3Renderer",
|
|
152
156
|
"Hy3RendererConfig",
|
|
153
157
|
"ImagePart",
|
|
158
|
+
"InklingRenderer",
|
|
159
|
+
"InklingRendererConfig",
|
|
154
160
|
"KimiK25Renderer",
|
|
155
161
|
"KimiK25RendererConfig",
|
|
156
162
|
"KimiK2Renderer",
|
|
@@ -188,6 +194,8 @@ __all__ = [
|
|
|
188
194
|
"Qwen35RendererConfig",
|
|
189
195
|
"Qwen36Renderer",
|
|
190
196
|
"Qwen36RendererConfig",
|
|
197
|
+
"Qwen38Renderer",
|
|
198
|
+
"Qwen38RendererConfig",
|
|
191
199
|
"Qwen3Renderer",
|
|
192
200
|
"Qwen3RendererConfig",
|
|
193
201
|
"Qwen3VLRenderer",
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.1.10.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1, 10, '
|
|
21
|
+
__version__ = version = '0.1.10.dev15'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 10, 'dev15')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -794,10 +794,10 @@ class MultimodalRenderer(Renderer, Protocol):
|
|
|
794
794
|
"""A :class:`Renderer` that supports multimodal inputs (images, video).
|
|
795
795
|
|
|
796
796
|
Concrete classes (``Qwen3VLRenderer``, ``Qwen35Renderer``,
|
|
797
|
-
``Qwen36Renderer``, ``KimiK25Renderer``) implement
|
|
798
|
-
structurally — no explicit inheritance required.
|
|
799
|
-
to drive vLLM's ``multi_modal_data`` features field or
|
|
800
|
-
forward across turns should dispatch on ``isinstance(r,
|
|
797
|
+
``Qwen36Renderer``, ``Qwen38Renderer``, ``KimiK25Renderer``) implement
|
|
798
|
+
this Protocol structurally — no explicit inheritance required.
|
|
799
|
+
Callers that need to drive vLLM's ``multi_modal_data`` features field or
|
|
800
|
+
carry images forward across turns should dispatch on ``isinstance(r,
|
|
801
801
|
MultimodalRenderer)`` and use the extended ``bridge_to_next_turn``
|
|
802
802
|
signature below.
|
|
803
803
|
"""
|
|
@@ -1031,6 +1031,8 @@ MODEL_RENDERER_MAP: dict[str, str] = {
|
|
|
1031
1031
|
"Qwen/Qwen3.5-397B-A17B": "qwen3.5",
|
|
1032
1032
|
# Qwen3.6.
|
|
1033
1033
|
"Qwen/Qwen3.6-35B-A3B": "qwen3.6",
|
|
1034
|
+
# Qwen3.8.
|
|
1035
|
+
"Qwen/Qwen3.8-27B": "qwen3.8",
|
|
1034
1036
|
# Qwen3-VL.
|
|
1035
1037
|
"Qwen/Qwen3-VL-4B-Instruct": "qwen3-vl",
|
|
1036
1038
|
"Qwen/Qwen3-VL-8B-Instruct": "qwen3-vl",
|
|
@@ -1093,6 +1095,10 @@ MODEL_RENDERER_MAP: dict[str, str] = {
|
|
|
1093
1095
|
# GPT-OSS.
|
|
1094
1096
|
"openai/gpt-oss-20b": "gpt-oss",
|
|
1095
1097
|
"openai/gpt-oss-120b": "gpt-oss",
|
|
1098
|
+
# Thinking Machines Inkling checkpoints share byte-identical tokenizer,
|
|
1099
|
+
# chat-template, and processor assets (vision + audio; transformers >= 5.14).
|
|
1100
|
+
"thinkingmachines/Inkling": "inkling",
|
|
1101
|
+
"thinkingmachines/Inkling-Small": "inkling",
|
|
1096
1102
|
# Tencent Hunyuan Hy3 (295B-A21B MoE). The FP8 checkpoint shares the same
|
|
1097
1103
|
# tokenizer and chat template. Hy3-preview is deliberately unmapped: it
|
|
1098
1104
|
# ships an older, incompatible template (un-suffixed special tokens,
|
|
@@ -1132,6 +1138,8 @@ MULTIMODAL_MODELS: dict[str, set[str]] = {
|
|
|
1132
1138
|
# Qwen3.6 extends Qwen3.5's chat template; same VL bits, only
|
|
1133
1139
|
# tool-call argument serialization differs.
|
|
1134
1140
|
"Qwen/Qwen3.6-35B-A3B": {"image"},
|
|
1141
|
+
# Qwen3.8 adds reasoning-effort control and preserves thinking by default.
|
|
1142
|
+
"Qwen/Qwen3.8-27B": {"image"},
|
|
1135
1143
|
# Kimi K2.5 / K2.6 are unified VLMs (HF tag ``image-text-to-text``)
|
|
1136
1144
|
# with custom processor (``KimiK25Processor`` + ``KimiK25VisionProcessor``).
|
|
1137
1145
|
# Vision wrap is different from Qwen-VL:
|
|
@@ -1141,6 +1149,8 @@ MULTIMODAL_MODELS: dict[str, set[str]] = {
|
|
|
1141
1149
|
# ``grid_thws``.
|
|
1142
1150
|
"moonshotai/Kimi-K2.5": {"image"},
|
|
1143
1151
|
"moonshotai/Kimi-K2.6": {"image"},
|
|
1152
|
+
"thinkingmachines/Inkling": {"image", "audio"},
|
|
1153
|
+
"thinkingmachines/Inkling-Small": {"image", "audio"},
|
|
1144
1154
|
}
|
|
1145
1155
|
|
|
1146
1156
|
|
|
@@ -1340,6 +1350,7 @@ def _populate_registry():
|
|
|
1340
1350
|
from renderers.gpt_oss import GptOssRenderer
|
|
1341
1351
|
from renderers.gemma4 import Gemma4Renderer
|
|
1342
1352
|
from renderers.hy3 import Hy3Renderer
|
|
1353
|
+
from renderers.inkling import InklingRenderer
|
|
1343
1354
|
from renderers.kimi_k2 import KimiK2Renderer
|
|
1344
1355
|
from renderers.kimi_k25 import KimiK25Renderer
|
|
1345
1356
|
from renderers.laguna_s21 import LagunaS21Renderer
|
|
@@ -1360,6 +1371,7 @@ def _populate_registry():
|
|
|
1360
1371
|
from renderers.qwen3_vl import Qwen3VLRenderer
|
|
1361
1372
|
from renderers.qwen35 import Qwen35Renderer
|
|
1362
1373
|
from renderers.qwen36 import Qwen36Renderer
|
|
1374
|
+
from renderers.qwen38 import Qwen38Renderer
|
|
1363
1375
|
|
|
1364
1376
|
RENDERER_REGISTRY.update(
|
|
1365
1377
|
{
|
|
@@ -1370,6 +1382,7 @@ def _populate_registry():
|
|
|
1370
1382
|
"gemma4": Gemma4Renderer,
|
|
1371
1383
|
"qwen3.5": Qwen35Renderer,
|
|
1372
1384
|
"qwen3.6": Qwen36Renderer,
|
|
1385
|
+
"qwen3.8": Qwen38Renderer,
|
|
1373
1386
|
"glm-5": GLM5Renderer,
|
|
1374
1387
|
"glm-5.1": GLM51Renderer,
|
|
1375
1388
|
"glm-4.5": GLM45Renderer,
|
|
@@ -1377,6 +1390,7 @@ def _populate_registry():
|
|
|
1377
1390
|
"deepseek-v3": DeepSeekV3Renderer,
|
|
1378
1391
|
"deepseek-r1": DeepSeekR1Renderer,
|
|
1379
1392
|
"hy3": Hy3Renderer,
|
|
1393
|
+
"inkling": InklingRenderer,
|
|
1380
1394
|
"kimi-k2": KimiK2Renderer,
|
|
1381
1395
|
"kimi-k2.5": KimiK25Renderer,
|
|
1382
1396
|
"laguna-xs.2": LagunaXS2Renderer,
|
|
@@ -1483,12 +1497,31 @@ def _merge_chat_template_kwargs(
|
|
|
1483
1497
|
return config
|
|
1484
1498
|
if not isinstance(chat_template_kwargs, Mapping):
|
|
1485
1499
|
raise TypeError("chat_template_kwargs must be a mapping.")
|
|
1500
|
+
kwargs = dict(chat_template_kwargs)
|
|
1501
|
+
config_cls = type(config)
|
|
1502
|
+
allowed = config_cls.template_field_names()
|
|
1503
|
+
if config_cls._allow_opaque_template_kwargs:
|
|
1504
|
+
reserved = frozenset(config_cls.model_fields) - allowed - {"name"}
|
|
1505
|
+
unsupported = frozenset(kwargs) & reserved
|
|
1506
|
+
else:
|
|
1507
|
+
unsupported = frozenset(kwargs) - allowed
|
|
1508
|
+
if unsupported:
|
|
1509
|
+
allowed_text = (
|
|
1510
|
+
"opaque Jinja kwargs"
|
|
1511
|
+
if config_cls._allow_opaque_template_kwargs
|
|
1512
|
+
else ", ".join(sorted(allowed)) or "(none)"
|
|
1513
|
+
)
|
|
1514
|
+
raise ValueError(
|
|
1515
|
+
f"Unsupported chat_template_kwargs for {config.name!r}: "
|
|
1516
|
+
f"{sorted(unsupported)}. Allowed: {allowed_text}. Pass "
|
|
1517
|
+
"renderer-internal options through the typed config instead."
|
|
1518
|
+
)
|
|
1486
1519
|
data: dict[str, Any] = {"name": config.name}
|
|
1487
1520
|
for field_name in config.__pydantic_fields_set__:
|
|
1488
1521
|
data[field_name] = getattr(config, field_name)
|
|
1489
1522
|
data.update(getattr(config, "model_extra", None) or {})
|
|
1490
|
-
data.update(
|
|
1491
|
-
return
|
|
1523
|
+
data.update(kwargs)
|
|
1524
|
+
return config_cls.model_validate(data)
|
|
1492
1525
|
|
|
1493
1526
|
|
|
1494
1527
|
def _resolve_renderer_config(
|