Skip to content

Kiln server kiln-v0.4.0 — embedded pi agent

Choose a tag to compare

@github-actions github-actions released this 12 Jun 05:08
· 1207 commits to main since this release

The flywheel closes by itself: kiln now spawns and drives pi as a managed
child process — submit a task over HTTP, watch the trajectory stream, and the
finished session lands in the agent-trace layer the self-improvement loop
trains on. Plus Muon becomes the default optimizer across every training mode.

  • agent: embedded pi runs (POST /v1/agent/runs) — the server spawns
    pi --mode rpc against its own OpenAI-compatible endpoint (same
    non-destructive pi-setup config merge as the embedded terminal, now
    serialized + atomic + skip-if-unchanged), streams the full agent event
    trajectory, and auto-merges the finished session JSONL into
    agent_traces.json under a cross-process file lock. Runs queue FIFO
    ([agent].max_concurrent_runs, default 2; run_timeout_secs, default 900;
    32-active backstop enforced atomically), persist to
    <adapter_dir>/agent_runs/runs.json across restarts (in-flight runs come
    back interrupted), and write sessions to per-run directories so a run
    that dies before flushing can never adopt a sibling's session.
  • agent: mid-run control — POST /v1/agent/runs/{id}/steer, /follow_up,
    and /abort. Messages sent while a run is still queued are buffered and
    delivered the moment it starts. The live feed is
    GET /v1/agent/runs/{id}/events?after=<seq> (inclusive cursor; pass the
    response's next_after back; truncated/first_available_seq flag replay
    gaps after ring-buffer prunes or restarts).
  • agent: honest outcomes — a run whose final assistant turn ended in an error
    reports failed with the error text, never a hollow completed; sessions
    from aborted/timed-out runs still index (partial trajectories are data).
  • agent: security posture matches the embedded terminal — enabled on loopback
    binds only, KILN_AGENT_RUNS=1 opts in on network binds, =0
    force-disables — and the gate covers the read endpoints too, since run
    records and event feeds carry task prompts, server paths, and raw tool
    output. KILN_PI_BIN overrides pi discovery for non-PATH installs.
  • dashboard: new Distill → Agent runs tab — launch form (task / cwd /
    label), live run list, and a drill modal with a 1s-polled event feed
    (assistant text, tool calls and results, errors), steer/follow-up/abort,
    and #distill/runs/{id} deep links on the shared modal conventions.
  • traces: POST /v1/agent/traces/discover also sweeps
    <adapter_dir>/agent_runs/sessions/, so rebuilding the index from
    ~/.pi never drops the rollouts kiln generated itself.
  • training: learning rates now resolve per optimizer. learning_rate is
    optional in the SFT/GRPO/OPD configs; when omitted, the trainer picks the
    selected optimizer's band — Muon (the default): SFT 2e-2, GRPO/OPD 2e-3;
    AdamW/SGD keep the legacy defaults (SFT 1e-4, GRPO/OPD 1e-5). This fixes a
    silent foot-gun from the Muon flip: the old AdamW-era defaults trained Muon
    100–400x too cold. Explicit values still deserialize and are used verbatim
    (full wire back-compat), train receipts record the resolved value, and an
    explicit lr more than 50x outside the optimizer's band logs a warning at
    run start. The dashboard's SFT/GRPO/OPD learning-rate fields now default to
    blank ("auto (per optimizer)") and omit the field from the request when
    blank; kiln train sft --lr is likewise optional. The Muon GRPO/OPD band
    scales the legacy AdamW SFT:GRPO ratio and is an initial heuristic pending
    an empirical sweep.
  • training: Muon is now the default optimizer for every training mode
    (SFT, GRPO, on-policy distillation / OPD, and the judge-LoRA flywheel that
    rides the OPD path). Muon is momentum-orthogonalized SGD — it keeps one
    per-parameter heavy-ball momentum buffer (vs AdamW's two moments), takes a
    Nesterov look-ahead, and projects the LoRA A/B weight-matrix updates onto
    the nearest semi-orthogonal matrix via a Newton-Schulz iteration before
    stepping, rescaling by sqrt(max(rows, cols)) so the update magnitude is
    shape-independent. It converges LoRA fine-tunes in fewer steps than AdamW at
    roughly half the optimizer state.
  • training: fused on-device Muon kernels for every backend — CUDA, ROCm,
    Vulkan, and Metal — implementing the whole step (heavy-ball momentum +
    Newton-Schulz orthogonalization + decoupled-weight-decay descent) in a
    single fused per-matrix launch. Newton-Schulz is computed in gram space via
    a k×k P-accumulator (k = LoRA rank), so the cost is dominated by two
    skinny GEMMs over the large matrix dimension. The portable CPU reference in
    kiln-optim is the parity oracle the GPU kernels are validated against.
  • API: the optimizer is still selected per training request. Omit the
    optimizer field to get Muon; opt back into the old behaviour with
    {"optimizer": {"kind": "adam_w"}} or {"optimizer": {"kind": "sgd"}}.
    Muon accepts momentum (0.95), nesterov (true), ns_iters (5), and
    weight_decay (0.0). Note Muon wants a larger learning rate than AdamW
    (~2e-2 vs ~1e-4 for LoRA), since its update is orthogonalized and
    RMS-matched to unit scale.

Install: prebuilt binaries below (Linux CUDA 12.4 / ROCm 7.2.4 / Vulkan 1.2, macOS Apple Silicon Metal, Windows CUDA 12.4), or ghcr.io/ericflo/kiln-server:0.4.0 / latest.

supported_sm: [80, 86, 89, 90]
min_cuda: 12.4
rocm: 7.2.4
rocm_archs: [gfx90a, gfx942, gfx1100, gfx1151]
vulkan: 1.2