Cost estimation for the Thinking Machines Lab Tinker SDK
Project description
tinker-cost
Cost estimation for the Thinking Machines Lab Tinker SDK.
Pass in the Datum list you already built for training — no manual token counting required. Token lengths are read directly from datum.model_input.length.
This package implements the feature requested in thinking-machines-lab/tinker-cookbook#298. A PR to the Tinker SDK that integrates this directly as
tinker costis pending review.
Installation
pip install tinker-cost
# or
uv add tinker-cost
Usage
Estimate training cost
from tinker_cost import estimate_training_cost
# `data` is the same List[Datum] you pass to forward_backward — no changes needed
est = estimate_training_cost(
"Qwen/Qwen3.5-9B",
data=my_dataset,
num_epochs=3,
batch_size=8,
)
print(f"Dataset: {est.num_datums} datums")
print(f"Steps: {est.num_steps}")
print(f"Avg seq length: {est.avg_tokens_per_datum:.0f} tokens")
print(f"Total tokens: {est.total_tokens:,}")
print(f"Estimated cost: ${est.total_cost:.2f}")
Dataset: 2000 datums
Steps: 750
Avg seq length: 512 tokens
Total tokens: 3,072,000,000
Estimated cost: $4087.30
Estimate sampling cost
from tinker_cost import estimate_sampling_cost
# `prompts` is a List[ModelInput] or List[SampleRequest]
est = estimate_sampling_cost(
"Qwen/Qwen3.5-9B",
prompts=my_prompts,
max_new_tokens=512,
)
print(f"Prompts: {est.num_prompts}")
print(f"Prompt tokens: {est.total_prompt_tokens:,}")
print(f"Prefill cost: ${est.prefill_cost:.4f}")
print(f"Sample cost: ${est.sample_cost:.4f}")
print(f"Estimated cost: ${est.total_cost:.4f}")
Check rates
from tinker_cost import PRICING
prefill_rate, sample_rate, train_rate = PRICING["Qwen/Qwen3.5-9B"]
print(f"Train: ${train_rate}/M tokens")
API reference
estimate_training_cost(model, data, *, num_epochs, batch_size) → TrainingCostEstimate
| Parameter | Type | Description |
|---|---|---|
model |
str |
Tinker model ID |
data |
Sequence[Datum] |
Your full training dataset — token lengths read from datum.model_input.length |
num_epochs |
int |
How many times the full dataset is trained over (default: 1) |
batch_size |
int |
Datums per forward_backward call — used to compute num_steps for reporting only, does not affect cost (default: 1) |
TrainingCostEstimate fields: model, num_datums, total_tokens, num_steps, avg_tokens_per_datum, total_cost
estimate_sampling_cost(model, prompts, *, max_new_tokens) → SamplingCostEstimate
| Parameter | Type | Description |
|---|---|---|
model |
str |
Tinker model ID |
prompts |
Sequence[ModelInput | SampleRequest] or int |
Prompt objects or total prompt token count |
max_new_tokens |
int |
Max output tokens per prompt (worst-case) |
SamplingCostEstimate fields: model, num_prompts, total_prompt_tokens, max_new_tokens, prefill_cost, sample_cost, total_cost
How it works
How the standalone package relates to the Tinker SDK
This package has no hard dependency on tinker. It reads token counts via duck typing — it calls .model_input.length on whatever objects you pass in. If those objects are tinker.Datum instances (which have that property), it works. You install both packages separately and they never interact at import time:
pip install tinker tinker-cost
In your code you import from tinker as normal and call tinker_cost.estimate_training_cost with the Datum objects you already have.
How token counts are calculated
Training (estimate_training_cost): token count per datum comes from datum.model_input.length. The total is sum(lengths) × num_epochs. A forward_backward call is billed at the train rate per token, which covers the full forward + backward pass. Prefill and sample rates are not used here.
Sampling (estimate_sampling_cost): prompt token count comes from model_input.length (or sample_request.prompt.length). Prompt tokens are billed at the prefill rate; generated tokens are estimated as num_prompts × max_new_tokens and billed at the sample rate.
Pricing table
Rates are hardcoded from the Tinker models page and embedded at package release time — no network requests are made at runtime. Every call is pure local arithmetic. The tradeoff is that when TML updates their prices, this package needs a new release. The # Source: comment in _estimator.py links directly to where to get updated values.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tinker_cost-0.1.0.tar.gz.
File metadata
- Download URL: tinker_cost-0.1.0.tar.gz
- Upload date:
- Size: 36.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7c841ef4d8e8336db2af0f7ee2e975d0a51ef3deca2d73b80ac0574e38001bf
|
|
| MD5 |
23e2aabc1461bc886fc8f79e0cd32f78
|
|
| BLAKE2b-256 |
83ac1c498e5c890d50e0b4738f728f60679cdd55a9bdb5d9b77c188d32f0f552
|
File details
Details for the file tinker_cost-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tinker_cost-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b80d1994238aec9331f8716b8759adf8d932053d4f0e756ac7c0a76299aa07c
|
|
| MD5 |
6e95b498ecd8c037bf3850c3facf7802
|
|
| BLAKE2b-256 |
61393daad6c22b494edf10a311796cabd78990bbd16049f5720e58f200446ecf
|