Propose a version-scoped recipe
The proposal combines an immutable dataset version, explicit rewards, an objective, and a desired outcome. Review every generated stage and budget before validation.
/v1/distill/recipes/proposeSend dataset_version, rewards, objective, and outcome. A proposal is advice; it does not start compute.
Validate the exact plan with a dry run
Create a run with dry_run: true. Lizzy resolves the version and rewards, compiles the stage graph, validates compute and budget, and stores a plan_hash. No GPU training or student publication occurs.
curl -X POST "https://<your-lizzy-host>/v1/distill/runs" \
+ -H "Authorization: Bearer $LIZZY_API_TOKEN" \
+ -H "Content-Type: application/json" \
+ -H "Idempotency-Key: dry-run-001" \
+ -d '{"dataset_version":"<dataset_version_id>","student_model_name":"support-student-v1","recipe":{"student_model":"<base-model>","rewards":["<reward_id>"],"stages":[{"kind":"sft","config":{"epochs":1}},{"kind":"eval","config":{}},{"kind":"publish","config":{}}]},"budget":{"max_cost_usd":25},"dry_run":true}'import os, requests
dry_run = requests.post(
"https://<your-lizzy-host>/v1/distill/runs",
headers={"Authorization": f"Bearer {os.environ['LIZZY_API_TOKEN']}", "Idempotency-Key": "dry-run-001"},
json={
"dataset_version": "<dataset_version_id>",
"student_model_name": "support-student-v1",
"recipe": recipe,
"budget": {"max_cost_usd": 25},
"dry_run": True,
},
).json()const response = await fetch("https://<your-lizzy-host>/v1/distill/runs", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.LIZZY_API_TOKEN}`, "Content-Type": "application/json", "Idempotency-Key": "dry-run-001" },
body: JSON.stringify({
dataset_version: "<dataset_version_id>", student_model_name: "support-student-v1",
recipe, budget: { max_cost_usd: 25 }, dry_run: true,
}),
});
if (!response.ok) throw await response.json();
const dryRun = await response.json();Approve live training
- 1Dry run succeeds
Keep its ID and immutable plan hash.
- 2Review the proposal
Check version, rewards, stages, compute, and hard budget.
- 3Approve in Lizzy
The copilot creates an approval request, not an unbounded live call.
- 4Start the exact plan
Send validated_dry_run and the matching plan_hash with dry_run false.
{
"dataset_version": "<dataset_version_id>",
"student_model_name": "support-student-v1",
"recipe": { "<same recipe used for validation>": "<unchanged>" },
"budget": { "max_cost_usd": 25 },
"dry_run": false,
"validated_dry_run": "<dry_run_id>",
"plan_hash": "<plan_hash>"
}Watch a run without polling forever
Persist the run ID and inspect GET /v1/distill/runs/{run_id}. Terminal states are succeeded, failed, and canceled. Bounded watches resume from the last checkpoint and return control when there is no progress.
/v1/distill/runs/{run_id}/cancelCancel a running job to stop future spend. Do not retry a failed stage blindly; inspect logs and use the UI for an explicit retry decision.