Skip to main content

tml-renderers

tml-renderers turns structured text, image, and audio chat into model-ready tokens and media for training and inference. It supports Thinking Machines Lab models, including Inkling and Inkling-Small, through TMLv0, and the supported third-party models served on Tinker through model-specific renderers.

Installation

Always use the latest release:

pip install --upgrade tml-renderers

tml-renderers is a compiled extension that requires PyTorch 2.10 or newer.

Quickstart

Create a short conversation with native chat objects and render it for inference or training:

from tml_renderers import chat, renderers

user = chat.Message(
    content=chat.Text("Hello, world!"),
    author=chat.Author(chat.AuthorKind.User),
)
assistant = chat.Message(
    content=chat.Text("Hello!"),
    author=chat.Author(chat.AuthorKind.Model),
)
native_messages = chat.MessageList([user, assistant])

renderer = renderers.Qwen3()
spans, parser = renderer.render_for_completion([user])
training_examples = renderer.render_for_sft(native_messages)

To continue a conversation, add the model response and new user or tool messages to the history and render again.

Supported models

Provider / family Models Renderer classes
thinkingmachines Inkling, Inkling-Small v0.Renderer (TMLv0)
Qwen Qwen3 (including vision), Qwen3.5, Qwen3.8 Qwen3, Qwen35, Qwen38
DeepSeek V3, R1, V3.1, V4, V4.1 Flash DeepSeekV3, DeepSeekR1, DeepSeekV31, DeepSeekV4, DeepSeekV41
Kimi K2, K2.5 KimiK2, KimiK25
GLM 5.2, 5.3, 5.3 Flash Glm52, Glm53, Glm53Flash
GPT-OSS GPT-OSS GptOss
Nemotron Nemotron 3 Nemotron3

OpenAI message compatibility

The same conversation can use OpenAI-style dictionaries:

Message Native chat object OpenAI-style dict
User chat.Message(content=chat.Text("Hello, world!"), author=chat.Author(chat.AuthorKind.User)) {"role": "user", "content": "Hello, world!"}
Assistant chat.Message(content=chat.Text("Hello!"), author=chat.Author(chat.AuthorKind.Model)) {"role": "assistant", "content": "Hello!"}

Convert the dictionaries before passing them to a renderer:

from tml_renderers import chat, renderers

openai_dicts = [
    {"role": "user", "content": "Hello, world!"},
    {"role": "assistant", "content": "Hello!"},
]
openai_messages = chat.OpenAIMessage.from_oss_messages(openai_dicts)
round_tripped = chat.OpenAIMessage.to_oss_messages(openai_messages)

renderer = renderers.Qwen3()
training_examples = renderer.render_for_sft(openai_messages)

The renderer also accepts openai_messages for completion. The conversion supports text, images, tool calls, and tool results; it handles message formats, not the OpenAI network API.

Rendering and parsing (TMLv0)

Rendering converts structured chat messages into the token and media-span sequence consumed by the model. v0 uses the same TMLv0 grammar for both inference and training:

  • render_for_completion(...) renders an inference prompt and returns a parser for turning generated model tokens back into messages.
  • render_for_sft(...) renders supervised-training examples with aligned, per-token loss weights.

The parser reconstructs structured messages from generated token spans:

from tml_renderers import chat, tokenizers, v0

tokenizer = tokenizers.O200kBaseChatTokenizer()
renderer = v0.Renderer(tokenizer)

messages = [
    chat.Message(
        content=chat.Text("Hello"),
        author=chat.Author(chat.AuthorKind.User),
    )
]

spans, parser = renderer.render_for_completion(messages)
parsed = parser.parse(spans)

training_examples = renderer.render_for_sft(messages)

The package includes native tokenizers for these renderers. It does not need Hugging Face chat templates or remote code.

tokenizer.encode_ordinary("hello")
tokenizer.decode([24912])
tokenizer.encode_special("message_user")   # -> 200000
tokenizer.decode_special(200000)            # -> "message_user"

