--- title: Continuous learning | Lightcone description: Deploy a model that learns from your corrections. Because Lightcone is your inference endpoint, the pushback already in your traffic becomes tomorrow's model with one base_url change, metered as compute. --- Continuous learning is in private preview and disabled by default. The API and SDK surface here are stable enough to build against, but you must have it enabled for your organization. Contact . Calls made without the flag return `403 feature_not_enabled`. Lightcone learns from your corrections. Because Lightcone is your inference endpoint, most of those corrections are already in your traffic. When a user pushes back mid-conversation (“use the §4.2 wording, the term is 24 months, not 12”), that reply is a training signal. Lightcone detects it, reviews it, and folds it into tonight’s model. One `base_url` change takes a static model to one that gets better at *your* work every day. Metering is one number in two directions: **forward 1 CU, backward 2 CU per 1,000 tokens**. ## 1. Deploy a model One command provisions capacity and returns an OpenAI-compatible endpoint, a key, and a compute-unit balance. Terminal window ``` tzafon deploy lc-8b → provisioning capacity … done (2m 14s) → endpoint: https://api.tzafon.ai/v1 → key: sk-…f2a4 · balance: 2,500,000 CU (fwd 1 · bwd 2) ``` ## 2. Point your client It speaks the API you already use. Change `base_url` and keep the rest. SDKs, streaming, and tool calls all work unchanged. ``` from openai import OpenAI import os client = OpenAI( base_url="https://api.tzafon.ai/v1", api_key=os.environ["TZAFON_API_KEY"], ) ``` ``` import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.tzafon.ai/v1", apiKey: process.env.TZAFON_API_KEY, }); ``` ## 3. It’s already learning You don’t need a labeling pipeline or a training call. The corrective turns in your normal traffic *are* the signal. When a user replies to fix a response, Lightcone detects it automatically and queues it for tonight’s batch. ``` r = client.chat.completions.create( model="lc-8b", messages=[ ..., {"role": "user", "content": "Use §4.2 wording, the term is 24 months, not 12."}, ], ) # that turn is the training signal, detected automatically # queued → tonight's batch · 2 CU / 1k tok · same review queue, same eval gate ``` ``` const r = await client.chat.completions.create({ model: "lc-8b", messages: [ ..., { role: "user", content: "Use §4.2 wording, the term is 24 months, not 12." }, ], }); // that turn is the training signal, detected automatically // queued → tonight's batch · 2 CU / 1k tok · same review queue, same eval gate ``` Watch the queue in **console → training**. Turn capture off per key (`training: off`) or per request with a header: ``` r = client.chat.completions.create( model="lc-8b", messages=[...], extra_headers={"X-Lightcone-Training": "off"}, ) ``` ``` const r = await client.chat.completions.create( { model: "lc-8b", messages: [...] }, { headers: { "X-Lightcone-Training": "off" } }, ); ``` ## 4. Precision teaching (optional) For pipelines with ground truth, non-conversational workloads, or teaching after the fact, attach a correction explicitly. It lands in the same review queue, behind the same eval gate, and meters as backward passes. ``` client.corrections.create( completion_id=r.id, correction="Use §4.2 wording, the term is 24 months, not 12.", ) # queued → tonight's batch · backward pass @ 2 CU / 1k tok # tomorrow, lc-8b knows. ``` ``` await client.corrections.create({ completion_id: r.id, correction: "Use §4.2 wording, the term is 24 months, not 12.", }); // queued → tonight's batch · backward pass @ 2 CU / 1k tok // tomorrow, lc-8b knows. ``` For computer-use workflows, the same idea applies: a [failed-run outcome or a human takeover](/cookbook/wrap-a-legacy-app-in-an-api/index.md) is a correction. Submit it here and the model improves at that workflow specifically. ## How it works Corrections don’t touch the live model. Each night (02:00–02:45 UTC, on your capacity, serving uninterrupted) the queued corrections train a **candidate checkpoint** by on-policy **self-distillation** (our SDPO method, Self-Distilled Policy Optimization): the model learns from its own verified-successful behavior, distilling it against a moving average of its own recent weights, so it generalizes the lesson rather than memorizing one phrasing. - **Verified outcomes are the signal.** No external labels or annotation pipeline. Only runs that pass their check are learned from. - **Stable by design.** Anchoring each update to the model’s own recent self is intended to keep new lessons from regressing what it already did well. (A design goal, not yet a published measurement.) The candidate is promoted **only if it beats the incumbent on your evals**. If a promotion ever regresses something, rollback is one call. The weights are a **private, per-organization** model. Your corrections never train the shared base model or any other customer’s. ## Core concepts | Concept | What it means | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | **Compute units (CU)** | One meter, two directions: forward **1 CU**, backward **2 CU** per 1,000 tokens. The meter is the invoice, with no separate training bill. | | **Corrections** | Plain language in, gradients out. Captured automatically from your conversations; the explicit API is for precision. | | **Checkpoints** | Nightly candidates that promote only if they beat the incumbent on your evals. Rollback is one call. | | **Capacity** | Shared pool while you serve base weights; dedicated nodes the moment your weights diverge from the base. | ## Manage checkpoints ``` status = client.learning.status() print(status.current_checkpoint, status.cu_balance, status.queue_depth) checkpoints = client.learning.checkpoints.list() client.learning.checkpoints.rollback("ckpt_00006") # instant revert ``` ``` const status = await client.learning.status(); console.log(status.current_checkpoint, status.cu_balance, status.queue_depth); const checkpoints = await client.learning.checkpoints.list(); await client.learning.checkpoints.rollback("ckpt_00006"); // instant revert ``` Each checkpoint carries the eval results it was promoted on. See the eval report in the console before promoting or rolling back. ## Rate limits & batch window - **Nightly training** runs 02:00–02:45 UTC on your capacity; serving is uninterrupted. - **Serving rate limit** is per key: 600 req/min on shared capacity, unmetered on dedicated nodes. ## Scope and guarantees - **Private, per-org weights.** Learning updates a model scoped to your organization. Your corrections never train the shared base model or another organization’s model. See [Security and data handling](/guides/security/index.md). - **Weight updates, not prompt-stuffing.** Corrections change the weights, so the lesson generalizes and survives across sessions. It is not a rules file appended to the prompt. - **Gated by your evals.** Every correction passes a review queue and an eval gate. A candidate promotes only if it beats the current model on your own evals. - **Reversible.** Roll back to any prior checkpoint in one call. ## API reference All routes require the preview flag; bodies and errors follow the standard [error model](/guides/errors/index.md). | Method | Path | Description | | ------ | ------------------------------------- | --------------------------------------------------------------------- | | `POST` | `/corrections` | Attach an explicit correction (`completion_id`, `correction`) | | `GET` | `/learning/status` | Current checkpoint, CU balance, training queue depth, next batch time | | `GET` | `/learning/checkpoints` | List checkpoints with their eval results | | `POST` | `/learning/checkpoints/{id}/rollback` | Revert to a checkpoint | Per-request control: `X-Lightcone-Training: off` skips capturing that request. Per-key control: set `training: off` on the key in the console. ## Next steps - [**Pricing**](/guides/pricing/index.md): how compute units meter forward and backward passes - [**Wrap a legacy app in a REST API**](/cookbook/wrap-a-legacy-app-in-an-api/index.md): where a failed run becomes a correction - [**Security and data handling**](/guides/security/index.md): how per-org weights and your data are isolated - [**Chat Completions**](/guides/chat-completions/index.md): the OpenAI-compatible surface you deploy onto