renderers 0.1.8.dev44__tar.gz → 0.1.8.dev45__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 (70) hide show
  1. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/PKG-INFO +1 -1
  2. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/_version.py +2 -2
  3. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/base.py +37 -11
  4. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/.github/workflows/publish-dev.yml +0 -0
  5. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/.github/workflows/publish.yml +0 -0
  6. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/.github/workflows/style.yml +0 -0
  7. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/.github/workflows/test.yml +0 -0
  8. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/.gitignore +0 -0
  9. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/.pre-commit-config.yaml +0 -0
  10. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/LICENSE +0 -0
  11. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/README.md +0 -0
  12. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/docs/renderer-config.md +0 -0
  13. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/examples/README.md +0 -0
  14. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/examples/sglang/multiturn_generate_sglang.py +0 -0
  15. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/examples/sglang/online_multiturn_sglang.py +0 -0
  16. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/examples/tinker/multiturn_generate_tinker.py +0 -0
  17. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/examples/transformers/multiturn_generate_transformers.py +0 -0
  18. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/examples/vllm/multiturn_generate_vllm.py +0 -0
  19. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/pyproject.toml +0 -0
  20. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/__init__.py +0 -0
  21. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/client.py +0 -0
  22. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/configs.py +0 -0
  23. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/deepseek_r1.py +0 -0
  24. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/deepseek_v3.py +0 -0
  25. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/default.py +0 -0
  26. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/glm45.py +0 -0
  27. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/glm5.py +0 -0
  28. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/gpt_oss.py +0 -0
  29. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/kimi_k2.py +0 -0
  30. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/kimi_k25.py +0 -0
  31. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/laguna_xs2.py +0 -0
  32. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/llama_3.py +0 -0
  33. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/minimax_m2.py +0 -0
  34. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/nemotron3.py +0 -0
  35. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/parsers.py +0 -0
  36. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/parsing.py +0 -0
  37. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/qwen3.py +0 -0
  38. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/qwen35.py +0 -0
  39. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/qwen36.py +0 -0
  40. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/renderers/qwen3_vl.py +0 -0
  41. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/conftest.py +0 -0
  42. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_bridge.py +0 -0
  43. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_build_helpers.py +0 -0
  44. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_client.py +0 -0
  45. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_deepseek_r1.py +0 -0
  46. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_gpt_oss_harmony_parity.py +0 -0
  47. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_incremental.py +0 -0
  48. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_is_content.py +0 -0
  49. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_kimi_k25_tool_schema.py +0 -0
  50. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_llama_3.py +0 -0
  51. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_load_tokenizer.py +0 -0
  52. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_load_tokenizer_fastokens.py +0 -0
  53. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_message_indices.py +0 -0
  54. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_message_tool_names.py +0 -0
  55. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_multimodal.py +0 -0
  56. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_nemotron3_parity.py +0 -0
  57. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_nemotron3_ultra.py +0 -0
  58. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_parse_response.py +0 -0
  59. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_parse_response_robustness.py +0 -0
  60. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_parsers.py +0 -0
  61. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_preserve_thinking.py +0 -0
  62. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_qwen35_size_coverage.py +0 -0
  63. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_render_ids.py +0 -0
  64. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_renderer_config.py +0 -0
  65. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_renderer_config_parity.py +0 -0
  66. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_roundtrip.py +0 -0
  67. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_sampled_mask.py +0 -0
  68. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_tokens_per_message.py +0 -0
  69. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/tests/test_tool_arg_type_preservation.py +0 -0
  70. {renderers-0.1.8.dev44 → renderers-0.1.8.dev45}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: renderers
3
- Version: 0.1.8.dev44
3
+ Version: 0.1.8.dev45
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.8.dev44'
22
- __version_tuple__ = version_tuple = (0, 1, 8, 'dev44')
21
+ __version__ = version = '0.1.8.dev45'
22
+ __version_tuple__ = version_tuple = (0, 1, 8, 'dev45')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -1708,19 +1708,45 @@ def _get_offset_tokenizer(tokenizer):
1708
1708
  kwargs = {"trust_remote_code": True, "revision": revision}
1709
1709
  else:
1710
1710
  kwargs = {"trust_remote_code": False}
1711
- # Explicitly vanilla — we want HF's Rust tokenizer with offset
1712
- # tracking, not the fastokens shim. ``load_tokenizer`` would
1713
- # patch fastokens in by default; routing through
1714
- # ``_load_tokenizer_via_auto`` keeps the fastokens patch out
1715
- # of this code path while still applying the config-build
1716
- # fallback (RoPE-validation failures on nested
1717
- # ``rope_parameters``, etc.).
1711
+
1712
+ def _has_offsets(tok) -> bool:
1713
+ if not getattr(tok, "is_fast", False):
1714
+ return False
1715
+ try:
1716
+ tok("a", add_special_tokens=False, return_offsets_mapping=True)
1717
+ return True
1718
+ except (NotImplementedError, ValueError, TypeError):
1719
+ return False
1720
+
1721
+ # We want HF's Rust tokenizer with offset tracking, not the fastokens
1722
+ # shim. The shim is installed by a *process-global* monkeypatch that
1723
+ # ``load_tokenizer`` toggles per pool-slot load, so a plain reload here
1724
+ # can race a concurrent slot's open patch window and silently pick up
1725
+ # the offset-less shim (then get cached, poisoning the process). So:
1726
+ # load, verify offsets, and if missing, reload with the patch forced
1727
+ # off — serialized against pool patch/unpatch via ``_FASTOKENS_PATCH_LOCK``
1728
+ # so no concurrent window can swap the shim back in mid-load — then
1729
+ # restore the prior patch state. Never cache a non-offset tokenizer.
1718
1730
  offset_tok = _load_tokenizer_via_auto(name_or_path, **kwargs)
1719
- if not getattr(offset_tok, "is_fast", False):
1731
+ if not _has_offsets(offset_tok):
1732
+ import fastokens
1733
+
1734
+ with _FASTOKENS_PATCH_LOCK:
1735
+ was_patched = bool(getattr(fastokens, "_patched", False))
1736
+ if was_patched:
1737
+ with contextlib.redirect_stdout(io.StringIO()):
1738
+ fastokens.unpatch_transformers()
1739
+ try:
1740
+ offset_tok = _load_tokenizer_via_auto(name_or_path, **kwargs)
1741
+ finally:
1742
+ if was_patched:
1743
+ with contextlib.redirect_stdout(io.StringIO()):
1744
+ fastokens.patch_transformers()
1745
+ if not _has_offsets(offset_tok):
1720
1746
  raise RuntimeError(
1721
- f"Vanilla tokenizer for {name_or_path!r} is not a fast "
1722
- "tokenizer; offset_mapping is unavailable. Hand-coded "
1723
- "renderers require a fast tokenizer for body/scaffold "
1747
+ f"Could not load an offset-capable tokenizer for {name_or_path!r}: "
1748
+ "offset_mapping is unavailable even with the fastokens patch off. "
1749
+ "Hand-coded renderers require a fast tokenizer for body/scaffold "
1724
1750
  "attribution."
1725
1751
  )
1726
1752
  _offset_tokenizers[name_or_path] = offset_tok
File without changes
File without changes