qwen_tokenizer = tokenizers.Qwen3Tokenizer()
qwen_tokenizer.encode_special("im_start")   # -> 151644

Full method surface:

method maps on invalid / partial UTF-8
encode_ordinary(text) text → ids — (special-token markup is encoded as literal text)
encode_special(name) name → id raises if name isn't a special token
decode(ids) ids → text lossy — invalid/partial bytes become U+FFFD, never raises (tiktoken parity)
decode_strict(ids) ids → text raises ValueError on invalid/partial UTF-8
decode_bytes(ids) ids → bytes raw bytes, no UTF-8 handling
decode_special(id) id → name None if id isn't a special token

The tokenizer also provides is_special_token(id), special_tokens(), and eos_token, bos_token, and all_special_tokens. decode is lossy: a truncated multibyte tail renders as � rather than raising. Use decode_strict when invalid UTF-8 must raise an error.

render_for_completion accepts a MessageList, a list[Message], or a list[OpenAIMessage]. For TMLv0, render_for_completion_with_effort(messages, effort) accepts an effort float in [0, 1] and inserts a system message before the first non-system message; input messages must not already contain ThinkingEffort. For SFT, render_for_sft returns TrainingExamples with per-token loss weights.

Multimodal inputs

tml-renderers includes multimodal codecs for the TMLv0 renderer:

  • An ImagePointer is rendered as an ImageAssetPointerTokenSpan with the expected image-token count.
  • An AudioPointer is rendered as a DmelTokenSpan.

Image and audio messages use the same completion and training APIs as text:

from tml_renderers import chat, tokenizers, v0

renderer = v0.Renderer(tokenizers.O200kBaseChatTokenizer())

image_msg = chat.Message(
    content=chat.ImagePointer(
        location="image.png",
        format=chat.ImageFormat.Png,
        width=512,
        height=512,
    ),
    author=chat.Author(chat.AuthorKind.User),
)

audio_msg = chat.Message(
    content=chat.AudioPointer(
        location="clip.wav",
        format=chat.AudioFormat.Wav,
        num_frames=48_000,
        sample_rate=16_000,
    ),
    author=chat.Author(chat.AuthorKind.User),
)

spans, _ = renderer.render_for_completion([image_msg, audio_msg])
dmel = next(s.span for s in spans if type(s.span).__name__ == "DmelTokenSpan")
print(dmel.dmel.shape)  # [num_audio_tokens, num_dmel_bins], uint8

Media locations are represented as pointers. Audio is read from local files; tml-renderers never fetches remote media.

Token spans

Renderers work with token-span types you can construct directly:

from tml_renderers.chat import (
    EncodedTextTokenSpan,
    ImageAssetPointerTokenSpan,
    ImageFormat,
    PaddingTokenSpan,
    TokenSpan,
)

text = EncodedTextTokenSpan([101, 102])
image = ImageAssetPointerTokenSpan(
    location="image.png", format=ImageFormat.Png, width=512, height=512, num_tokens=256
)
padding = PaddingTokenSpan(4)

# Wrap in the oneof only where a call boundary asks for a TokenSpan.
wrapped = TokenSpan(text)

DmelTokenSpan is the encoded-audio span produced by the renderer. Its dmel field is a uint8 tensor of shape [num_audio_tokens, num_dmel_bins].

Using with Tinker

In Tinker Cookbook, use the recommended renderer for your model. Select tml_v0 for Inkling and Inkling-Small; supported third-party models use their model-specific renderers. Cookbook converts rendered text, image, and audio inputs for sampling and SFT.

The lower-level tml_renderers.tinker helpers are also available for direct Tinker SDK integration. Provide local media files or base64 image data.

