> ## Documentation Index
> Fetch the complete documentation index at: https://fireworks.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction

> Fireworks Training API — custom training loops with full Python control over objectives, while Fireworks handles distributed GPU infrastructure.

export const TrainingLifecycle = () => {
  const PATHS = [{
    id: "serverless",
    label: "Serverless",
    tone: "tl-blue",
    link: "tl-link tl-blue",
    note: "Billed per token, no idle GPU cost. Nothing to provision.",
    href: "/fine-tuning/training-api/serverless"
  }, {
    id: "dedicated",
    label: "Dedicated",
    tone: "tl-orange",
    link: "tl-link tl-orange",
    note: "Time-based billing on GPUs you provision and hold.",
    href: "/fine-tuning/training-api/dedicated"
  }];
  const [activeId, setActiveId] = useState("serverless");
  const active = PATHS.find(p => p.id === activeId) || PATHS[0];
  const WRITE = {
    title: "Write your training loop",
    sub: "Plain Python on your machine, no local GPUs",
    pills: ['pip install "fireworks-ai[training]"']
  };
  const STAGES = [{
    id: "connect",
    serverless: {
      title: "Connect to the pool",
      timing: "Effectively instant",
      sub: "Attach to an always-on trainer. No trainer job or deployment to create.",
      pills: ["FiretitanServiceClient", "create_lora_training_client()"]
    },
    dedicated: {
      title: "Provision trainer and deployment",
      timing: "Minutes to tens of minutes",
      sub: "You set the trainer and deployment configuration. The SDK creates both resources.",
      pills: ["from_firetitan_config()", "create_deployment_sampler()"]
    }
  }, {
    id: "train",
    serverless: {
      title: "Train on shared trainer instances",
      timing: "Shared throughput",
      sub: "LoRA only. Trainer capacity is shared with other tenants.",
      pills: ["forward_backward()", "optim_step()"]
    },
    dedicated: {
      title: "Train on your dedicated GPUs",
      timing: "Faster, no contention",
      sub: "LoRA or full-parameter, with the whole trainer to yourself.",
      pills: ["forward_backward()", "forward_backward_custom()", "optim_step()"]
    }
  }, {
    id: "sample",
    serverless: {
      title: "Sample on shared deployment instances",
      timing: "No weight sync",
      sub: "Sample from a checkpoint without syncing weights onto a deployment.",
      pills: ["save_weights_for_sampler()", "create_sampling_client()"]
    },
    dedicated: {
      title: "Faster sampling on dedicated deployments",
      timing: "Weight sync each checkpoint",
      sub: "Checkpoint, weight-sync, then sample through your own deployment.",
      pills: ["save_weights_for_sampler()", "create_deployment_sampler(model_path=...)"]
    }
  }];
  const PROMOTE = {
    title: "Promote the checkpoint, then deploy",
    sub: "Promote the newest promotable checkpoint to a Fireworks model, then deploy it with live merge or load it onto a multi-LoRA deployment. Serverless promotes a session checkpoint and dedicated promotes a job checkpoint, but the step is the same.",
    pills: ["promote_session_checkpoint()", "promote_checkpoint()", "deployments.create()"]
  };
  const TEARDOWN = {
    serverless: {
      title: "Nothing to tear down",
      sub: "Close the sampler and service client at the end of a run as good practice, but nothing was provisioned, so there is no idle GPU cost to reclaim.",
      pills: ["service.close()"]
    },
    dedicated: {
      title: "Tear down the trainer and deployment",
      sub: "Time-based billing runs until you close them. An idle trainer also stops on its own after 10 minutes with no activity, so a forgotten session does not bill indefinitely.",
      pills: ["service.close()"]
    }
  };
  const CSS = `
.tl-root {
  --tl-sub: #52525b; --tl-muted: #5f5f68; --tl-edge: #e4e4e7;
  --tl-surface: #ffffff; --tl-track: rgba(113,113,122,0.10);
  --tl-track-line: rgba(113,113,122,0.28);
  --tl-code-bg: #ffffff; --tl-code-fg: #18181b; --tl-code-line: #c7c7cd;
}
.dark .tl-root {
  --tl-sub: #a1a1aa; --tl-muted: #a1a1aa; --tl-edge: #3f3f46;
  --tl-surface: #18181b; --tl-track: rgba(113,113,122,0.16);
  --tl-track-line: rgba(113,113,122,0.35);
  --tl-code-bg: #0b0b0e; --tl-code-fg: #f4f4f5; --tl-code-line: #52525b;
}
.tl-blue {
  --c-bg: #eff6ff; --c-line: #bfdbfe; --c-title: #1e3a8a;
  --c-label: #1d4ed8; --c-fill: #dbeafe; --c-fill-fg: #1e40af; --c-strong: #2563eb;
}
.dark .tl-blue {
  --c-bg: rgba(37,99,235,0.13); --c-line: rgba(96,165,250,0.38); --c-title: #dbeafe;
  --c-label: #93c5fd; --c-fill: rgba(96,165,250,0.20); --c-fill-fg: #bfdbfe; --c-strong: #60a5fa;
}
.tl-orange {
  --c-bg: #fff7ed; --c-line: #fed7aa; --c-title: #7c2d12;
  --c-label: #c2410c; --c-fill: #ffedd5; --c-fill-fg: #9a3412; --c-strong: #ea580c;
}
.dark .tl-orange {
  --c-bg: rgba(234,88,12,0.13); --c-line: rgba(251,146,60,0.38); --c-title: #ffedd5;
  --c-label: #fdba74; --c-fill: rgba(251,146,60,0.18); --c-fill-fg: #fed7aa; --c-strong: #fb923c;
}
.tl-emerald {
  --c-bg: #ecfdf5; --c-line: #a7f3d0; --c-title: #064e3b;
  --c-label: #047857; --c-fill: #d1fae5; --c-fill-fg: #065f46; --c-strong: #059669;
}
.dark .tl-emerald {
  --c-bg: rgba(5,150,105,0.13); --c-line: rgba(52,211,153,0.35); --c-title: #d1fae5;
  --c-label: #6ee7b7; --c-fill: rgba(52,211,153,0.18); --c-fill-fg: #a7f3d0; --c-strong: #34d399;
}
.tl-root {
  border: 1px solid var(--tl-edge); background: var(--tl-surface);
  border-radius: 16px;
}
.tl-card {
  border: 1px solid var(--c-line); background: var(--c-bg);
  border-radius: 12px; padding: 11px 15px;
}
.tl-eyebrow {
  color: var(--c-label); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 3px;
}
.tl-title { color: var(--c-title); font-size: 14px; font-weight: 600; }
.tl-sub { color: var(--tl-sub); font-size: 13px; line-height: 1.45; margin-top: 3px; }
.tl-chip {
  display: inline-flex; align-items: center; line-height: 1.2; margin-left: auto;
  padding: 2px 8px; border-radius: 999px; font-size: 10.5px; font-weight: 600;
  white-space: nowrap; border: 1px solid var(--c-line);
  background: var(--c-fill); color: var(--c-fill-fg);
}
/* A signature reads as code, so it gets a plain surface rather than the card's
   tint, and a neutral border rather than the card's: a tinted edge against a
   tinted card left the chip with almost nothing to separate it. Weight 500 at
   13px is what makes monospace hold up on a 1x display, where 12px at 400 goes
   thin and grey. No nowrap: create_deployment_sampler(model_path=...) is wider
   than a card and would be clipped rather than wrapped. */
.tl-pill {
  display: inline-block; padding: 3px 8px; border-radius: 6px;
  font-size: 13px; font-weight: 500; line-height: 1.45;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
  background: var(--tl-code-bg); color: var(--tl-code-fg);
  border: 1px solid var(--tl-code-line);
  max-width: 100%; overflow-wrap: anywhere;
}
.tl-track {
  display: inline-flex; gap: 4px; padding: 4px; border-radius: 10px;
  background: var(--tl-track); border: 1px solid var(--tl-track-line);
}
.tl-seg {
  padding: 5px 14px; border-radius: 7px; font-size: 12.5px; font-weight: 500;
  border: 1px solid transparent; background: transparent; color: var(--tl-muted);
  cursor: pointer; transition: color 0.12s, background-color 0.12s;
}
/* :not() keeps hover off the selected segment, whose own colour is set below
   and would otherwise lose to this rule on specificity. */
.tl-seg:not(.tl-seg-on):hover { color: var(--c-label); }
.tl-seg-on {
  background: var(--c-fill); border-color: var(--c-strong);
  color: var(--c-title); font-weight: 600;
}
.tl-box { border: 1px dashed var(--c-line); border-radius: 14px; padding: 10px 12px 12px; }
.tl-box-label { text-align: center; font-size: 12px; font-weight: 600; color: var(--c-label); }
.tl-note { text-align: center; font-size: 11.5px; line-height: 1.4; color: var(--tl-muted); }
.tl-foot { font-size: 11px; line-height: 1.6; color: var(--tl-muted); }
.tl-arrow { display: flex; justify-content: center; padding: 6px 0; color: var(--tl-muted); }
.tl-link { color: var(--c-label); text-decoration: underline; }
.tl-link:hover { color: var(--c-title); }
`;
  const Arrow = () => <div className="tl-arrow" aria-hidden="true">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none">
        <path d="M12 4v14M6 13l6 6 6-6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      </svg>
    </div>;
  const Card = ({data, tone, eyebrow}) => <div className={"tl-card " + tone}>
      {eyebrow && <div className="tl-eyebrow">{eyebrow}</div>}
      <div className="flex items-baseline justify-between gap-2 flex-wrap">
        <span className="tl-title">{data.title}</span>
        {data.timing && <span className="tl-chip">{data.timing}</span>}
      </div>
      {data.sub && <div className="tl-sub">{data.sub}</div>}
      {data.pills && data.pills.length > 0 && <div className="mt-2 flex flex-wrap gap-1.5">
          {data.pills.map(p => <span key={p} className="tl-pill">
              {p}
            </span>)}
        </div>}
    </div>;
  return <div className="tl-root not-prose mt-4 mb-6 p-4 md:p-5">
      <style>{CSS}</style>

      <Card data={WRITE} tone="tl-emerald" eyebrow="Both paths" />
      <Arrow />

      {}
      <div className="flex flex-col items-center gap-1.5 mb-3">
        <div className="tl-track" role="group" aria-label="Training infrastructure">
          {PATHS.map(p => <button key={p.id} type="button" aria-pressed={p.id === activeId} onClick={() => setActiveId(p.id)} className={p.id === activeId ? "tl-seg tl-seg-on " + p.tone : "tl-seg " + p.tone}>
              {p.label}
            </button>)}
        </div>
        <div className="tl-note">{active.note}</div>
      </div>

      <div className={"tl-box " + active.tone}>
        {}
        <div className="tl-box-label mb-2">Runs on Fireworks GPUs</div>
        {STAGES.map((s, i) => <div key={s.id}>
            {i > 0 && <Arrow />}
            <Card data={s[activeId]} tone={active.tone} />
          </div>)}
        <div className="tl-note mt-2.5">Train and sample repeat every training step</div>
      </div>

      <Arrow />
      <Card data={PROMOTE} tone="tl-emerald" eyebrow="Both paths" />
      <Arrow />
      <Card data={TEARDOWN[activeId]} tone={active.tone} eyebrow={active.label} />

      <div className="tl-foot mt-3">
        <div>
          <code>forward_backward()</code> runs a built-in trainer-side loss and is what most loops
          use. <code>forward_backward_custom()</code> is only for a custom Python loss function.
        </div>
        <div className="mt-1">
          A fine-tuned LoRA deploys to an on-demand deployment on either path. Serverless per-token
          serving of your own adapter is not available.
        </div>
        <div className="mt-1.5">
          Full walkthrough:{" "}
          {PATHS.map((p, i) => <span key={p.id}>
              {i > 0 && " · "}
              <a href={p.href} className={p.link}>
                {p.label} Training
              </a>
            </span>)}
        </div>
      </div>
    </div>;
};

