Skip to content
Browse changelogs · TML Renderers
Jump to a version

TML Renderers

v0.4.1

New

  • Adds renderers.KimiK31Pro() and tokenizers.KimiK3Tokenizer() for Kimi K3.1-Pro. The default reasoning effort is max; use .high(), .low(), .disable_thinking(), or .no_reasoning_effort() for other supported modes.

Changes

  • None.

Fixed

  • Kimi: Keeps KimiK2 and KimiK25 streamed answer indices consistent with the completed message after an empty thinking block.
  • GLM: Trains the correct assistant-turn ending in Glm52, Glm53, and Glm53Flash supervised examples: <|observation|> after tool calls and <|user|> otherwise, matching the next prompt. This changes the last trained token of GLM SFT examples.
  • Qwen: Corrects Qwen35Tokenizer token IDs for more text. This changes rendered tokens in Qwen3.5 and Qwen3.8 prompts and SFT examples.

Deprecations

  • None.

Breaking changes

  • None.

Dependencies

  • Python >=3.10 → >=3.11

v0.4.0

New

  • Use renderers.Inkling() for Inkling and Inkling-Small, or renderers.Inkling2() for Inkling 2 Small. Each builds its matching tokenizer. Set thinking effort with render_for_completion_with_effort(messages, effort).
  • Use tokenizers.H200kBaseChatTokenizer(), the Inkling 2 Small tokenizer, with low-level TMLv0 rendering: v0.Renderer(tokenizers.H200kBaseChatTokenizer()).

Changes

  • None.

Fixed

  • GLM: Corrects GlmTokenizer token IDs for some text. This changes rendered tokens for Glm52, Glm53, and Glm53Flash.
  • Qwen: Corrects Qwen35Tokenizer token IDs for some text. This changes rendered tokens for Qwen35 and Qwen38.

Deprecations

  • None.

Breaking changes

  • parser.parse_tokens() and parser.parse() now return ParseResult instead of a list. For list-specific operations, replace messages = parser.parse_tokens(tokens) with messages = parser.parse_tokens(tokens).messages; iteration and integer indexing still work on the result. result.token_counts reports counts per completed message, and streaming completion updates expose num_tokens.
  • renderers.DeepSeekR1 and tokenizers.DeepSeekR1Tokenizer are removed. Select a supported model and its matching renderer/tokenizer before upgrading; applications that still require these R1 APIs must remain on 0.3.0.
  • A v0.Renderer pickled with 0.3.0 or earlier raises TypeError when loaded with 0.4.0. Recreate and re-save renderers after upgrading, and use matching package versions in workers that exchange them.

Dependencies

  • Drops support for Python 3.10.

v0.3.0

New

  • Parse sampled tokens incrementally with parser.parse_stream(). Inside its context manager, call stream.feed(token_ids) for each chunk and stream.finish() at completion; each returns ParseUpdate objects.
  • Continue a conversation without re-encoding its sampled prefix using renderer.bridge_to_next_turn(prefix, message_history, next_messages). It returns the combined token spans, the appended suffix, and a parser for the next turn.
  • Use renderers.Nemotron3VL() and tokenizers.Nemotron3VLTokenizer() for Nemotron 3.5 Super VL, including image inputs. Call .disable_thinking() for the non-thinking preset.
  • Preserve DeepSeek-V4.1 reasoning across turns with renderers.DeepSeekV41.preserve_thinking_history() or DeepSeekV41(strip_thinking_from_history=False).
  • Use chat.ParseErrorContent(error_message=..., sampled_tokens=...) to record a failed parse in a conversation. Renderers write only its error_message into the prompt. DeepSeek-V3.1 does not accept it, and DeepSeek-V4, DeepSeek-V4.1, GLM, and GPT-OSS accept it only in user messages.
  • Convert OpenAI Chat Completions messages with MessageList.from_openai_chat_dicts(messages, tools=...) and convert back with to_openai_chat_dicts(). A top-level reasoning_content becomes reasoning, and the request's tools list becomes a tool declaration. OpenAIMessage has the same methods.

Changes

  • None.

Fixed

  • Accepts repeated argument names when constructing or copying InvokeTool calls, such as calls returned by the parser. 0.2.x raised ValueError.
  • Keeps assistant dictionaries with content: [] as empty assistant turns during conversion, instead of dropping them.
  • Rejects zero-width or zero-height image pointers during image-dictionary conversion instead of failing later during rendering.
  • Encodes adjacent same-weight text together in Qwen and Nemotron supervised targets, so the tokens match what the model samples. This changes SFT tokens.
  • Corrects whitespace, newlines, and tool-result order in Qwen, Nemotron, GLM, and DeepSeek-V4 prompts. This changes prompt tokens for some conversations.
  • Smaller parsing fixes for GLM, Nemotron, DeepSeek-V4, GPT-OSS, and Kimi: unfinished tool calls, string arguments, message authors, and adjacent assistant turns.

Deprecations

  • The from_oss_* and to_oss_* methods of OpenAIMessage and MessageList are deprecated and emit DeprecationWarning. Use the *_openai_chat_* methods, or tinker_cookbook.third_party.tml_renderers_compat for cookbook-format messages. No removal version or date is announced.

Breaking changes

  • The TMLv0, Qwen3, Qwen3.5, Qwen3.8, Nemotron 3, DeepSeek-R1, and DeepSeek-V3.1 parsers now raise when a completion stops inside a message, instead of returning only the completed messages. The error is a ValueError (v0.ParseError for TMLv0). Catch ValueError and read error.completed_messages to recover the completed messages. DeepSeek-V3, V4, and V4.1 errors now carry completed_messages too. This applies to both parse_tokens() and parse().
  • Glm53 and Glm53Flash now preserve historical reasoning by default (clear_thinking=False), changing prompts and supervised examples. Pass clear_thinking=True, including to .high() or .low(), to retain the previous behavior consistently in sampling and training.
  • The from_oss_dict() and from_oss_messages() readers now reject a top-level reasoning_content instead of dropping it. Read OpenAI Chat dicts with the from_openai_chat_dict or from_openai_chat_dicts helpers.

