← TinyGPT · docs · devlog · roadmap · speedup
source: docs/learn/castform-rl-finetune.md · view on GitHub ↗

Castform RL fine-tune — what we stole

Source: castform.com — RL fine-tune SaaS that lets engineers train open-source models on proprietary data + a user-defined reward function. Visited 2026-06-13; surface inspected via product copy + the public Python SDK sketches.

Why look at them: Castform’s product thesis (“4B fine-tuned beats GPT-5.4 on the narrow task at 1.0× the cost”) is identical to TinyGPT’s Mac-specialist thesis. The interesting question isn’t whether small models can win — it’s which engineering primitives make training them practical. Castform exposes four that are worth borrowing.

This page is a steal-map (same format as agent-context-hierarchy.md): one section per pattern, what it gives us, where it goes in the PRDs.

The four steals

1. Composite reward functions — filed as B28

Castform: a reward is a composition of named dimensionscorrectness + conciseness + citation + tool_call_efficiency — each independently scorable, then aggregated via weights into the training signal. The dashboard shows the per-dimension breakdown per rollout so you can see which axis is driving the gradient.

Where we are: DPO has a single implicit reward from log_π_pol − log_π_ref. ES has a single scalar (negative loss). There’s no abstraction for “this reward is actually four things in a trenchcoat”, which is the practical shape every real specialist eventually needs.

Filed as B28 composite-reward-framework in PLAN.md — a Reward struct with named dimensions, weighted aggregation, per-dimension logging. Usable from DPO (as the chosen/rejected score), GRPO (5.1), and ES.

The base struct ships in this PR (CompositeReward.swift). The training-loop integrations are the rest of B28.

2. Trace-driven dataset synthesis — filed as B29

Castform: pull from production agent traces (Braintrust, Langfuse, LangSmith) and RAG corpora (Turbopuffer, Pinecone, Chroma, Postgres). Auto-filter via dedup + tool-echo drop + LLM-judge pivot at configurable thresholds (0.6–0.9). The output is a training-ready JSONL the user never had to hand-label.

Where we are: B22 (token-preserving trajectory recorder) ships the substrate — every .atraj file carries input_ids, output_ids, tool calls, rewards. But there’s no consumer that turns the substrate into SFT/DPO training data.

Filed as B29 trace-to-training-data in PLAN.md — the bridge between B22 and A1. Reads .atraj files, runs the existing tinygpt dedupe, tinygpt judge (E7) shims for filtering, emits training JSONL.

3. Multi-hop reasoning classification — filed as B30

Castform: classify training prompts by reasoning depth (single-hop, multi-hop, comparison) so the training mix is balanced — too much single-hop and the model never learns to chain. Too much multi-hop on a base that hasn’t shipped basic capability yet and it diverges.

Where we are: no classifier; balance is per-corpus by hand. Works for narrow specialists; falls over for the agent-trace data B29 will produce, which is intrinsically mixed-depth.

Filed as B30 prompt-reasoning-classifier — small classifier head trained on a labeled subset, scores any prompt into {single-hop, multi-hop, comparison, other}. Drops into B29’s filtering pipeline + the leaderboard’s per-category breakdown.

4. Pluggable BaseEnv interface — not filed (out of scope)

Castform: users subclass BaseEnv with async run_tool() + compute_reward(). The platform handles rollouts + the training loop. This is a UX choice for a SaaS surface.

Where we are: TinyGPT is a CLI + Swift library, not a SaaS. Users write a Swift EvalCompare.Row row or a Python eval harness; the “plug in your env” abstraction is already there, just spelled in two languages.

Deliberately not filed. The B6 Mac app (Factory tab) is the right place for a friendlier env-config UX, and B6 already covers that — adding a BaseEnv Python class layer is fake reuse since the underlying mechanism is the same.

What we deliberately did not steal

The addition this analysis surfaced (our note)

Castform’s “solve rate (pass@k)” metric is the per-prompt version of what B23 protocol does across the eval suite. Combined: every leaderboard row reports mean ± σ (B23) AND the per-prompt pass@k distribution under the recorded budget. That’s a deliverable for B23’s V2 — not blocking now, but the data is free once K-pass rollouts are running.