renderers 0.1.12.dev1__tar.gz → 0.1.12.dev3__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.
Files changed (85) hide show
  1. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/PKG-INFO +1 -1
  2. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/_version.py +2 -2
  3. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/base.py +1 -1
  4. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/client.py +5 -6
  5. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_client.py +19 -1
  6. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/.github/workflows/publish-dev.yml +0 -0
  7. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/.github/workflows/publish.yml +0 -0
  8. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/.github/workflows/style.yml +0 -0
  9. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/.github/workflows/test.yml +0 -0
  10. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/.gitignore +0 -0
  11. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/.pre-commit-config.yaml +0 -0
  12. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/LICENSE +0 -0
  13. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/README.md +0 -0
  14. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/docs/renderer-config.md +0 -0
  15. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/examples/README.md +0 -0
  16. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/examples/sglang/multiturn_generate_sglang.py +0 -0
  17. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/examples/sglang/online_multiturn_sglang.py +0 -0
  18. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/examples/tinker/multiturn_generate_tinker.py +0 -0
  19. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/examples/transformers/multiturn_generate_transformers.py +0 -0
  20. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/examples/vllm/multiturn_generate_vllm.py +0 -0
  21. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/pyproject.toml +0 -0
  22. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/__init__.py +0 -0
  23. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/configs.py +0 -0
  24. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/deepseek_r1.py +0 -0
  25. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/deepseek_v3.py +0 -0
  26. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/deepseek_v4.py +0 -0
  27. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/default.py +0 -0
  28. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/gemma4.py +0 -0
  29. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/glm45.py +0 -0
  30. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/glm5.py +0 -0
  31. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/gpt_oss.py +0 -0
  32. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/hy3.py +0 -0
  33. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/inkling.py +0 -0
  34. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/kimi_k2.py +0 -0
  35. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/kimi_k25.py +0 -0
  36. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/laguna_s21.py +0 -0
  37. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/laguna_xs2.py +0 -0
  38. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/llama_3.py +0 -0
  39. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/minimax_m2.py +0 -0
  40. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/nemotron3.py +0 -0
  41. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/parsers.py +0 -0
  42. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/parsing.py +0 -0
  43. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/prime_qwen3.py +0 -0
  44. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/qwen3.py +0 -0
  45. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/qwen35.py +0 -0
  46. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/qwen36.py +0 -0
  47. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/qwen38.py +0 -0
  48. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/renderers/qwen3_vl.py +0 -0
  49. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/conftest.py +0 -0
  50. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/parity.py +0 -0
  51. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/reference_rendering.py +0 -0
  52. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_bridge.py +0 -0
  53. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_build_helpers.py +0 -0
  54. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_deepseek_r1.py +0 -0
  55. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_deepseek_v4.py +0 -0
  56. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_disabled_thinking_stability.py +0 -0
  57. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_gemma4.py +0 -0
  58. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_glm_tool_name_validation.py +0 -0
  59. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_hy3.py +0 -0
  60. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_incremental.py +0 -0
  61. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_inkling.py +0 -0
  62. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_is_content.py +0 -0
  63. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_kimi_k25_tool_schema.py +0 -0
  64. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_laguna_m1.py +0 -0
  65. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_laguna_xs21.py +0 -0
  66. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_llama_3.py +0 -0
  67. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_load_tokenizer.py +0 -0
  68. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_message_indices.py +0 -0
  69. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_message_tool_names.py +0 -0
  70. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_multimodal.py +0 -0
  71. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_nemotron3_ultra.py +0 -0
  72. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_offsetless_tokenizers.py +0 -0
  73. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_parity.py +0 -0
  74. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_parse_response.py +0 -0
  75. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_parse_response_robustness.py +0 -0
  76. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_parsers.py +0 -0
  77. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_preserve_thinking.py +0 -0
  78. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_qwen35_size_coverage.py +0 -0
  79. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_qwen38.py +0 -0
  80. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_renderer_config.py +0 -0
  81. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_roundtrip.py +0 -0
  82. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_sampled_mask.py +0 -0
  83. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_tokens_per_message.py +0 -0
  84. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/tests/test_tool_arg_type_preservation.py +0 -0
  85. {renderers-0.1.12.dev1 → renderers-0.1.12.dev3}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: renderers
3
- Version: 0.1.12.dev1
3
+ Version: 0.1.12.dev3
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
@@ -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.12.dev1'
22
- __version_tuple__ = version_tuple = (0, 1, 12, 'dev1')
21
+ __version__ = version = '0.1.12.dev3'
22
+ __version_tuple__ = version_tuple = (0, 1, 12, 'dev3')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -2095,7 +2095,7 @@ def build_trajectory_step(
2095
2095
  "completion_mask": [True] * len(completion_ids),
2096
2096
  "completion_logprobs": [0.0] * len(completion_ids),
2097
2097
  "routed_experts": None,
2098
- "kept_tokens": None,
2098
+ "sampling_mask": None,
2099
2099
  }
