build strategy · tinker

Train once, ship the report.

Every mega-prompt in this archive collapses into the same shape: a Python Tinker training script that runs once in Lovable's Linux build sandbox, plus a static TanStack route that renders its JSON output. Deployed apps make zero AI calls at runtime — training already happened.

Why Tinker?

Thinking Machines' Tinker exposes LoRA post-training as a clean Python API — ServiceClient, forward_backward_async, optim_step_async, sample_async. Fine-tune Qwen3-8B or GPT-OSS-20B on a few dozen examples without ever renting a GPU. One API, four loss functions, a real checkpoint at the end.

Why the Lovable sandbox?

Cloudflare Workers can't run Python. Lovable's build agent runs on Linux with Python installed — that's the only place the Tinker Python SDK has to live. Train once during the build turn, commit the artifact JSON, and the deployed site is a fast, static report page.

The pattern in code.

scripts/train.py — runs in the build sandbox
# scripts/train.py — runs ONCE in Lovable's Linux build sandbox.
#   python -m pip install -q tinker
#   TINKER_API_KEY=... python scripts/train.py
# Writes src/data/run-artifact.json (loss curve + before/after samples).
import asyncio, json, pathlib, tinker
from tinker import types

BASE = "Qwen/Qwen3-8B"
PAIRS = [{"prompt": "...", "completion": "..."}]  # 40+ real examples

async def main():
    svc   = tinker.ServiceClient()                     # reads TINKER_API_KEY
    train = svc.create_lora_training_client(base_model=BASE, rank=16)
    tok   = train.get_tokenizer()

    def datum(p, c):
        pi, ci = tok.encode(p), tok.encode(c) + [tok.eos_token_id]
        ids = pi + ci
        return types.Datum(
            model_input=types.ModelInput.from_ints(tokens=ids),
            loss_fn_inputs=dict(target_tokens=ids[1:] + [tok.eos_token_id],
                                weights=[0]*len(pi) + [1]*len(ci)))
    data = [datum(x["prompt"], x["completion"]) for x in PAIRS]

    losses = []
    for step in range(200):
        b  = data[(step*4) % len(data): (step*4) % len(data) + 4] or data[:4]
        fb = await train.forward_backward_async(data=b, loss_fn="cross_entropy")
        losses.append([step, float((await fb.result_async()).loss)])
        await (await train.optim_step_async(types.AdamParams(learning_rate=1e-4))).result_async()

    tuned = train.save_weights_and_get_sampling_client(name="final")
    # ... sample before/after here, write JSON ...
    pathlib.Path("src/data/run-artifact.json").write_text(json.dumps({
        "base_model": BASE, "kernel": "sft-instruct",
        "training": {"steps": 200, "loss_curve": losses}, "samples": []}))

asyncio.run(main())
src/routes/index.tsx — deployed report page
// src/routes/index.tsx — deployed app is a STATIC report page.
// It imports the JSON artifact produced above; no runtime API calls,
// no Python, no Tinker key on Cloudflare Workers.
import { createFileRoute } from "@tanstack/react-router";
import artifact from "@/data/run-artifact.json";

export const Route = createFileRoute("/")({ component: Report });

function LossCurve({ points }: { points: [number, number][] }) {
  const w = 800, h = 240;
  const max = Math.max(...points.map((p) => p[1]));
  const d = points.map((p, i) =>
    `${i ? "L" : "M"}${(i / (points.length - 1)) * w},${h - (p[1] / max) * h}`
  ).join(" ");
  return <svg viewBox={`0 0 ${w} ${h}`}><path d={d} fill="none" stroke="currentColor" /></svg>;
}

function Report() {
  const a = artifact as typeof artifact;
  return (
    <main>
      <h1>{a.base_model} · {a.kernel}</h1>
      <LossCurve points={a.training.loss_curve} />
      {a.samples.map((s, i) => (
        <div key={i}>{s.prompt} → {s.before} · {s.after}</div>
      ))}
    </main>
  );
}
env + Lovable build turn
# Only ONE secret is used — and only at BUILD time.
TINKER_API_KEY=tk_...   # https://tinker-console.thinkingmachines.ai

# How Lovable stitches it all together in one prompt:
# 1. Paste a mega-prompt from this archive.
# 2. Lovable, in its Linux sandbox:
#      python -m pip install -q tinker
#      TINKER_API_KEY=... python scripts/train.py
#    -> writes src/data/run-artifact.json (loss curve + samples)
# 3. Lovable then writes src/routes/index.tsx that imports the artifact
#    and renders the training report — hero + SVG loss curve + gallery.
# 4. Deployed on Cloudflare Workers. Zero runtime API calls. Zero
#    server functions. The report is the artifact.

Shipping a 5-credit demo