Skip to main content
The scripts are in the repository, not in the installed package. Clone it, then cd recipes/04-train/hosted-loop before running the commands below. Browse this recipe on GitHub.
Four calls from graded rows to a chat completion from the trained model, all on the platform. One key, one A10G run, no GPU of your own. What you will learn: the shape of a train set and a task-disjoint holdout on the platform, what wai.train returns and how to wait on it, what wai.serve gives you back, and how to call the served adapter. The rows are deliberately small; this is the wiring check, not a result. You need WHILEAI_API_KEY (or whileai login); no model key, since the rows come from the template writer and a scripted agent.

What each step does

One run of python run.py with the defaults (--seed 1 --budget 96, SFT on Qwen/Qwen3-4B, one epoch): 24 train rows over 7 tasks, and a 72-row holdout because the splitter seeds the held-out side by failure signature first (see below). The loss numbers are one run’s; the platform trainer is not seeded, so yours will differ:
The rows here are small on purpose (a scripted agent, template situations) so the loop finishes in minutes. The loss drop shows the wiring works; it says nothing about the agent. Replace scripted_agent and judge with yours, or point data at rows you already graded.

What to know before you run it

  • Only two bases serve. Qwen/Qwen3-4B and microsoft/phi-4. The trainer’s defaults (Qwen2.5-0.5B for SFT, 1.5B for GRPO and DPO) train faster but cannot be hosted; wai.train warns and wai.serve refuses. SFT runs on an A10G and takes about a minute here; GRPO and DPO run on an L40S (--method grpo --steps 10 took 137 s on Qwen3-4B).
  • Cold starts. The serving GPU scales to zero. The first call after idle can take a few minutes; call waits up to fifteen.
  • Thinking mode. Qwen3 reasons before it answers unless told not to. call sends chat_template_kwargs: {"enable_thinking": false} so the reply is the answer, not the reasoning.
  • Cost. SFT here is about a minute of A10G, GRPO a few minutes of L40S. Serving bills while the GPU is awake; the endpoint idles back to zero on its own.
  • Holdout. split_pseudo_production moves whole tasks and seeds the held-out side with one task per failure signature first, so on a tiny set (7 tasks here) the holdout ends up larger than the fraction asks. That is fine for a wiring check; a real set has hundreds of tasks.

Where it shows up

run.url is the loss curve and the before/after on the platform. wai.models() lists what the account hosts, wai.get_run(run_id) returns the points, and the dataset cards link to the run. Docs: https://docs.withwhile.com/api/training
Last modified on September 19, 2026