<Info>
  The Training API is currently in **private preview**. [Request early access](https://fireworks.ai/contact-training) to get started.
</Info>

<Tip>
  **Using a coding agent?** Install the [Fireworks training skill](/docs/fine-tuning/agent/use-with-coding-agents) to help configure, run, and troubleshoot training jobs using current Fireworks best practices.
</Tip>

## What is the Training API?

Fireworks Training API lets you write training logic in plain Python on your local machine while model computation runs on remote GPUs managed by Fireworks.

Most users should start from [Cookbook recipes](/docs/fine-tuning/training-api/cookbook/overview), the recommended entry point for standard SFT, DPO, GRPO-style training, and experimental async RL loops for agentic RL. Recipes use the Python SDK and can be run directly or through your agent.

Use the Python SDK directly when you need full control over Training API behavior.

| Starting point      | Best for                                                               | How you use it                                              |
| ------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------- |
| **Cookbook recipe** | Adapting a working SFT, DPO, GRPO-style, or experimental async RL loop | Run it with the Python SDK directly or through your agent   |
| **Python SDK**      | Full control over training behavior                                    | Write the training flow in Python while Fireworks runs GPUs |

## Choose serverless or dedicated infrastructure

After choosing the Training API, decide how compute is provided:

* [**Serverless Training**](/docs/fine-tuning/training-api/serverless): shared pooled trainer, LoRA SFT, DPO, or RL on supported models, no provisioning, per-token billing.
* [**Dedicated Training**](/docs/fine-tuning/training-api/dedicated): provisioned trainer and deployment resources, broader model and method support, explicit checkpoint/resume/deployment control.

Use the [infrastructure decision guide](/docs/fine-tuning/training-api/choose-infrastructure) before adapting a recipe.

## Who does what

| Fireworks handles                                                        | Cookbook recipes handle                                                    | Python SDK users implement                                                     |
| ------------------------------------------------------------------------ | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| GPU provisioning and cluster management                                  | Training loop structure for supported recipes                              | Training loop logic (`forward_backward_custom` + `optim_step`)                 |
| Service-mode trainer lifecycle (create, health-check, reconnect, delete) | Resource setup, health checks, reconnect, and cleanup                      | Managed service setup with `FiretitanServiceClient.from_firetitan_config(...)` |
| Distributed forward pass, backward pass, optimizer execution             | Common losses and reward/evaluation plumbing                               | Loss function and batch construction                                           |
| Checkpoint storage and export                                            | Checkpoint save, resume, promotion, and sampler refresh                    | Checkpoint calls (`save_weights_for_sampler`, DCP snapshots)                   |
| Inference deployments and weight sync                                    | Deployment sampling and serving-integrated evaluation for RL recipes       | Custom rollout, sampling, and evaluation logic through the managed service     |
| Preemption recovery and job resume                                       | Resume logic for supported recipe checkpoints                              | Resume policy and state restoration calls                                      |
| Distributed training (multi-node, sharding, FSDP)                        | Config surfaces for learning rate, grad accumulation, context length, W\&B | Hyperparameter schedules, data pipeline, and experiment tracking               |

## System architecture

<div
  role="img"
  aria-label="Training API lifecycle from a local Python loop through Fireworks training and sampling infrastructure"
  style={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))",
