renderers 0.1.8.dev40__tar.gz → 0.1.8.dev42__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.8.dev40 → renderers-0.1.8.dev42}/PKG-INFO +1 -1
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/__init__.py +4 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/_version.py +2 -2
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/base.py +10 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/configs.py +28 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/kimi_k25.py +15 -3
- renderers-0.1.8.dev42/renderers/llama_3.py +516 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/parsing.py +134 -3
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/qwen3.py +2 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/qwen3_vl.py +2 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/conftest.py +32 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_bridge.py +1 -0
- renderers-0.1.8.dev42/tests/test_llama_3.py +407 -0
- renderers-0.1.8.dev42/tests/test_parse_response.py +276 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_preserve_thinking.py +6 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_roundtrip.py +7 -0
- renderers-0.1.8.dev40/tests/test_parse_response.py +0 -137
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/.github/workflows/publish-dev.yml +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/.github/workflows/publish.yml +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/.github/workflows/style.yml +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/.github/workflows/test.yml +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/.gitignore +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/.pre-commit-config.yaml +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/LICENSE +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/README.md +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/docs/renderer-config.md +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/examples/README.md +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/examples/sglang/multiturn_generate_sglang.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/examples/sglang/online_multiturn_sglang.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/examples/tinker/multiturn_generate_tinker.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/examples/transformers/multiturn_generate_transformers.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/examples/vllm/multiturn_generate_vllm.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/pyproject.toml +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/client.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/deepseek_v3.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/default.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/glm45.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/glm5.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/gpt_oss.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/kimi_k2.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/laguna_xs2.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/minimax_m2.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/nemotron3.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/parsers.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/qwen35.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/renderers/qwen36.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_build_helpers.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_client.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_gpt_oss_harmony_parity.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_incremental.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_is_content.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_kimi_k25_tool_schema.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_load_tokenizer.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_load_tokenizer_fastokens.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_message_indices.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_message_tool_names.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_multimodal.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_nemotron3_ultra.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_parse_response_robustness.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_parsers.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_qwen35_size_coverage.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_render_ids.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_renderer_config.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_renderer_config_parity.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_sampled_mask.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_tokens_per_message.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/tests/test_tool_arg_type_preservation.py +0 -0
- {renderers-0.1.8.dev40 → renderers-0.1.8.dev42}/uv.lock +0 -0
|
@@ -52,6 +52,7 @@ from renderers.configs import (
|
|
|
52
52
|
KimiK25RendererConfig,
|
|
53
53
|
KimiK2RendererConfig,
|
|
54
54
|
LagunaXS2RendererConfig,
|
|
55
|
+
Llama3RendererConfig,
|
|
55
56
|
MiniMaxM2RendererConfig,
|
|
56
57
|
Nemotron3RendererConfig,
|
|
57
58
|
Qwen35RendererConfig,
|
|
@@ -82,6 +83,7 @@ _LAZY_RENDERERS: dict[str, str] = {
|
|
|
82
83
|
"KimiK25Renderer": "renderers.kimi_k25",
|
|
83
84
|
"KimiK2Renderer": "renderers.kimi_k2",
|
|
84
85
|
"LagunaXS2Renderer": "renderers.laguna_xs2",
|
|
86
|
+
"Llama3Renderer": "renderers.llama_3",
|
|
85
87
|
"MiniMaxM2Renderer": "renderers.minimax_m2",
|
|
86
88
|
"Nemotron3Renderer": "renderers.nemotron3",
|
|
87
89
|
"Qwen35Renderer": "renderers.qwen35",
|
|
@@ -130,6 +132,8 @@ __all__ = [
|
|
|
130
132
|
"KimiK2RendererConfig",
|
|
131
133
|
"LagunaXS2Renderer",
|
|
132
134
|
"LagunaXS2RendererConfig",
|
|
135
|
+
"Llama3Renderer",
|
|
136
|
+
"Llama3RendererConfig",
|
|
133
137
|
"MULTIMODAL_MODELS",
|
|
134
138
|
"Message",
|
|
135
139
|
"MiniMaxM2Renderer",
|
|
@@ -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.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1, 8, '
|
|
21
|
+
__version__ = version = '0.1.8.dev42'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 8, 'dev42')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -1045,6 +1045,14 @@ MODEL_RENDERER_MAP: dict[str, str] = {
|
|
|
1045
1045
|
"nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-BF16": "nemotron-3",
|
|
1046
1046
|
"nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16": "nemotron-3",
|
|
1047
1047
|
"nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-FP8": "nemotron-3",
|
|
1048
|
+
# Llama 3.2 (Instruct). Tested against the gated meta-llama repos and
|
|
1049
|
+
# the unrestricted unsloth/... mirror, which ships a byte-identical
|
|
1050
|
+
# chat template. ``Llama3Renderer`` defaults ``date_string`` to
|
|
1051
|
+
# "26 Jul 2024" — matching the chat template's strftime fallback —
|
|
1052
|
+
# so the renderer is reproducible. Pass ``date_string=...`` at
|
|
1053
|
+
# construction to pin a different date.
|
|
1054
|
+
"meta-llama/Llama-3.2-1B-Instruct": "llama-3",
|
|
1055
|
+
"meta-llama/Llama-3.2-3B-Instruct": "llama-3",
|
|
1048
1056
|
# Poolside Laguna.
|
|
1049
1057
|
"poolside/Laguna-XS.2": "laguna-xs.2",
|
|
1050
1058
|
# GPT-OSS.
|
|
@@ -1334,6 +1342,7 @@ def _populate_registry():
|
|
|
1334
1342
|
from renderers.kimi_k2 import KimiK2Renderer
|
|
1335
1343
|
from renderers.kimi_k25 import KimiK25Renderer
|
|
1336
1344
|
from renderers.laguna_xs2 import LagunaXS2Renderer
|
|
1345
|
+
from renderers.llama_3 import Llama3Renderer
|
|
1337
1346
|
from renderers.minimax_m2 import MiniMaxM2Renderer
|
|
1338
1347
|
from renderers.nemotron3 import Nemotron3Renderer
|
|
1339
1348
|
from renderers.qwen3 import Qwen3Renderer
|
|
@@ -1356,6 +1365,7 @@ def _populate_registry():
|
|
|
1356
1365
|
"kimi-k2": KimiK2Renderer,
|
|
1357
1366
|
"kimi-k2.5": KimiK25Renderer,
|
|
1358
1367
|
"laguna-xs.2": LagunaXS2Renderer,
|
|
1368
|
+
"llama-3": Llama3Renderer,
|
|
1359
1369
|
"nemotron-3": Nemotron3Renderer,
|
|
1360
1370
|
"gpt-oss": GptOssRenderer,
|
|
1361
1371
|
}
|
|
@@ -318,6 +318,31 @@ class LagunaXS2RendererConfig(BaseRendererConfig):
|
|
|
318
318
|
chat template's ``render_assistant_messages_raw`` gate."""
|
|
319
319
|
|
|
320
320
|
|
|
321
|
+
class Llama3RendererConfig(BaseRendererConfig):
|
|
322
|
+
"""Llama-3.x Instruct renderer config.
|
|
323
|
+
|
|
324
|
+
Llama-3 ships no reasoning channel, so the base ``preserve_*_thinking``
|
|
325
|
+
flags don't apply: ``Llama3Renderer`` raises ``NotImplementedError``
|
|
326
|
+
if either is set (matching ``DefaultRenderer``'s contract for the
|
|
327
|
+
same case). Both fields below mirror real ``apply_chat_template``
|
|
328
|
+
kwargs.
|
|
329
|
+
"""
|
|
330
|
+
|
|
331
|
+
name: Literal["llama-3"] = "llama-3"
|
|
332
|
+
|
|
333
|
+
date_string: str = "26 Jul 2024"
|
|
334
|
+
"""``Today Date`` value injected into the system preamble. Pinned to
|
|
335
|
+
the chat template's ``strftime`` fallback by default so output stays
|
|
336
|
+
deterministic; override per instance for production runs that want
|
|
337
|
+
today's date. Mirrors the chat template's ``date_string`` kwarg."""
|
|
338
|
+
|
|
339
|
+
tools_in_user_message: bool = True
|
|
340
|
+
"""When ``True`` (default), tool descriptions + JSON signatures inject
|
|
341
|
+
into the first user message; ``False`` routes them into the system
|
|
342
|
+
block instead. Mirrors the chat template's ``tools_in_user_message``
|
|
343
|
+
kwarg."""
|
|
344
|
+
|
|
345
|
+
|
|
321
346
|
class MiniMaxM2RendererConfig(BaseRendererConfig):
|
|
322
347
|
"""MiniMax M2 / M2.5 renderer config."""
|
|
323
348
|
|
|
@@ -410,6 +435,7 @@ RendererConfig = Annotated[
|
|
|
410
435
|
KimiK2RendererConfig,
|
|
411
436
|
KimiK25RendererConfig,
|
|
412
437
|
LagunaXS2RendererConfig,
|
|
438
|
+
Llama3RendererConfig,
|
|
413
439
|
MiniMaxM2RendererConfig,
|
|
414
440
|
Nemotron3RendererConfig,
|
|
415
441
|
DeepSeekV3RendererConfig,
|
|
@@ -444,6 +470,7 @@ _CONFIG_BY_NAME: dict[str, type[BaseRendererConfig]] = {
|
|
|
444
470
|
"kimi-k2": KimiK2RendererConfig,
|
|
445
471
|
"kimi-k2.5": KimiK25RendererConfig,
|
|
446
472
|
"laguna-xs.2": LagunaXS2RendererConfig,
|
|
473
|
+
"llama-3": Llama3RendererConfig,
|
|
447
474
|
"minimax-m2": MiniMaxM2RendererConfig,
|
|
448
475
|
"nemotron-3": Nemotron3RendererConfig,
|
|
449
476
|
"deepseek-v3": DeepSeekV3RendererConfig,
|
|
@@ -486,6 +513,7 @@ __all__ = [
|
|
|
486
513
|
"KimiK25RendererConfig",
|
|
487
514
|
"KimiK2RendererConfig",
|
|
488
515
|
"LagunaXS2RendererConfig",
|
|
516
|
+
"Llama3RendererConfig",
|
|
489
517
|
"MiniMaxM2RendererConfig",
|
|
490
518
|
"Nemotron3RendererConfig",
|
|
491
519
|
"Qwen35RendererConfig",
|
|
@@ -42,7 +42,7 @@ from renderers.base import (
|
|
|
42
42
|
trim_to_turn_close,
|
|
43
43
|
)
|
|
44
44
|
from renderers.configs import KimiK25RendererConfig
|
|
45
|
-
from renderers.parsing import parse_kimi_k2_section
|
|
45
|
+
from renderers.parsing import _reasoning_end_token_index, parse_kimi_k2_section
|
|
46
46
|
from renderers.qwen3_vl import (
|
|
47
47
|
_image_hash,
|
|
48
48
|
_is_image_part,
|
|
@@ -452,6 +452,13 @@ def _parse_kimi_k2_response(
|
|
|
452
452
|
ids = ids[:i]
|
|
453
453
|
break
|
|
454
454
|
|
|
455
|
+
# Reasoning first: a tool-call section the model drafts *inside* its
|
|
456
|
+
# <think> trace must not be parsed as a real call (regression #78 — cf.
|
|
457
|
+
# parse_qwen3). K2.5 renders </think> as text, so locate the boundary by
|
|
458
|
+
# decoding; the section scan then starts past it. content_ids still begins
|
|
459
|
+
# at 0, so the </think> text-split below recovers reasoning unchanged.
|
|
460
|
+
reasoning_end = _reasoning_end_token_index(tokenizer, ids)
|
|
461
|
+
|
|
455
462
|
# Token-ID path — produces spans. Only run if every relevant special
|
|
456
463
|
# token resolved at init (i.e. is in the tokenizer's vocab).
|
|
457
464
|
tool_calls: list[ParsedToolCall] = []
|
|
@@ -471,6 +478,7 @@ def _parse_kimi_k2_response(
|
|
|
471
478
|
tool_call_begin_id=tool_call_begin_id,
|
|
472
479
|
tool_call_argument_begin_id=tool_call_argument_begin_id,
|
|
473
480
|
tool_call_end_id=tool_call_end_id,
|
|
481
|
+
scan_start=reasoning_end,
|
|
474
482
|
)
|
|
475
483
|
text = (
|
|
476
484
|
tokenizer.decode(content_ids, skip_special_tokens=False)
|
|
@@ -481,9 +489,13 @@ def _parse_kimi_k2_response(
|
|
|
481
489
|
text = tokenizer.decode(ids, skip_special_tokens=False) if ids else ""
|
|
482
490
|
|
|
483
491
|
# Fallback path: model emitted literal-text section delimiters (singular
|
|
484
|
-
# variant) rather than special tokens. Spans unavailable here.
|
|
492
|
+
# variant) rather than special tokens. Spans unavailable here. Start the
|
|
493
|
+
# search past the first </think> so a literal section drafted inside the
|
|
494
|
+
# reasoning trace isn't matched as a real call (regression #78).
|
|
485
495
|
if not tool_calls:
|
|
486
|
-
|
|
496
|
+
think_close = text.find("</think>")
|
|
497
|
+
search_from = think_close + len("</think>") if think_close != -1 else 0
|
|
498
|
+
tc_match = _TOOL_CALLS_SECTION_RE.search(text, search_from)
|
|
487
499
|
if tc_match:
|
|
488
500
|
text = text[: tc_match.start()]
|
|
489
501
|
tool_section = (
|