# Tinker Cookbook [GitHub ↗](https://github.com/thinking-machines-lab/tinker-cookbook) · [PyPI ↗](https://pypi.org/project/tinker-cookbook/) ## [v0.6.1](#v0-6-1) Published November 6, 2026 ### New - Use `moonshotai/Kimi-K3.1-Pro`, with text, image, and tool-call support, through [`get_tokenizer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/tokenizer_utils/get_tokenizer/) and [`get_renderer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/renderers/get_renderer/). The renderers are `kimi_k31_pro_max_reasoning` (the default), `kimi_k31_pro_high_reasoning`, `kimi_k31_pro_low_reasoning`, `kimi_k31_pro_disable_thinking`, and `kimi_k31_pro_no_reasoning_effort`. `get_lr()` has no calibrated learning rate for it, so set one explicitly. - Pass `TrainOnWhat.LAST_ASSISTANT_TURN` to the `tml_v0` renderer and to `tinker_messages_to_sft_message_list()` to weight the assistant messages after the last user message. Before, both raised `NotImplementedError`. ### Changes - None. ### Fixed - None. ### Deprecations - None. ### Breaking changes - Direct callers of `TmlRenderersTokenizerAdapter(name_or_path)` must now supply a `tml_tokenizer` argument. Prefer [`get_tokenizer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/tokenizer_utils/get_tokenizer/), for example `get_tokenizer("thinkingmachines/Inkling-Small")`, to select and construct the correct adapter. ### Dependencies - tml-renderers `>=0.4.0` → `>=0.4.1` ## [v0.6.0](#v0-6-0) Published November 5, 2026 ### New - RL and SL trainers report per-step and cumulative token usage and estimated USD cost. Rates are fetched once per process from published pricing; if unavailable, token counts remain available. RL totals include discarded constant-reward groups and KL scoring, but do not represent complete billed usage. - Call `tinker_messages_to_openai(...)` in `third_party.openai_compat` to build OpenAI chat inputs from cookbook messages, including tool calls and declarations, reasoning, images, and audio. `openai_messages_to_tinker(...)` now also converts reasoning, images, and audio. - Convert cookbook messages to and from `tml-renderers` message lists through `third_party.tml_renderers_compat`, including supervised weighting and multimodal content. - Use `thinkingmachines/Inkling-2-Small` with [`get_tokenizer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/tokenizer_utils/get_tokenizer/) and the `tml_v0` renderer. LoRA parameter counts are included. `get_lr()` has no calibrated learning rate for it, so set one explicitly. - `BenchmarkConfig.for_model()` now returns evaluation defaults for every Inkling model, including the 256K `:peft:262144` variants. Before, it raised `ValueError` for them. - Call `tokenizer_utils.encode_without_special_tokens(tokenizer, text)` to encode raw text with Hugging Face and `tml-renderers` tokenizers alike. ### Changes - Async RL skips sampler-only weight exports after all training rollout workers finish, while still refreshing weights needed for evaluation, checkpoints, and KL measurements. ### Fixed - Preserves original SDFT teacher token positions across masked gaps so teacher and student tokens remain correctly aligned. - Backs up the metrics file and removes rows at or beyond the resumed step before logging again, preventing duplicate or out-of-order rows when resuming an earlier checkpoint. - Completes partial training steps, final evaluation, and environment cleanup during async shutdown. - Returns `ParseTermination.MALFORMED` with decoded text when the `tml_v0` renderer parses an unsupported text-form tool call, instead of failing or producing an empty tool name. ### Deprecations - None. ### Breaking changes - Async RL now trains completed rollouts regardless of age instead of discarding stale rollouts and retrying their problems. `max_steps_off_policy` limits sampling ahead to `groups_per_batch * (max_steps_off_policy + 1)` groups, increasing possible sandbox concurrency. Size environment pools accordingly; use `max_steps_off_policy=0` when on-policy execution is required. Observed staleness is reported in `async/staleness_min`, `async/staleness_max`, and `async/staleness_mean`. - Async RL and the `math_rl`, `rubric`, and `prometheus_experimental` recipes now default to [StableReinforce (alpha)](https://tinker-docs.thinkingmachines.ai/tinker/losses/stable-reinforce/), including its default sampler KL coefficient of `0.01`. Set `AsyncConfig.loss_fn="importance_sampling"`, or pass `loss_fn=importance_sampling` in those recipes, to retain the former objective. Conflicting nondefault `Config.loss_fn` values in async runs now raise `ConfigurationError`. Other synchronous RL configs retain their existing `importance_sampling` default. - StableReinforce requires sampled-token provenance: custom completers must populate `TokensWithLogprobs.sequence_id`, or callers must choose a different loss. With an active KL penalty, set `kl_discount_factor=0` or use another loss; discounted prompt-token advantages are not supported by StableReinforce. - Async RL now keeps evaluation metrics that finish after newer training steps. To do this, async training and late evaluations log independent metric events, so W&B internal steps count metric arrivals rather than training updates. For charts and consumers, use `training/step` and `eval/snapshot/training_step` as the model-version axes. Evaluation rows also carry the cost and elapsed-time coordinates of the weights they evaluated. - The cookbook now calls the unified `APIFuture` methods of tinker `0.38` (`sample`, `forward`, and others) instead of the `*_async` methods. Objects that stand in for a Tinker client must provide these methods; for example, the capture proxy's `SamplingClientLike` now requires `sample`. See the [migration guide](https://tinker-docs.thinkingmachines.ai/tinker/howto/concurrency_async/). - `rl.metrics.incorporate_kl_penalty()`, `rl.metrics.compute_post_kl()`, and `rl.train.prepare_minibatch()` now also return token usage. Unpack the extra value: `metrics, usage = await incorporate_kl_penalty(...)`, `metrics, usage = await compute_post_kl(...)`, and `data_D, metrics, usage = await prepare_minibatch(...)`. ### Dependencies - tinker `>=0.35.0` → `>=0.38.0` - tml-renderers `>=0.0.1` → `>=0.4.0` ## [v0.5.9](#v0-5-9) Published October 27, 2026 ### New - Set `rl.train.Config.num_epochs` to train for multiple passes over an RL dataset. `EpochCycledRLDataset` supports deterministic epoch cycling while checkpoints and resume retain global step numbering. - Set `sandbox_factory` on the Harbor distillation CLI config, directly or through an import string, to use a custom sandbox backend. - Set `session_name` in recipe CLIs and in the DPO and distillation configs to name the Tinker session. By default, a recipe uses its run name or a supplied `wandb_name`. Recipes without a run name use `cookbook-`, and multi-stage recipes append their stage. ### Changes - SL and RL trainers now finish their Tinker sessions when training ends, including successful, failed, and interrupted runs. - RL and SL training now log a warning when `max_steps` exceeds `num_epochs` times the dataset length. Training still stops after the last epoch. ### Fixed - Finishes rolling checkpoint saves before recording the final checkpoint, preventing resume from pointing to a deleted checkpoint. - Splits held-out source rows before interleaved-dataset oversampling, preventing duplicate holdouts and leakage into training. This changes which rows are held out, and a `test_size` larger than the sources allow now raises `ValueError`. - Smaller evaluation fixes: AIME grading rejects fractional and out-of-range answers instead of truncating them, which can lower AIME scores. Resumed evaluations keep their token and turn counts. Deleting an evaluation run also removes unfinished transcripts. Importing the custom-evaluator example no longer loads a tokenizer or calls the service. - Skips `None` metric values in `dict_mean` instead of crashing. - Consumes the final queued batches in streaming-minibatch async training before shutdown completes. - Prevents "Already borrowed" tokenizer errors during concurrent Qwen rendering. - Evaluates the final trained weights in synchronous RL loops when evaluation is enabled. ### Deprecations - None. ### Breaking changes - [`weights.download()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/weights/download/) no longer accepts `sampler_weights/` checkpoints after removal of the SDK archive API. Export from a training client with `save_weights_external()` and download the resulting `external_weights/` path instead. - The standalone `recipes.rl_loop` now defaults to [StableReinforce (alpha)](https://tinker-docs.thinkingmachines.ai/tinker/losses/stable-reinforce/) instead of `importance_sampling`. Pass `loss_fn=importance_sampling` to retain the previous objective; `loss_fn` also supports `cispo` and `gspo`. ### Dependencies - tinker `>=0.34.0` → `>=0.35.0` - litellm (`litellm` and `all` extras) `>=1.80.0,!=1.82.7,!=1.82.8` → `==1.105.1` - transformers `>=4.57.6,!=5.4.*,!=5.5.0,!=5.5.1,!=5.5.2,!=5.5.3,<=5.5.4` → `>=4.57.6,!=5.3.0,!=5.4.*,!=5.5.0,!=5.5.1,!=5.5.2,!=5.5.3,!=5.6.*` ## [v0.5.8](#v0-5-8) Published October 21, 2026 ### New - Adds `supervised.nll_evaluator.SamplerNLLEvaluator` for held-out NLL evaluation through a sampling client. Use `.from_dataset(...)` and supply a tokenizer to also report bits per byte. - Adds [decision-model helpers](https://tinker-docs.thinkingmachines.ai/cookbook/recipes/decisions/) for scoring labeled choices and training on either a chosen label or a target probability distribution. Use `DecisionRenderer`, `sample_decision`, and the datum helpers in `recipes.decisions`. - Adds a long-context, many-turn counting recipe for checking RL numerics with a paginated document-reading tool. - Use `qwen3_5_preserve_thinking` with [`get_renderer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/renderers/get_renderer/) to retain reasoning across Qwen3.5/Qwen3.6 tool-use turns. - Use GLM-5.3-Flash with the `glm5_3_max_reasoning` (default), `glm5_3_high_reasoning`, and `glm5_3_low_reasoning` renderers. Use DeepSeek-V4.1-Flash and DeepSeek-V4.1-Flash-1017 with the new `deepseekv4_1`, `deepseekv4_1_low_reasoning`, `deepseekv4_1_max_reasoning`, `deepseekv4_1_disable_thinking`, and `deepseekv4_1_preserve_thinking` renderers. Use Nemotron-3.5-Super-VL, including image input, with the `nemotron3_ultra` renderers. GLM-5.3-Flash and DeepSeek-V4.1-Flash take text only. LoRA parameter counts are included. `get_lr()` has no calibrated learning rate for these models, so set one explicitly. - Set `session_name` on SL and RL training configs to name the Tinker session. When unset, `wandb_name` is used if provided. - Pass `tinker:///external_weights/` or `tinker:///weights/` paths to [`weights.download()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/weights/download/). A training checkpoint downloads through a temporary encrypted export that is decrypted locally; this starts a training session on the checkpoint's base model. Files are installed only after the complete download succeeds. ### Changes - The forecasting recipe adds a GLM-5.3 example and updates defaults to learning rate `1e-4`, 128 steps, evaluation every 16 steps, and checkpoints every 64 steps. - SFT and DPO held-out NLL evaluation now uses sampling clients. - Training traces now include external weight exports through `TrainingClient.save_weights_external_async`. ### Fixed - Honors `save_every` in the guess-number and twenty-questions recipes. - Trims leading and trailing whitespace from list-shaped Qwen3.5 and Qwen3.6 content, as string content already was, so sampled tool-use turns re-render consistently. This changes rendered tokens for such content. - Omits empty header chunks from generation prompts after consecutive tool responses, preventing HTTP 400 errors, including with Nemotron parallel tool calls. - Handles Modal-side sandbox cancellation as `SandboxTerminatedError` without canceling the entire training step or discarding healthy rollouts. Cancellation of the caller still propagates. ### Deprecations - `supervised.nll_evaluator.NLLEvaluator` is deprecated. Create a sampling client with `TrainingClient.save_weights_and_get_sampling_client()` and use `SamplerNLLEvaluator` instead. No removal version or date is announced. - The [checkpoint-copy script](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/scripts/copy_checkpoint/) is deprecated in favor of `ServiceClient.copy_weights()`. The script retains its behavior; removal is planned for a future release without a specified version or date. ### Breaking changes - Recipe outputs now default to `~/tinker-runs` instead of `/tmp`, and re-downloadable caches use `~/.cache/tinker-cookbook`. Set `TINKER_COOKBOOK_RUNS_DIR` to choose another root, or use `cli_utils.runs_path()` to build a path under it. Explicit output paths work as before. Existing outputs are not moved: re-run data-preparation steps, or pass the old paths, for data created by an earlier release. - W&B logging now also accepts credentials saved by `wandb login`. A run that sets `wandb_project` without W&B credentials now raises `ConfigurationError` instead of continuing without W&B. Run `wandb login` or set `WANDB_API_KEY`, set `WANDB_MODE=offline`, or leave `wandb_project` unset. ### Dependencies - tinker `>=0.23.0` → `>=0.34.0` - pyrage `>=1.4.0` ## [v0.5.7](#v0-5-7) Published September 3, 2026 ### New - None. ### Changes - None. ### Fixed - Trains the `<|observation|>` or `<|user|>` terminator on every GLM-5.3 assistant turn, rather than only the final turn. Prompt-supplied thinking-prefill tokens carry no loss. This changes loss weights for multi-turn supervised examples. ### Deprecations - None. ### Breaking changes - None. ### Dependencies - None. ## [v0.5.6](#v0-5-6) Published September 1, 2026 ### New - Use GLM-5.3 with the `glm5_3_low_reasoning`, `glm5_3_high_reasoning`, and `glm5_3_max_reasoning` renderers through [`get_renderer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/renderers/get_renderer/), including tool calling. `get_lr()` has no calibrated learning rate for it, so set one explicitly. - Run the [forecasting recipe](https://tinker-docs.thinkingmachines.ai/cookbook/recipes/forecasting/) to train on Prophet Arena binary prediction markets, with a chronological train/validation split and a Brier-score reward. - `get_lora_param_count()` now supports Inkling-Small. ### Changes - None. ### Fixed - Accepts model names with a variant suffix, such as `:peft:262144`, in `get_lr()`, `get_lora_param_count()`, and `get_full_finetune_param_count()`. Before, these names raised an error. ### Deprecations - None. ### Breaking changes - None. ### Dependencies - None. ## [v0.5.5](#v0-5-5) Published August 21, 2026 ### New - Use `Qwen/Qwen3.8-27B` with the `qwen3_8_xhigh_reasoning`, `qwen3_8_medium_reasoning`, `qwen3_8_low_reasoning`, or `qwen3_8_disable_thinking` renderers through [`get_renderer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/renderers/get_renderer/). ### Changes - None. ### Fixed - Groups consecutive tool responses into one user turn in the Qwen3.5, Qwen3.6, and Nemotron renderers. Qwen3.5 and Qwen3.6 also omit the blank line before `` when an assistant message has no text. This changes rendered tokens for conversations with tool calls. - Treats Qwen3 turn markers in user-provided message text as content rather than conversation boundaries. This changes rendered tokens for such text. ### Deprecations - None. ### Breaking changes - When using a reasoning-disabled Qwen, Kimi K2.5 and K2.6, or Nemotron renderer, remove reasoning from affected supervised targets or select a thinking-enabled renderer. Inputs previously accepted with a mismatched prompt can now raise `RendererError`. ### Dependencies - None. ## [v0.5.4](#v0-5-4) Published August 11, 2026 ### New - Use `nemotron3_preserve_thinking` or `nemotron3_ultra_preserve_thinking` with [`get_renderer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/renderers/get_renderer/) to keep historical reasoning in multi-turn contexts. - Use `nvidia/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-BF16` with the `nemotron3_ultra`, `nemotron3_ultra_disable_thinking`, and `nemotron3_ultra_preserve_thinking` renderers. `get_lr()` has no calibrated learning rate for it, so set one explicitly. - Call [`Renderer.build_supervised_examples()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/renderers/renderer/) on renderers without the sequence-extension property to train on every assistant turn. Before, these renderers raised `NotImplementedError`. ### Changes - Inkling rendering is now part of the base installation, and the `[inkling]` extra is removed. Installing `tinker-cookbook[inkling]` still works but prints a warning, so remove the extra from install commands and requirement files. ### Fixed - Corrects the final Qwen3 assistant turn: reasoning gets its own lines inside the thinking block, a reply without reasoning gets an empty block, and a tool-only reply has no newline before ``. This changes rendered tokens and parsed reasoning. - Trims leading and trailing whitespace from string content in the Qwen3.5, Qwen3.6, and Nemotron renderers. This changes rendered tokens for such content. - Preserves content whitespace when the `role_colon` renderer parses its rendered output. - Excludes prompt-supplied reasoning-prefill tokens from supervised loss. Qwen3.5 also preserves the prompt boundary when adjacent newlines would otherwise merge into one token. This changes training weights for the reasoning modes of the Qwen3.5, Nemotron, DeepSeek, and Kimi K2.5 and K2.6 renderers. - Includes sampling-compatible thinking delimiters in DeepSeek thinking-mode supervised examples without reasoning. - Preserves the required opening thinking token when a custom prefill is supplied to the Kimi K2.5 and K2.6 renderers, placing the prefill after it. ### Deprecations - None. ### Breaking changes - Qwen3 with thinking disabled now rejects a nonempty supervised assistant target when the conversation contains no user message. Add a user message or use a thinking-enabled renderer instead of relying on the previous mismatched training prompt. ### Dependencies - tinker `>=0.22.3` → `>=0.23.0` - torch `>=2.0` → `>=2.10` - tml-renderers `>=0.0.1` ## [v0.5.3](#v0-5-3) Published July 30, 2026 ### New - Use `tinker_cookbook.capture` to record training and sampling tokens, log probabilities, and run coordinates. Call `capture_to_store(...)` for a local SQLite store with HTTP queries and live SSE updates, or pass your own capture sink. For agent harnesses that do not call the SDK, run the Anthropic- and OpenAI-compatible proxy with `python -m tinker_cookbook.capture.proxy.serve`. - Use `thinkingmachines/Inkling-Small` with the model registry and the `tml_v0` renderer. It gets the same agentic rollout defaults as Inkling, and [`get_tokenizer()`](https://tinker-docs.thinkingmachines.ai/cookbook/api-reference/tokenizer_utils/get_tokenizer/) returns the Inkling tokenizer for it. ### Changes - The `inkling.sample_reasoning` script now maps `minimal`, `low`, and `medium` to 0.1, 0.2, and 0.7. Its smallest default generation budget applies below effort 0.2. ### Fixed - Uses a default `max_tokens` of 2048 for Inspect evaluations, avoiding response truncation at 128 tokens when no limit is specified. This changes scores for such evaluations. - Keeps the Search-R1 worked example within its one-to-five-word answer instruction. This changes the recipe's prompt tokens. ### Deprecations - None. ### Breaking changes - `set_rollout_executor()` and the `rollout_executor` argument of `rl.train` now raise `ValueError` for a process pool that uses `fork`, because such workers could hang after inheriting a Tinker client. On Linux before Python 3.14, `fork` is the default, so create the pool with `ProcessPoolExecutor(mp_context=multiprocessing.get_context("spawn"))`. The cookbook's own sweep pools now use `spawn`, so put parallel `sweep.run()` calls inside `if __name__ == "__main__":`. An unguarded call now raises `RuntimeError`. ### Dependencies - None. ## [v0.5.2](#v0-5-2) Published July 15, 2026 ### New - None. ### Changes - The `inkling.sample_reasoning` script now chooses a generation budget of 4096, 8192, or 16384 tokens according to reasoning effort. Set `max_tokens` to use one budget for every effort; the script also reports when a response reaches the limit. ### Fixed - None. ### Deprecations - None. ### Breaking changes - None. ### Dependencies - None. ## [v0.5.1](#v0-5-1) Published July 15, 2026 ### New - None. ### Changes - None. ### Fixed - Uses the selected model’s renderer and tokenizer when `model_name=...` overrides the defaults in `sl_basic` or `rl_basic`. ### Deprecations - None. ### Breaking changes - None. ### Dependencies - None. ## [v0.5.0](#v0-5-0) Published July 15, 2026 ### New - Use Thinking Machines’ Inkling model with the `tml_v0` renderer. Pass `effort` from `0` up to but excluding `1` to `build_generation_prompt()` or `build_supervised_examples()` to control reasoning effort. - Use the `recipes.audio` speech transcription and emotion recognition recipes for supervised and reinforcement learning. The `scripts.inkling` sampling examples cover reasoning, images, and audio. - Pass a `RolloutConfig` to `rl.rollout_runner.run_rollout()` to set turn, token, tool-call, and time limits and configure parse-error retries. Start with the `agentic()` preset for multi-turn tool use. - Pass a tokenizer to `NLLEvaluator` to report bits per byte alongside loss. Supervised training enables this metric for its test dataset and excludes special tokens from the byte-normalized score. - Use `inference.modal.prepare` and `inference.modal.serve` to deploy a trained checkpoint as a persistent OpenAI-compatible SGLang endpoint on Modal. ### Changes - None. ### Fixed - Treats turns containing only malformed tool calls as parse failures in `AgentToolMessageEnv`, applying `failed_parse_reward` instead of grading them as completed answers. This changes rewards for those rollouts. ### Deprecations - None. ### Breaking changes - None. ### Dependencies - Adds the `inkling` extra with `tinker` `>=0.23.0`, `tml-renderers` `>=0.0.1`, and `torch` `>=2.10`. - Adds the `audio` extra with `jiwer` `>=3.0.0` and `soundfile` `>=0.12.0`. - `modal` `>=1.0.0` → `>=1.5.1` in the `modal`, `eval`, `eval-livecodebench`, `eval-mbpp`, `eval-swe-bench`, `eval-terminal-bench`, and `all` extras. ## [v0.4.3](#v0-4-3) Published June 24, 2026 ### New - None. ### Changes - Updates distillation recipe defaults to Qwen3.5 students and teachers, and Kimi K2.6 for multi-turn Harbor distillation. Override `model_name` and `teacher_model` to choose other supported models. ### Fixed - Loads Kimi K2 tokenizers with their model-specific chat template, avoiding the Transformers fallback that breaks tool formatting. ### Deprecations - None. ### Breaking changes - None. ### Dependencies - `transformers` `>=4.57.6,<=5.5.3` → `>=4.57.6,<=5.5.4,!=5.4.*,!=5.5.0,!=5.5.1,!=5.5.2,!=5.5.3`. ## [v0.4.2](#v0-4-2) Published June 10, 2026 ### New - Use Nemotron 3 Ultra with the `nemotron3_ultra`, `nemotron3_ultra_medium_thinking`, or `nemotron3_ultra_disable_thinking` renderer. The model registry also adds Qwen3.5-9B, Qwen3.5-9B-Base, and Qwen3.5-35B-A3B-Base. - Pass `save_every_tokens` or `save_every_seconds` to `supervised.train.Config` to schedule checkpoints by processed tokens or elapsed time. Custom loops using `CheckpointManager` can pass `elapsed_tokens` to `maybe_save_async()`. - Use `python -m tinker_cookbook.scripts.save_audit_log` to archive audit logs as daily JSONL files. Pass `--once` for a single fetch or `--backfill-days` to include earlier days; your account must have permission to read audit logs. - Pass `--destination-project-id` to `scripts.copy_checkpoint` to choose the project receiving a copied checkpoint. Copies within your organization can use your current credentials without a separate `--source-access-token`. ### Changes - Updates recipe default models from Llama and Qwen models to Qwen3.5, and from Kimi K2 Thinking to Kimi K2.6. Pass `model_name` to choose a different supported model. ### Fixed - Preserves tool calls and tool results in the Inspect AI integration and honors required or named `tool_choice` settings. ### Deprecations - None. ### Breaking changes - None. ### Dependencies - `tinker` `>=0.9.0` → `>=0.22.3`. - Adds the `tutorials` extra with `marimo` `>=0.23.8`, `matplotlib` `>=3.7.0`, `math-verify` `>=0.5.0`, `pylatexenc` `>=2.0`, and `sympy` `>=1.12.0`. ## [v0.4.1](#v0-4-1) Published May 11, 2026 ### New - None. ### Changes - None. ### Fixed - Loads the Kimi K2.6 tokenizer with its required vocabulary files and model-specific tool-call chat template. ### Deprecations - None. ### Breaking changes - `get_lora_param_count()` now returns a single parameter count that accounts for the selected training components. Replace `detailed`, `include_experts`, and `shared_expert_outer_loras` with `train_mlp`, `train_attn`, and `train_unembed` flags matching your training client; dictionary results are no longer available. ### Dependencies - None. ## [v0.4.0](#v0-4-0) Published May 8, 2026 ### New - Use Kimi K2.6 and Qwen3.6 models in Cookbook recipes. Kimi K2.6 includes thinking, non-thinking, and reasoning-history-preserving renderers; Nemotron 3 Super adds the `nemotron3_low_thinking` renderer. - Pass `submit_ahead` to `supervised.train.Config` to control how many training steps are submitted ahead, and `async_periodic_saves=True` to save periodic checkpoints in the background. - Use `reverse=True` with `topk>0` in the SDFT recipe to train with analytical reverse KL over the teacher’s top-K tokens. - Use `python -m tinker_cookbook.scripts.copy_checkpoint` to copy a training checkpoint into your account. Pass `--source-path` and `--source-access-token`; set `--output-kind training` to keep training from the copy. - Use `recipes.multiplayer_rl.text_arena.play` to play against a trained tic-tac-toe model or evaluate it against random and optimal opponents. ### Changes - `conversation_to_datum()` now normalizes loss weights per example after truncation, so examples with more trainable tokens no longer receive more total weight. Pass `reduction="none"` to retain unnormalized token weights. ### Fixed - Handles sandbox creation failures during Harbor evaluation and uploads nested fixture directories without flattening their paths. ### Deprecations - None. ### Breaking changes - `Renderer.parse_response()` returns a `ParseTermination` value instead of a success boolean. Unpack `message, termination = renderer.parse_response(tokens)` and check `termination.is_clean`, or `termination.is_stop_sequence` for strict stop-sequence validation. All enum values are truthy, including `MALFORMED`; a best-effort message is still returned for malformed responses. - Replace `RollingCheckpointManager` with `CheckpointManager` and pass scheduling options by keyword. The manager handles periodic and rolling saves; use `save_final_async(loop_state)` to write a permanent final checkpoint and clean up rolling checkpoints. ### Dependencies - `transformers` `>=4.57.6,<=5.3.0` → `>=4.57.6,<=5.5.3`.