gap: "0.75rem",
margin: "1.5rem 0",
}}
>
  <div style={{ border: "1px solid rgba(146, 73, 231, 0.4)", borderRadius: "0.75rem", padding: "1rem" }}>
    <div style={{ fontSize: "0.75rem", fontWeight: 700, textTransform: "uppercase" }}>1 · Your laptop</div>
    <strong>Python loop</strong>

    <div style={{ fontSize: "0.875rem", marginTop: "0.35rem" }}>
      Loads data, builds batches, computes rewards, and controls the experiment.
    </div>
  </div>

  <div style={{ border: "1px solid rgba(146, 73, 231, 0.4)", borderRadius: "0.75rem", padding: "1rem" }}>
    <div style={{ fontSize: "0.75rem", fontWeight: 700, textTransform: "uppercase" }}>2 · Fireworks API</div>
    <strong>Control plane</strong>

    <div style={{ fontSize: "0.875rem", marginTop: "0.35rem" }}>
      Authenticates requests, routes operations, and manages the selected infrastructure.
    </div>
  </div>

  <div style={{ border: "1px solid rgba(146, 73, 231, 0.4)", borderRadius: "0.75rem", padding: "1rem" }}>
    <div style={{ fontSize: "0.75rem", fontWeight: 700, textTransform: "uppercase" }}>3 · Remote compute</div>
    <strong>GPU trainer</strong>

    <div style={{ fontSize: "0.875rem", marginTop: "0.35rem" }}>
      Runs forward passes, backward passes, and optimizer steps.
    </div>
  </div>

  <div style={{ border: "1px solid rgba(146, 73, 231, 0.4)", borderRadius: "0.75rem", padding: "1rem" }}>
    <div style={{ fontSize: "0.75rem", fontWeight: 700, textTransform: "uppercase" }}>4 · Separate compute</div>
    <strong>Sampling</strong>

    <div style={{ fontSize: "0.875rem", marginTop: "0.35rem" }}>
      Serves saved weights for rollouts and evaluation outside the trainer.
    </div>
  </div>

  <div style={{ border: "1px solid rgba(146, 73, 231, 0.4)", borderRadius: "0.75rem", padding: "1rem" }}>
    <div style={{ fontSize: "0.75rem", fontWeight: 700, textTransform: "uppercase" }}>5 · Persistent output</div>
    <strong>Artifacts</strong>

    <div style={{ fontSize: "0.875rem", marginTop: "0.35rem" }}>
      Stores sampler snapshots and resumable training state for later use.
    </div>
  </div>