2100
2100
  if (
2101
2101
  full_rendered.multi_modal_data is not None
@@ -28,7 +28,6 @@ from renderers.base import (
28
28
 
29
29
  _request_logger = logging.getLogger("renderers.client")
30
30
  ROUTED_EXPERTS_DATA_PREFIX = b'"routed_experts":{"data":"'
31
- KEPT_TOKENS_IDS_PREFIX = b'"kept_tokens":{"ids":"'
32
31
  # vLLM uses this value both when sampled-token evidence is missing and as a
33
32
  # lower-bound clamp, so receiving it cannot prove the real logprob was returned.
34
33
  VLLM_LOGPROB_SENTINEL = -9999.0
@@ -129,12 +128,9 @@ def _strip_base64_field(raw: bytes, prefix: bytes) -> tuple[bytes, memoryview |
129
128
 
130
129
  def parse_generate_response(raw: bytes) -> dict[str, Any]:
131
130
  stripped, routed_data = _strip_base64_field(raw, ROUTED_EXPERTS_DATA_PREFIX)
132
- stripped, kept_ids_data = _strip_base64_field(stripped, KEPT_TOKENS_IDS_PREFIX)
133
131
  payload: dict[str, Any] = json.loads(stripped)
134
132
  if routed_data is not None:
135
133
  payload["choices"][0]["routed_experts"]["data"] = routed_data
136
- if kept_ids_data is not None:
137
- payload["choices"][0]["kept_tokens"]["ids"] = kept_ids_data
138
134
  return payload
139
135
 
140
136
 
@@ -374,7 +370,9 @@ async def generate(
374
370
  parsed = renderer.parse_response(completion_ids, tools=tools)
375
371
 
376
372
  routed_experts = choice.get("routed_experts")
377
- kept_tokens = choice.get("kept_tokens")
373
+ # vLLM's native kept-set sampling masks (``--return-sampling-mask``):
374
+ # one list of surviving vocab ids per completion token.
375
+ sampling_mask = choice.get("sampling_mask")
378
376
 
379
377
  # /inference/v1/generate returns finish_reason in {"stop","length",...} —
380
378
  # never "tool_calls" (a chat-completions concept). Promote stop→tool_calls
@@ -393,6 +391,7 @@ async def generate(
393
391
 
394
392
  return {
395
393
  "request_id": data.get("request_id") or "",
394
+ "usage": data.get("usage"),
396
395
  "prompt_ids": list(effective_prompt_ids or prompt_ids),
397
396
  "renderer_prompt_ids": list(prompt_ids) if content_parts else None,
398
397
  "mm_placeholders": mm_placeholders,
@@ -403,7 +402,7 @@ async def generate(
403
402
  "tool_calls": parsed.tool_calls,
404
403
  "finish_reason": finish_reason,
405
404
  "routed_experts": routed_experts,
406
- "kept_tokens": kept_tokens,
405
+ "sampling_mask": sampling_mask,
407
406
  # The mm sidecar consumed on the request side, surfaced back so
408
407
  # callers can persist it on the trajectory step for downstream
409
408
  # multi-turn bridging and training-sample construction.
@@ -68,6 +68,7 @@ class _FakeClient:
68
68
  def __init__(self):
69
69
  self.calls = []
70
70
  self.base_url = "http://fake-host:8000/v1"
71
+ self.usage = None
71
72
  routed_experts = np.array([[[1]], [[2]]], dtype=np.uint8)
72
73
  self.choice = {
73
74
  "index": 0,
@@ -93,6 +94,8 @@ class _FakeClient:
93
94
  "request_id": "gen-test",
94
95
  "choices": [self.choice],
95
96
  }
97
+ if self.usage is not None:
98
+ payload["usage"] = self.usage
96
99
  if body and body.get("content_parts"):
97
100
  payload["prompt_token_ids"] = [1, 2, 2, 3]
98
101
  payload["mm_placeholders"] = {"image": [{"offset": 1, "length": 2}]}
@@ -114,8 +117,22 @@ def _run_generate(client, renderer=None):
114
117
  )
115
118
 
116
119
 
117
- def test_generate_builds_request_body_and_parses_response():
120
+ @pytest.mark.parametrize(
121
+ "usage",
122
+ [
123
+ None,
124
+ {
125
+ "prompt_tokens": 3,
126
+ "completion_tokens": 2,
127
+ "total_tokens": 5,
128
+ "prompt_tokens_details": {"cached_tokens": 2},
129
+ "completion_tokens_details": {"reasoning_tokens": 1},
130
+ },
131
+ ],
132
+ )
133
+ def test_generate_builds_request_body_and_parses_response(usage):
118
134
  client = _FakeClient()
135
+ client.usage = usage
119
136
  renderer = _FakeRenderer()
120
137
 
121
138
  result = asyncio.run(
@@ -167,6 +184,7 @@ def test_generate_builds_request_body_and_parses_response():
167
184
  assert result["routed_experts"]["data"].tobytes() == base64.b64encode(b"\x01\x02")
168
185
  assert result["multi_modal_data"] is None
169
186
  assert result["request_id"] == "gen-test"
187
+ assert result["usage"] == usage
170
188
  # Per-token attribution from the renderer surfaces on the result so
171
189
  # downstream consumers (verifiers RendererClient → prime-rl) can
172
190
  # build selective loss masks without a second render pass.
File without changes
File without changes