Dependencies

  • None.

v0.2.1

New

  • None.

Changes

  • renderers.GptOss() now defaults to reasoning_effort="medium" instead of "low". Pass reasoning_effort="low" to retain the previous prompt setting.

Fixed

  • Allows renderers and parsers to be used from a Python thread other than the one that created them, without raising PanicException.
  • Prevents a deadlock when multiple threads construct their first tokenizer concurrently.
  • When a reply is cut off after one or more finished messages, parse_tokens() and parse() return the finished messages instead of raising. This applies to TMLv0, Qwen3, Qwen3.5, Qwen3.8, Nemotron 3, DeepSeek-R1, and DeepSeek-V3.1 in thinking mode. A reply cut off in its first message still raises.
  • Places system text at a fixed position in Qwen and Nemotron prompts that declare tools, whatever the message order: before the tool declarations for Qwen3 and Nemotron 3, and after them for Qwen3.5 and Qwen3.8, with a blank line before it. This changes prompt tokens, for example for a Qwen3.5 system message given before the tool declaration.
  • Uses the correct special-token IDs in Qwen3.5 and Nemotron tool-declaration examples. User-provided text and schema strings remain literal text.
  • TMLv0: Parses an empty message as Text("") and keeps every value of a repeated tool-call argument, instead of raising v0.ParseError.

Deprecations

  • None.

Breaking changes

  • TMLv0: Writes the tool name in the header of each structured tool-call message, for example <|message_model|>get_weather<|content_invoke_tool_json|>. This restores the 0.1.0 tokens for tool calls converted from OpenAI-style messages, and adds the name for tool calls without an author name. A tool call whose author.name differs from the tool name now raises ValueError; unset author.name or set it to the tool name.

Dependencies

  • None.

v0.2.0

New

  • Introducing support for other model families in tml-renderers: Qwen3, Qwen3.5, Qwen3.8, DeepSeek-V3, DeepSeek-R1, DeepSeek-V3.1, DeepSeek-V4, DeepSeek-V4.1, Kimi K2, Kimi K2.5, GLM-5.2, GLM-5.3, GLM-5.3-Flash, GPT-OSS, and Nemotron 3.
  • Set chat.ImagePointer.override_width and override_height to request a rendering resolution different from the stored image dimensions. Rendered image spans carry the resolved virtual_width and virtual_height.
  • Normalize native or OpenAI-style message sequences with chat.MessageList.from_messages(). The helper also accepts an existing MessageList.
  • Pass a tool failure as a content part such as {"type": "tool_error", "text": "command failed"} in OpenAI-style messages. It converts to chat.ToolError, and TMLv0 renders it as a tool error.
  • Pickle renderers, for example to send them to worker processes. This includes v0.Renderer.
  • Use renderer.tokenizer to get a renderer's tokenizer, and type code that accepts any renderer with tml_renderers.Renderer.

Changes

  • TMLv0: Parsed tool calls now carry a tool_call_id numbered in call order, for example functions.read:0. 0.1.0 returned None.

Fixed

  • TMLv0: Rejects TML image pointers with non-positive dimensions instead of silently rendering an image with zero tokens.
  • Preserves WAV audio through OSS message round trips.
  • TMLv0: Rejects sampled tool calls with an unknown field or an empty tool name with v0.ParseError. 0.1.0 dropped the field, for example "trace" in {"name": "read", "args": {}, "trace": "abc"}, and accepted the empty name.

Deprecations

  • tokenizers.o200k_base_chat() is deprecated; use tokenizers.O200kBaseChatTokenizer(). The old factory remains available and emits DeprecationWarning. No removal version or date is announced.
  • tml_renderers.tinker.TokenSpanWrapper and RawTokenSpan remain as deprecated compatibility names. Annotate rendered spans with chat.TokenSpan and access the contained value through .span. No removal version or date is announced.

Breaking changes

  • The old incremental parser methods parse_token(), parse_updates(), flush_updates(), flush(), reset(), and is_at_message_boundary() are removed. Accumulate a completion and pass it to parse_tokens() or parse(); each call handles a complete parsing attempt.
  • parse_errors.UnterminatedMessageError is replaced by UnterminatedStructureError and UnterminatedContentError. Update imports and checks of ParseError.kind to distinguish incomplete structure from incomplete content.
  • TMLv0: parse_tokens() and parse() now raise v0.ParseError when a completion stops inside a message, even when earlier messages completed. 0.1.0 returned only the completed messages, or []. A completion with no message, such as a lone end-of-sampling token, also raises (EmptyResponseError). Catch v0.ParseError when a completion can reach a token limit.
  • chat.InvokeTool raises ValueError for an empty tool name, a repeated argument name, or raw text combined with a structured call, on construction and on copy(). 0.1.0 accepted these. Remove repeated arguments, and use chat.InvokeTool("raw text") for a raw-text call.

Dependencies

  • Adds support for Python 3.10.

v0.1.0

New

  • Introducing tml-renderers, including the TMLv0 renderer for use with Thinking Machines’ Inkling model.

Changes

  • None.

Fixed

  • None.

Deprecations

  • None.

Breaking changes

  • None.

Dependencies

  • Requires Python >=3.11.
  • PyTorch >=2.10. Install it separately; the wheel does not install it.