</div>

Your Python process stays on your laptop throughout the run. It sends model operations to Fireworks and receives metrics or completions back. Sampling uses separate inference infrastructure rather than the trainer itself.

## How service-mode training works

<Warning>
  **Most common gotchas**

  * Remote operations such as `forward`, `forward_backward`, `optim_step`, sampling, and checkpoint saves return future-like results. Call `.result()` on operations that return one.
  * `token_weights=0` means prompt/no-loss tokens, `token_weights=1` means response/learned tokens.
  * `forward_backward_custom` computes gradients only; you still need `optim_step` to apply updates.
</Warning>

### Minimal training step lifecycle

The shape of the loop is the same on both infrastructures. Toggle between them to see what changes at each stage:

<TrainingLifecycle />

### Datums

A **Datum** is the unit of training data sent to the remote GPU. It wraps tokenized input and per-token weights that your loss function needs.

For SFT, token weight `0.0` marks prompt tokens and `1.0` marks response tokens. Cookbook renderers construct these weights from chat messages.

### Logprobs and forward\_backward\_custom

When you call `forward_backward_custom`, the GPU runs a forward pass and returns **per-token log-probabilities** as PyTorch tensors with `requires_grad=True`. Your loss function computes a scalar loss, the API calls `loss.backward()`, and gradients are sent back to the GPU for the model backward pass.