Types

  • Core: Message, MessageList, Author, AuthorKind, MessageChannel, MessageMetadata
  • Content: Text, Thinking, ThinkingEffort, ImagePointer, AudioPointer, InvokeTool, StructuredToolCall, ToolError, ToolDeclareJson, ModelEndSampling
  • Token spans: TokenSpan, EncodedTextTokenSpan, ImageAssetPointerTokenSpan, DmelTokenSpan, PaddingTokenSpan
  • Formats: ImageFormat, AudioFormat
  • Tool args: ToolArg, ToolMetadata. ToolArg.value is a JSON-encoded string, matching the OpenAI function.arguments convention.
  • Tool declarations: ToolSpecJson (one declared tool with name, description, type_name, and JSON-schema parameters), grouped into ToolDeclareJson. The constructor accepts a dict for parameters and serializes it.

Examples

  • examples/run_tml_v0.py — low-level rendering and parsing of text and audio.
  • examples/cookbook_tinker_demo.py — native and OpenAI-style messages, including tool calls and results. See the public tool-call example.

License

Apache-2.0. The wheel includes LICENSE, NOTICE, and THIRD_PARTY_LICENSES.md.

Metadata

Release files for tml-renderers 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for tml-renderers 0.2.0
File
tml_renderers-0.2.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details
tml_renderers-0.2.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details
tml_renderers-0.2.0-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details
tml_renderers-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64 Details
tml_renderers-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ ARM64 Details
tml_renderers-0.2.0-cp310-cp310-macosx_11_0_arm64.whl CPython 3.10 CPython 3.10 macOS 11.0+ ARM64 Details

Total release size: 78.8 MB

Release files / tml_renderers-0.2.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL tml_renderers-0.2.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 13.4 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
7d6c9c0908594dda80358e2dfc6d14b4b40b78d6c01ad0a519dc871946cd2851
BLAKE2b-256 checksum
How to use checksums
b9b5a9419dc7e43c9774361e74ea6fcc989d59a1f4ac2123fe8a28dbc42ed0a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release files / tml_renderers-0.2.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL tml_renderers-0.2.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 13.2 MB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
6e65cb18fcb6ea0583d9583106674d503f94ce8ebcde0969b4dc51345a3e259a
BLAKE2b-256 checksum
How to use checksums
b6e99a4ed992f3634df8c2bc1a32343cb531940cfd4b6a9238f3296bce0dbe26
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release files / tml_renderers-0.2.0-cp311-abi3-macosx_11_0_arm64.whl

Download URL tml_renderers-0.2.0-cp311-abi3-macosx_11_0_arm64.whl
Size 12.9 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
983ca5353bc64b23454f65222a995793de71001f209973386ae5fe98f8a7644e
BLAKE2b-256 checksum
How to use checksums
b26b184a2359a0ec3b59fee2b632c18530c0916df6b958ba523f163085feb3fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release files / tml_renderers-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL tml_renderers-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 13.4 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
72e77d77efdf86ebe4e55f4080227cae3746b6115a3f9c458d8d23b8f531f0b3
BLAKE2b-256 checksum
How to use checksums
abee16cd520a6da48008f78ec2047687af3d3e7911396cd5584b206e5f4e576b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release files / tml_renderers-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL tml_renderers-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 13.2 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64
SHA-256 checksum
How to use checksums
75389f9f1d0ae5143b8bb3f2fc51dd74b1fe887ef11ccbed3d097596b8134128
BLAKE2b-256 checksum
How to use checksums
43db58faa8e26d1c9a995375a12cf9f4b7f65cce7992182cb42446c5f8df7358
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release files / tml_renderers-0.2.0-cp310-cp310-macosx_11_0_arm64.whl

Download URL tml_renderers-0.2.0-cp310-cp310-macosx_11_0_arm64.whl
Size 12.9 MB
Tags CPython 3.10 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
25478051f4fa03a95122113b1ab5afd76747dc76b3e9a6d166a927ed7856d44b
BLAKE2b-256 checksum
How to use checksums
b8045c2f05b29a48b78972c795c12165dde47efeda6b867f4e87efc5e1779dea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.2.0 This release

6 release files

0.1.0

3 release files

0.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page