Tinker Format Specification
This reference documents the exact data structures required for Tinker supervised fine-tuning.
Core Data Types
Datum
The fundamental training unit in Tinker:
from tinker import types
datum = types.Datum(
model_input=types.ModelInput.from_ints(tokens=input_tokens),
loss_fn_inputs={
"target_tokens": target_tokens, # List[int] - shifted by 1 for next-token prediction
"weights": weights # List[float] - 0.0 for prompt, 1.0 for completion
}
)ModelInput
Container for tokenized input:
# Simple text-only input
model_input = types.ModelInput.from_ints(tokens=[...])
# Multi-modal (for VLMs)
model_input = types.ModelInput(chunks=[
types.EncodedTextChunk(tokens=[...]),
types.ImageChunk(data=image_bytes, format="png"),
types.EncodedTextChunk(tokens=[...])
])Token Weight Assignment
The weights array determines which tokens contribute to the loss:
| Token Type | Weight | Description |
|---|---|---|
| System prompt | 0.0 | Context, not learned |
| User message | 0.0 | Input prompt |
| Assistant message | 1.0 | Target completion |
| Special tokens | 0.0 | EOS, BOS, delimiters |
Renderer System
Tinker uses renderers to convert message lists to tokens with proper weights.
Using Built-in Renderers
from tinker_cookbook import renderers, tokenizer_utils
# Get tokenizer for your model
tokenizer = tokenizer_utils.get_tokenizer("meta-llama/Llama-3.1-8B-Instruct")
# Get appropriate renderer
renderer = renderers.get_renderer("llama3", tokenizer)
# Convert messages to training format
messages = [
{"role": "system", "content": "You are a creative writer..."},
{"role": "user", "content": "Write a 500 word excerpt..."},
{"role": "assistant", "content": "The actual book text..."}
]
model_input, weights = renderer.build_supervised_example(messages)Renderer Output Visualization
The renderer assigns weights per-token:
Token Weight
<|im_start|> 0.0
system 0.0
\n 0.0
You are... 0.0
<|im_end|> 0.0
... ...
<|im_start|> 0.0
assistant 0.0
\n 0.0
The actual 1.0 <- Completion starts
book text 1.0
... 1.0
<|im_end|> 1.0 <- Final token weightedJSONL Format
For batch processing, use standard conversation JSONL:
{"messages": [{"role": "system", "content": "..."}, {"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]}
{"messages": [{"role": "system", "content": "..."}, {"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]}Converting JSONL to Datum
import json
from tinker import types
from tinker_cookbook import renderers, tokenizer_utils
def load_dataset(jsonl_path: str, model_name: str) -> list[types.Datum]:
"""Load JSONL and convert to Tinker Datum objects."""
tokenizer = tokenizer_utils.get_tokenizer(model_name)
renderer = renderers.get_renderer("llama3", tokenizer)
data = []
with open(jsonl_path) as f:
for line in f:
example = json.loads(line)
messages = example["messages"]
model_input, weights = renderer.build_supervised_example(messages)
# Get token sequences
input_tokens = model_input.to_ints()
target_tokens = input_tokens[1:] # Shift for next-token prediction
input_tokens = input_tokens[:-1]
weights = weights[1:] # Align weights with targets
datum = types.Datum(
model_input=types.ModelInput.from_ints(tokens=input_tokens),
loss_fn_inputs={
"target_tokens": target_tokens,
"weights": weights
}
)
data.append(datum)
return dataTraining Loop Integration
import tinker
from tinker import types
async def train_on_book_dataset(
dataset: list[types.Datum],
model_name: str,
learning_rate: float = 1e-4,
epochs: int = 1
):
"""Train on book SFT dataset."""
service_client = tinker.ServiceClient()
training_client = await service_client.create_lora_training_client_async(
base_model=model_name,
rank=32
)
for epoch in range(epochs):
for batch_start in range(0, len(dataset), 1): # Batch size 1
batch = dataset[batch_start:batch_start + 1]
# Forward-backward with cross-entropy loss
fwd_bwd_future = await training_client.forward_backward_async(
batch,
loss_fn="cross_entropy"
)
# Optimizer step with aggressive learning rate
optim_future = await training_client.optim_step_async(
types.AdamParams(learning_rate=learning_rate * 2.0)
)
# Wait for completion
fwd_bwd_result = await fwd_bwd_future
optim_result = await optim_futureKey Constraints
- Batch Size: Use 1 for style transfer. Larger batches average out stylistic gradients.
- Sequence Length: Keep chunks under 1000 tokens. Longer sequences dilute local style patterns.
- Learning Rate: Use 2x multiplier (e.g., 2e-4 instead of 1e-4) for faster style convergence.
- Token Alignment: Target tokens must be shifted by 1 position from input tokens.
- Weight Precision: Weights should be float32, typically 0.0 or 1.0.
Model Selection
For book SFT, consider:
| Model | Use Case |
|---|---|
| meta-llama/Llama-3.1-8B-Instruct | General style transfer |
| Qwen/Qwen3-30B-A3B | Higher quality, MoE efficiency |
| GPT-4o (via OpenAI) | Data generation only, not Tinker |
References
- Tinker Cookbook:
tinker_cookbook/supervised/train.py - Renderer implementations:
tinker_cookbook/renderers.py - Type definitions:
tinker/types.py