renderers 0.1.12.dev20__tar.gz → 0.1.13.dev5__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.12.dev20 → renderers-0.1.13.dev5}/PKG-INFO +2 -2
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/README.md +1 -1
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/docs/renderer-config.md +2 -2
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/__init__.py +4 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/_version.py +2 -2
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/base.py +9 -1
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/client.py +32 -3
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/configs.py +9 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/glm5.py +326 -35
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/parity.py +5 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_client.py +27 -0
- renderers-0.1.13.dev5/tests/test_glm53_flash.py +624 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_reasoning_boundaries.py +2 -1
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/.github/workflows/publish-dev.yml +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/.github/workflows/publish.yml +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/.github/workflows/style.yml +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/.github/workflows/test.yml +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/.gitignore +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/.pre-commit-config.yaml +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/LICENSE +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/examples/README.md +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/examples/sglang/multiturn_generate_sglang.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/examples/sglang/online_multiturn_sglang.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/examples/tinker/multiturn_generate_tinker.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/examples/transformers/multiturn_generate_transformers.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/examples/vllm/multiturn_generate_vllm.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/pyproject.toml +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/custom.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/deepseek_r1.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/deepseek_v3.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/deepseek_v4.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/default.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/gemma4.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/glm45.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/gpt_oss.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/hy3.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/inkling.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/kimi_k2.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/kimi_k25.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/laguna_s21.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/laguna_xs2.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/llama_3.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/minimax_m2.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/nemotron3.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/parsers.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/parsing.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/prime_qwen3.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/qwen3.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/qwen35.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/qwen36.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/qwen38.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/qwen3_vl.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/reasoning.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/renderers/tagged.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/audit_prefix_stability.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/conftest.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/fixtures/prefix_stability.json +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/reference_continuations.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/reference_rendering.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/replay.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_bridge.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_build_helpers.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_custom.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_deepseek_r1.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_deepseek_v4.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_disabled_thinking_stability.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_gemma4.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_glm_tool_name_validation.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_hy3.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_incremental.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_inkling.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_is_content.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_kimi_k25_tool_schema.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_laguna_m1.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_laguna_xs21.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_llama_3.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_load_tokenizer.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_message_indices.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_message_tool_names.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_multimodal.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_nemotron35_vlm.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_nemotron3_ultra.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_offsetless_tokenizers.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_parity.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_parse_response.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_parse_response_robustness.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_parsers.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_preserve_thinking.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_qwen35_size_coverage.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_qwen38.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_renderer_config.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_roundtrip.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_sampled_mask.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_tagged_rollout.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_tokens_per_message.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/tests/test_tool_arg_type_preservation.py +0 -0
- {renderers-0.1.12.dev20 → renderers-0.1.13.dev5}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: renderers
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.13.dev5
|
|
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
|
|
@@ -114,7 +114,7 @@ next_prompt_ids = r.bridge_to_next_turn(
|
|
|
114
114
|
)
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
Hand-coded renderers ship for `qwen3`, `qwen3-vl`, `qwen3.5`, `qwen3.6`, `qwen3.8`, `gemma4`, `glm-5`, `glm-5.1`, `glm-5.3`, `glm-4.5`, `minimax-m2`, `deepseek-v3`, `deepseek-r1`, `deepseek-v4` (V4 Flash 0731), `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).
|
|
117
|
+
Hand-coded renderers ship for `qwen3`, `qwen3-vl`, `qwen3.5`, `qwen3.6`, `qwen3.8`, `gemma4`, `glm-5`, `glm-5.1`, `glm-5.3`, `glm-5.3-flash`, `glm-4.5`, `minimax-m2`, `deepseek-v3`, `deepseek-r1`, `deepseek-v4` (V4 Flash 0731), `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`, `glm-5.3-flash`, `kimi-k2.5` / `kimi-k2.6`, and the Inkling checkpoints are multimodal (Inkling handles both image **and** audio; `glm-5.3-flash` renders images only with `process_multimodal=False`).
|
|
118
118
|
|
|
119
119
|
## API
|
|
120
120
|
|
|
@@ -94,7 +94,7 @@ next_prompt_ids = r.bridge_to_next_turn(
|
|
|
94
94
|
)
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
Hand-coded renderers ship for `qwen3`, `qwen3-vl`, `qwen3.5`, `qwen3.6`, `qwen3.8`, `gemma4`, `glm-5`, `glm-5.1`, `glm-5.3`, `glm-4.5`, `minimax-m2`, `deepseek-v3`, `deepseek-r1`, `deepseek-v4` (V4 Flash 0731), `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).
|
|
97
|
+
Hand-coded renderers ship for `qwen3`, `qwen3-vl`, `qwen3.5`, `qwen3.6`, `qwen3.8`, `gemma4`, `glm-5`, `glm-5.1`, `glm-5.3`, `glm-5.3-flash`, `glm-4.5`, `minimax-m2`, `deepseek-v3`, `deepseek-r1`, `deepseek-v4` (V4 Flash 0731), `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`, `glm-5.3-flash`, `kimi-k2.5` / `kimi-k2.6`, and the Inkling checkpoints are multimodal (Inkling handles both image **and** audio; `glm-5.3-flash` renders images only with `process_multimodal=False`).
|
|
98
98
|
|
|
99
99
|
## API
|
|
100
100
|
|
|
@@ -34,7 +34,7 @@ product in `tests/test_parity.py`.
|
|
|
34
34
|
| Qwen3-VL | `Qwen3VLRendererConfig` | `add_vision_id` | `image_cache_max` |
|
|
35
35
|
| Gemma 4 | `Gemma4RendererConfig` | `enable_thinking`, `preserve_thinking` | `image_cache_max` |
|
|
36
36
|
| GLM-5 / 5.1 | `GLM5RendererConfig` / `GLM51RendererConfig` | `enable_thinking`, `clear_thinking` | - |
|
|
37
|
-
| GLM-5.3 | `GLM53RendererConfig` | `clear_thinking`, `reasoning_effort` | - |
|
|
37
|
+
| GLM-5.3 / 5.3 Flash | `GLM53RendererConfig` / `GLM53FlashRendererConfig` | `clear_thinking`, `reasoning_effort` | - |
|
|
38
38
|
| GLM-4.5 | `GLM45RendererConfig` | `enable_thinking` | - |
|
|
39
39
|
| gpt-oss | `GptOssRendererConfig` | `reasoning_effort`, `conversation_start_date` | `use_system_prompt`, `knowledge_cutoff`, `model_identity`, `auto_drop_analysis` |
|
|
40
40
|
| Hy3 | `Hy3RendererConfig` | `reasoning_effort`, `preserved_thinking`, `is_training`, `raw_last_assistant`, `fallback_strategy` | - |
|
|
@@ -141,7 +141,7 @@ the knobs its template actually exposes:
|
|
|
141
141
|
| Qwen3.8 | `preserve_thinking=True -> all`; else `enable_thinking=False -> all`; else `tool_cycle` |
|
|
142
142
|
| Gemma 4 | `preserve_thinking=True -> all`; else `enable_thinking=False -> all`; else `tool_cycle` |
|
|
143
143
|
| GLM-5 / 5.1 | `clear_thinking=False -> all`; else `enable_thinking=False -> all`; else `tool_cycle` |
|
|
144
|
-
| GLM-5.3 | `clear_thinking=False -> all`, else `tool_cycle` |
|
|
144
|
+
| GLM-5.3 / 5.3 Flash | `clear_thinking=False -> all`, else `tool_cycle` |
|
|
145
145
|
| GLM-4.5 | `enable_thinking=False -> all`, else `tool_cycle` |
|
|
146
146
|
| gpt-oss | `auto_drop_analysis=False -> all`, else `tool_cycle` |
|
|
147
147
|
| Hy3 | `preserved_thinking=True -> all`, else `tool_cycle` |
|
|
@@ -55,6 +55,7 @@ from renderers.configs import (
|
|
|
55
55
|
GLM5RendererConfig,
|
|
56
56
|
GLM45RendererConfig,
|
|
57
57
|
GLM51RendererConfig,
|
|
58
|
+
GLM53FlashRendererConfig,
|
|
58
59
|
GLM53RendererConfig,
|
|
59
60
|
GptOssRendererConfig,
|
|
60
61
|
Hy3RendererConfig,
|
|
@@ -95,6 +96,7 @@ _LAZY_RENDERERS: dict[str, str] = {
|
|
|
95
96
|
"DefaultRenderer": "renderers.default",
|
|
96
97
|
"GLM45Renderer": "renderers.glm45",
|
|
97
98
|
"GLM51Renderer": "renderers.glm5",
|
|
99
|
+
"GLM53FlashRenderer": "renderers.glm5",
|
|
98
100
|
"GLM53Renderer": "renderers.glm5",
|
|
99
101
|
"GLM5Renderer": "renderers.glm5",
|
|
100
102
|
"GptOssRenderer": "renderers.gpt_oss",
|
|
@@ -155,6 +157,8 @@ __all__ = [
|
|
|
155
157
|
"GLM45RendererConfig",
|
|
156
158
|
"GLM51Renderer",
|
|
157
159
|
"GLM51RendererConfig",
|
|
160
|
+
"GLM53FlashRenderer",
|
|
161
|
+
"GLM53FlashRendererConfig",
|
|
158
162
|
"GLM53Renderer",
|
|
159
163
|
"GLM53RendererConfig",
|
|
160
164
|
"GLM5Renderer",
|
|
@@ -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.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
21
|
+
__version__ = version = '0.1.13.dev5'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 13, 'dev5')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -1012,6 +1012,8 @@ MODEL_RENDERER_MAP: dict[str, str] = {
|
|
|
1012
1012
|
"zai-org/GLM-5.1": "glm-5.1",
|
|
1013
1013
|
"zai-org/GLM-5.3": "glm-5.3",
|
|
1014
1014
|
"zai-org/GLM-5.3-BF16": "glm-5.3",
|
|
1015
|
+
"zai-org/GLM-5.3-Flash": "glm-5.3-flash",
|
|
1016
|
+
"zai-org/GLM-5.3-Flash-BF16": "glm-5.3-flash",
|
|
1015
1017
|
# GLM-4.5.
|
|
1016
1018
|
"THUDM/GLM-4.5-Air": "glm-4.5",
|
|
1017
1019
|
"zai-org/GLM-4.5-Air": "glm-4.5",
|
|
@@ -1353,7 +1355,12 @@ def _populate_registry():
|
|
|
1353
1355
|
from renderers.deepseek_v4 import DeepSeekV4Renderer
|
|
1354
1356
|
from renderers.default import DefaultRenderer
|
|
1355
1357
|
from renderers.gemma4 import Gemma4Renderer
|
|
1356
|
-
from renderers.glm5 import
|
|
1358
|
+
from renderers.glm5 import (
|
|
1359
|
+
GLM5Renderer,
|
|
1360
|
+
GLM51Renderer,
|
|
1361
|
+
GLM53FlashRenderer,
|
|
1362
|
+
GLM53Renderer,
|
|
1363
|
+
)
|
|
1357
1364
|
from renderers.glm45 import GLM45Renderer
|
|
1358
1365
|
from renderers.gpt_oss import GptOssRenderer
|
|
1359
1366
|
from renderers.hy3 import Hy3Renderer
|
|
@@ -1393,6 +1400,7 @@ def _populate_registry():
|
|
|
1393
1400
|
"glm-5": GLM5Renderer,
|
|
1394
1401
|
"glm-5.1": GLM51Renderer,
|
|
1395
1402
|
"glm-5.3": GLM53Renderer,
|
|
1403
|
+
"glm-5.3-flash": GLM53FlashRenderer,
|
|
1396
1404
|
"glm-4.5": GLM45Renderer,
|
|
1397
1405
|
"minimax-m2": MiniMaxM2Renderer,
|
|
1398
1406
|
"deepseek-v3": DeepSeekV3Renderer,
|
|
@@ -7,6 +7,7 @@ messages → Renderer.render_ids() → token IDs → POST /inference/v1/generate
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import asyncio
|
|
10
|
+
import base64
|
|
10
11
|
import json
|
|
11
12
|
import logging
|
|
12
13
|
import math
|
|
@@ -14,6 +15,7 @@ from collections.abc import Mapping
|
|
|
14
15
|
from typing import Any, cast
|
|
15
16
|
|
|
16
17
|
import httpx
|
|
18
|
+
import numpy as np
|
|
17
19
|
from openai import AsyncOpenAI
|
|
18
20
|
|
|
19
21
|
from renderers.base import (
|
|
@@ -134,9 +136,26 @@ def parse_generate_response(raw: bytes) -> dict[str, Any]:
|
|
|
134
136
|
return payload
|
|
135
137
|
|
|
136
138
|
|
|
139
|
+
def _parse_packed_completion_logprobs(
|
|
140
|
+
packed: Mapping[str, Any], completion_ids: list[int]
|
|
141
|
+
) -> list[float]:
|
|
142
|
+
"""prime-rl's packed form: base64 float32 ``{data, shape, dtype}``, one per token."""
|
|
143
|
+
values = np.frombuffer(base64.b64decode(packed["data"]), dtype=packed["dtype"])
|
|
144
|
+
valid = np.isfinite(values) & (values > VLLM_LOGPROB_SENTINEL)
|
|
145
|
+
if len(values) != len(completion_ids) or not valid.all():
|
|
146
|
+
raise MalformedGenerateResponseError(
|
|
147
|
+
f"Engine response choice.completion_logprobs: {len(values)} values for "
|
|
148
|
+
f"{len(completion_ids)} completion tokens, or a non-finite or missing (-9999) logprob."
|
|
149
|
+
)
|
|
150
|
+
return values.astype(np.float64).tolist()
|
|
151
|
+
|
|
152
|
+
|
|
137
153
|
def _parse_completion_logprobs(
|
|
138
154
|
choice: Mapping[str, Any], completion_ids: list[int]
|
|
139
155
|
) -> list[float]:
|
|
156
|
+
packed = choice.get("completion_logprobs")
|
|
157
|
+
if packed is not None:
|
|
158
|
+
return _parse_packed_completion_logprobs(packed, completion_ids)
|
|
140
159
|
raw_logprobs = choice.get("logprobs")
|
|
141
160
|
if not isinstance(raw_logprobs, Mapping):
|
|
142
161
|
raise MalformedGenerateResponseError(
|
|
@@ -317,7 +336,9 @@ async def generate(
|
|
|
317
336
|
"token_ids": prompt_ids,
|
|
318
337
|
"sampling_params": sp,
|
|
319
338
|
}
|
|
320
|
-
content_parts =
|
|
339
|
+
content_parts = (
|
|
340
|
+
_content_parts(messages, renderer=renderer) if not process_multimodal else None
|
|
341
|
+
)
|
|
321
342
|
features = (
|
|
322
343
|
_build_mm_features(renderer, mm_data)
|
|
323
344
|
if process_multimodal and mm_data and not mm_data.is_empty()
|
|
@@ -376,7 +397,8 @@ async def generate(
|
|
|
376
397
|
|
|
377
398
|
routed_experts = choice.get("routed_experts")
|
|
378
399
|
# vLLM's native kept-set sampling masks (``--return-sampling-mask``):
|
|
379
|
-
# one list of surviving vocab ids per completion token
|
|
400
|
+
# one list of surviving vocab ids per completion token, or (prime-rl's
|
|
401
|
+
# server) packed CSR ``{"ids", "counts"}`` base64 int32 arrays.
|
|
380
402
|
sampling_mask = choice.get("sampling_mask")
|
|
381
403
|
|
|
382
404
|
# /inference/v1/generate returns finish_reason in {"stop","length",...} —
|
|
@@ -434,8 +456,15 @@ _MEDIA_URL_TYPES = {
|
|
|
434
456
|
}
|
|
435
457
|
|
|
436
458
|
|
|
437
|
-
def _content_parts(
|
|
459
|
+
def _content_parts(
|
|
460
|
+
messages: list[Message], *, renderer: Renderer
|
|
461
|
+
) -> list[dict[str, Any]]:
|
|
438
462
|
"""Flatten raw media in prompt order for vLLM's token generate endpoint."""
|
|
463
|
+
# Some templates reorder tool results. Use the same order for raw media,
|
|
464
|
+
# including when the caller supplies a prebuilt prompt and skips rendering.
|
|
465
|
+
order_messages = getattr(renderer, "messages_in_prompt_order", None)
|
|
466
|
+
if order_messages is not None:
|
|
467
|
+
messages = order_messages(messages)
|
|
439
468
|
parts: list[dict[str, Any]] = []
|
|
440
469
|
for message in messages:
|
|
441
470
|
content = message.get("content")
|
|
@@ -434,6 +434,12 @@ class GLM53RendererConfig(BaseRendererConfig):
|
|
|
434
434
|
return self
|
|
435
435
|
|
|
436
436
|
|
|
437
|
+
class GLM53FlashRendererConfig(GLM53RendererConfig):
|
|
438
|
+
"""GLM-5.3 Flash renderer config. GLM-5.3's template surface, plus images."""
|
|
439
|
+
|
|
440
|
+
name: Literal["glm-5.3-flash"] = "glm-5.3-flash"
|
|
441
|
+
|
|
442
|
+
|
|
437
443
|
class GLM45RendererConfig(BaseRendererConfig):
|
|
438
444
|
"""GLM-4.5 Air renderer config."""
|
|
439
445
|
|
|
@@ -1042,6 +1048,7 @@ RendererConfig = Annotated[
|
|
|
1042
1048
|
GLM5RendererConfig,
|
|
1043
1049
|
GLM51RendererConfig,
|
|
1044
1050
|
GLM53RendererConfig,
|
|
1051
|
+
GLM53FlashRendererConfig,
|
|
1045
1052
|
GLM45RendererConfig,
|
|
1046
1053
|
GptOssRendererConfig,
|
|
1047
1054
|
Hy3RendererConfig,
|
|
@@ -1091,6 +1098,7 @@ _CONFIG_BY_NAME: dict[str, type[BaseRendererConfig]] = {
|
|
|
1091
1098
|
"glm-5": GLM5RendererConfig,
|
|
1092
1099
|
"glm-5.1": GLM51RendererConfig,
|
|
1093
1100
|
"glm-5.3": GLM53RendererConfig,
|
|
1101
|
+
"glm-5.3-flash": GLM53FlashRendererConfig,
|
|
1094
1102
|
"glm-4.5": GLM45RendererConfig,
|
|
1095
1103
|
"gpt-oss": GptOssRendererConfig,
|
|
1096
1104
|
"hy3": Hy3RendererConfig,
|
|
@@ -1144,6 +1152,7 @@ __all__ = [
|
|
|
1144
1152
|
"DeepSeekV4RendererConfig",
|
|
1145
1153
|
"GLM45RendererConfig",
|
|
1146
1154
|
"GLM51RendererConfig",
|
|
1155
|
+
"GLM53FlashRendererConfig",
|
|
1147
1156
|
"GLM53RendererConfig",
|
|
1148
1157
|
"GLM5RendererConfig",
|
|
1149
1158
|
"Gemma4RendererConfig",
|