After accumulating gradients, call `optim_step` to apply the update. See the [Dedicated Training Quickstart](/docs/fine-tuning/training-api/quickstart) for one complete runnable Datum, loss, and optimizer loop.

### Futures

Remote training operations such as `forward`, `forward_backward`, `optim_step`, and checkpoint saves return **future-like results**. Call `.result()` on operations that return one so failures surface.

### Checkpointing and weight sync

After training, you export checkpoints for serving:

* **Base snapshot:** a complete chain anchor for the trainable state. For LoRA this is the adapter; for full-parameter training it is model weights.
* **Delta snapshot:** a change relative to a prior full-parameter base snapshot.

The SDK selects base versus delta automatically unless the recipe overrides it.

Checkpoint-to-sampler behavior depends on the infrastructure:

* **Serverless:** save a snapshot and bind an in-session sampling client to that snapshot. There is no deployment weight sync. See [Serverless Training](/docs/fine-tuning/training-api/serverless).
* **Dedicated:** save a snapshot and refresh an SDK-managed deployment sampler, which syncs weights onto the deployment. See [Dedicated Training and Sampling](/docs/fine-tuning/training-api/training-and-sampling).

For dedicated RL rollouts that continue across weight sync, see [KV cache behavior for RL rollouts](/docs/guides/rollout-inference#kv-cache-behavior-for-rl-rollouts).

### Dedicated RL rollout transition mode

When a dedicated RL recipe provisions a hot-load rollout deployment, you can set `hot_load_transition_type` to `ASYNC` or `SYNC` in the SDK provisioning config or the cookbook rollout deployment config. Leave it unset to keep the recommended `ASYNC` default; set `SYNC` when a rollout must not span a weight transition. For the tradeoffs and KV-cache behavior, see [Async transition (recommended, default for RL)](/docs/fine-tuning/rl-rollout-debugging#async-transition-recommended-default-for-rl).

## Key APIs

| API                                                                             | Purpose                                                                                                                                       |
| ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| [`FiretitanServiceClient`](/docs/fine-tuning/training-api/reference/service-client)  | Recommended direct SDK entry point. Creates or reattaches trainers/deployments and returns training, reference, and sampling clients.         |
| [`FiretitanTrainingClient`](/docs/fine-tuning/training-api/reference/service-client) | Tinker-compatible training client: `forward_backward_custom`, `optim_step`, `save_weights_for_sampler`, `save_state`, and load methods.       |
| [`DeploymentSampler`](/docs/fine-tuning/training-api/reference/deployment-sampler)   | FireTitan-native sampler for tokenized rollout/evaluation from SDK-managed deployments.                                                       |
| [`FireworksClient`](/docs/fine-tuning/training-api/reference/fireworks-client)       | Standalone checkpoint operations such as listing checkpoints or promoting a model without a live training instance.                           |
| [`TrainerJobManager`](/docs/fine-tuning/training-api/reference/trainer-job-manager)  | Legacy/compatibility lifecycle manager. Documented for existing SDK users and advanced debugging; not the recommended user-facing path.       |
| [`DeploymentManager`](/docs/fine-tuning/training-api/reference/deployment-manager)   | Legacy/compatibility deployment manager. Documented for existing SDK users and advanced debugging; normal code uses `FiretitanServiceClient`. |

## Renderers

Chat-template formatting, stop-token handling, and loss-weight masking for SFT/DPO datasets are handled by **renderers** — pluggable per-model classes that turn raw conversations into the trainer's `Datum` shape. Most users never touch a renderer directly; cookbook recipes pick the right one for the `base_model` you set. If you need to author a new one or debug parity against HuggingFace, use the canonical training skill's [renderer implementation reference](https://github.com/fw-ai/cookbook/blob/main/skills/fireworks-training/references/renderer.md) and [verification reference](https://github.com/fw-ai/cookbook/blob/main/skills/fireworks-training/references/renderer-verification.md).

## Comparing Training API pricing vs DIY bare metal

When comparing a managed training platform with a self-managed bare-metal stack,
optimize for **cost per successful iteration**, not just headline `$ / GPU-hour`.

### What to compare

* **Time to first deployed model**: include environment setup, training orchestration, checkpoint handoff, and serving integration.
* **Iteration cycle time** (`train -> eval -> deploy -> repeat`): include all retrain/redeploy plumbing, not just GPU runtime.
* **Infra engineering overhead**: include one-time setup and recurring maintenance for containers, runtimes, deployment workflows, and compatibility fixes.
* **Effective `$ / GPU-hour` at real utilization**: include idle capacity, reservation constraints, and burst/overflow behavior.
* **Train/serve parity risk**: account for potential quality drift when training and inference runtimes diverge.
* **Parallel experiment capacity**: compare fixed-reservation throughput against elastic capacity for sweeps and multi-seed runs.

### Useful formulas

```text theme={null}
iterations_per_month = available_working_days / cycle_time_days
effective_cost_per_gpu_hour = total_monthly_spend / gpu_hours_consumed
multi_turn_success ~= (single_turn_success)^turn_count
```

### Keep assumptions explicit

Document assumptions so readers can adjust them for their own workload:

* team size and fully-loaded engineering cost
* average cycle duration in each setup
* expected utilization and burst profile
* average turn count for production agent workflows
* required concurrent experiment count

## FAQ

### Why is my training run "doing nothing" even though code executed?

Usually because `.result()` was not called on futures, so failures were never surfaced.

### What's the difference between base and delta checkpoints, and when should I use each?

Let the SDK select automatically. LoRA snapshots contain the full adapter; full-parameter delta snapshots can accelerate synchronization but are not promotable. See [Saving and Loading](/docs/fine-tuning/training-api/saving-and-loading#sampler-checkpoints).

### Do I need to manage distributed training infra?

No. You implement training logic while Fireworks manages GPU provisioning and distributed infrastructure.

### Should I start with a Cookbook recipe or the Python SDK?

Start with a Cookbook recipe for most SFT, DPO, or GRPO adaptations. Use the Python SDK directly when you need custom loop semantics and full control.

### Can I evaluate serving behavior during training?

Yes. On serverless, save a snapshot and sample from it in the same session. On dedicated infrastructure, sync a snapshot to the SDK-managed deployment sampler and evaluate there.

### How should I compare Training API pricing vs a DIY bare-metal setup?

Use the framework in [Comparing Training API pricing vs DIY bare metal](#comparing-training-api-pricing-vs-diy-bare-metal). Focus on total iteration economics (cycle time, engineering overhead, utilization-adjusted cost, and quality-parity risk), then plug in your own assumptions.

### How can I compare rollout cost vs other providers?

See the [Price comparison vs Tinker](/docs/fine-tuning/multi-turn-cost-comparison) calculator to estimate scenario-based costs on Fireworks Dedicated against Tinker's per-token pricing.

## Next steps

* [Dedicated quickstart](/docs/fine-tuning/training-api/quickstart) — run a minimal dedicated custom loop
* [Choose infrastructure](/docs/fine-tuning/training-api/choose-infrastructure) — compare serverless and dedicated training
* [Serverless Training](/docs/fine-tuning/training-api/serverless) — shared pooled LoRA training
* [Dedicated Training](/docs/fine-tuning/training-api/dedicated) — provisioned trainer and deployment lifecycle
* [Dedicated Training and Sampling](/docs/fine-tuning/training-api/training-and-sampling) — deployment-sampling lifecycle
* [Loss Functions](/docs/fine-tuning/training-api/loss-functions) — built-in and custom loss functions
* [Vision Inputs](/docs/fine-tuning/training-api/vision-inputs) — fine-tune vision-language models with image and text data
* [The Cookbook](/docs/fine-tuning/training-api/cookbook/overview) — ready-to-run recipes for SFT, DPO, ORPO, GRPO/IGPO, and async RL (experimental)
