Skip to content

SDXL & SD1 LoRA training

Train a Stable Diffusion LoRA on your own image dataset using AI Toolkit. This page covers the two classic SD ecosystems:

ecosystemOutput LoRA usable withBuzz / epochNative resolution
sdxlSDXL image generation501024²
sd1SD1 image generation50512²

Both are the cheapest training ecosystems on the platform — good first pick when iterating on dataset choice or hyperparameters before stepping up to a more expensive model family. SDXL is the better default for new fine-tunes; SD1 is mostly useful when you specifically need a SD 1.5 LoRA (e.g. to deploy onto an existing SD 1.5 product).

The request shape

Every training request is a single training step with an engine and ecosystem selector:

json
{
  "$type": "training",
  "input": {
    "engine":    "ai-toolkit",
    "ecosystem": "sdxl"          // sdxl | sd1
  }
}

The input shape is shared with the other AI Toolkit ecosystems — see Common parameters below. The fields documented here are the SD-family-specific ones (model, minSnrGamma, triggerWord, default text-encoder behavior).

Long-running step

Training takes minutes to hours depending on dataset size and epoch count. Always submit with wait=0 and follow up with polling or a webhook — see Results & webhooks. The <RecipeRun> widgets below preview cost via whatif=true so you can see the price without kicking off an actual training run.

Prerequisites

  • A Civitai orchestration token (Quick start → Prerequisites)
  • A training-data zip uploaded to a Civitai-reachable URL. Three accepted forms:
    • A signed https://civitai-delivery-worker-prod.*.r2.cloudflarestorage.com/... URL
    • A Civitai R2 AIR (e.g. urn:air:other:other:civitai-r2:civitai-delivery-worker-prod@training-images/.../...zip)
    • Any HTTPS URL that returns the zip without auth
  • An accurate count of images in the zip — used to compute numberOfRepeats defaults and batch sizing

SDXL

Stable Diffusion XL trains at 1024² and produces a LoRA usable with any SDXL checkpoint. The base checkpoint defaults to urn:air:sdxl:checkpoint:civitai:101055@128078 (Juggernaut XL); override model to train on top of a different SDXL checkpoint.

http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "tags": ["training"],
  "steps": [{
    "$type": "training",
    "priority": "normal",
    "retries": 2,
    "input": {
      "engine": "ai-toolkit",
      "ecosystem": "sdxl",
      "model": "urn:air:sdxl:checkpoint:civitai:101055@128078",
      "epochs": 10,
      "numberOfRepeats": 14,
      "lr": 0.0005,
      "textEncoderLr": 5e-5,
      "trainTextEncoder": true,
      "lrScheduler": "cosine",
      "optimizerType": "adafactor",
      "networkDim": 32,
      "networkAlpha": 32,
      "noiseOffset": 0.1,
      "minSnrGamma": 5,
      "triggerWord": "cat",
      "trainingData": {
        "type": "zip",
        "sourceUrl": "urn:air:other:other:civitai-r2:civitai-delivery-worker-prod@training-images/6/2783465TrainingData.koBd.zip",
        "count": 15
      },
      "samples": {
        "prompts": [
          "catz no humans, cat, whiskers, animal focus, looking at viewer, animal, solo, yellow eyes",
          "catz no humans, candle, pokemon (creature), blurry, animal focus, solo, food, bird, standing",
          "catz no humans, food, noodles, bowl, cat, green eyes, tongue, food focus, ramen, chopsticks"
        ]
      }
    }
  }]
}
POST/v2/consumer/workflows
Set your Civitai API token via the Token button in the navbar to enable Try It.
Request body — edit to customize (e.g. swap the image URL or prompt)
Valid JSON

SDXL-specific fields:

FieldDefaultRange / valuesNotes
modelurn:air:sdxl:checkpoint:civitai:101055@128078Any SDXL checkpoint AIRThe base checkpoint your LoRA is trained on top of.
minSnrGamma5020Min-SNR-γ stabilization. 5 is a good default; lower values can speed up convergence on simple subjects.
triggerWord(none)stringOptional prompt token that activates the trained LoRA. Recommended for character / style LoRAs.
trainTextEncodertrueboolSDXL benefits noticeably from text-encoder training. Disable to halve memory cost at the price of prompt-following quality.
textEncoderLr5e-501Only used when trainTextEncoder: true.
optimizerTypeadafactorsee enumadafactor is the SDXL house default; adamw8bit works too if you have memory headroom.

SD1

Stable Diffusion 1.5 trains at 512² and produces a LoRA usable with any SD1.5 checkpoint. Base checkpoint defaults to urn:air:sd1:checkpoint:civitai:127227@139180. Same shape as SDXL with two differences: optimizerType defaults to adamw8bit (not adafactor), and noiseOffset defaults to 0 (not 0.1).

http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "tags": ["training"],
  "steps": [{
    "$type": "training",
    "input": {
      "engine": "ai-toolkit",
      "ecosystem": "sd1",
      "model": "urn:air:sd1:checkpoint:civitai:127227@139180",
      "epochs": 100,
      "lr": 0.0005,
      "textEncoderLr": 5e-5,
      "trainTextEncoder": true,
      "lrScheduler": "cosine",
      "optimizerType": "adamw8bit",
      "networkDim": 32,
      "networkAlpha": 16,
      "noiseOffset": 0.1,
      "minSnrGamma": 5,
      "trainingData": {
        "type": "zip",
        "sourceUrl": "urn:air:other:other:civitai-r2:civitai-delivery-worker-prod@training-images/6/2707938TrainingData.Ac22.zip",
        "count": 8
      },
      "samples": {
        "prompts": [
          "no humans, cat, whiskers, animal focus, looking at viewer, animal, solo, yellow eyes",
          "no humans, food, tiger, cake, animal focus, food focus, whiskers, black background",
          "no humans, fruit, food, bug, black background, wings, food focus, orange (fruit), antennae"
        ]
      }
    }
  }]
}
POST/v2/consumer/workflows
Set your Civitai API token via the Token button in the navbar to enable Try It.
Request body — edit to customize (e.g. swap the image URL or prompt)
Valid JSON

SD1-specific fields are a subset of the SDXL list — same model / minSnrGamma / triggerWord / trainTextEncoder / textEncoderLr, with these defaults:

FieldSD1 defaultSDXL default
optimizerTypeadamw8bitadafactor
noiseOffset00.1
numberOfRepeats (auto)ceil(400 / count)ceil(200 / count)

Common parameters

These apply to every AI Toolkit training input regardless of ecosystem. Defaults shown are the post-ApplyDefaults values for SDXL; some ecosystems override individual defaults (the SD1 / SDXL differences above are the main examples).

FieldRequiredDefaultNotes
engineAlways ai-toolkit for these recipes.
ecosystemsdxl or sd1 for this page.
epochs5120. One pass through the dataset = one epoch. Billed per epoch (see Cost).
numberOfRepeatsauto15000. Per-image repeats inside one epoch. Auto-computed from dataset size when omitted.
lr0.000101. UNet learning rate. 0.0005 is typical for character/style LoRAs on SDXL.
textEncoderLrOnly used when trainTextEncoder: true. SDXL/SD1 default to 5e-5.
trainTextEncodertrue (SDXL/SD1)Train CLIP alongside the diffuser.
lrSchedulercosineconstant, constant_with_warmup, cosine, linear, step.
optimizerTypeadafactor (SDXL) / adamw8bit (SD1)adamw, adamw8bit, adam8bit, lion, lion8bit, adafactor, adagrad, prodigy, prodigy8bit, automagic.
networkDim321256. LoRA rank. Higher = more capacity, larger LoRA file.
networkAlphamatches networkDim1256. Scales the effective learning rate via alpha / dim.
noiseOffset0.1 (SDXL) / 0 (SD1)01. Adds noise during training to improve dark/bright sample handling.
flipAugmentationfalseRandom horizontal flips. Useful for symmetric subjects.
shuffleTokensfalseRandomize caption-tag order.
keepTokens0010. When shuffleTokens: true, keep the first N tokens fixed.
triggerWord(none)Activation token recommended for character/style LoRAs.
trainingData.typezip (only currently supported type).
trainingData.sourceUrlSigned HTTPS URL or Civitai R2 AIR.
trainingData.countNumber of images in the zip.
samples.prompts[][]Up to a handful of preview prompts rendered after each epoch with the trained LoRA at strength 1.0. Empty entries are skipped.
samples.negativePrompt(none)Applied to all sample prompts.

Reading the result

Submitting with wait=0 returns immediately with status: processing. Poll GetWorkflow (or use a webhook — see Results & webhooks) until the step settles. A successful step produces one epochs[] entry per epoch; each contains the trained LoRA blob and any sample images:

json
{
  "status": "succeeded",
  "steps": [{
    "name": "0",
    "$type": "training",
    "status": "succeeded",
    "output": {
      "moderationStatus": "Approved",
      "epochs": [
        {
          "epochNumber": 1,
          "model": { "id": "blob_...", "url": "https://.../epoch_1.safetensors" },
          "samples": [
            { "id": "blob_...", "url": "https://.../sample_0.jpeg" },
            { "id": "blob_...", "url": "https://.../sample_1.jpeg" }
          ]
        },
        { "epochNumber": 2, "model": { "...": "..." }, "samples": [] }
      ]
    }
  }]
}

The blob URLs are signed and expire — refetch the workflow or call GetBlob for a fresh URL when downloading the trained LoRA.

moderationStatus reflects safety review of the dataset: Approved is the green-light case. Rejected means the run was halted because the dataset failed moderation.

Runtime

Training is highly variable and depends on epochs × numberOfRepeats × count. Always use wait=0.

EcosystemPer-epoch wall time (15 imgs, default settings)Typical full run
sdxl~30–60 s5–15 min for 10 epochs
sd1~10–25 s3–10 min for 100 epochs (SD1 is much faster per step)

Queue time on busy days can dominate — use the workflow's events[] to see when the step actually started.

Cost

Billed in Buzz (1 Buzz ≈ 1/6 second of GPU). Both SDXL and SD1 are flat-rate per epoch:

total = costPerEpoch × epochs
costPerEpoch = 50 (sdxl), 50 (sd1)

Sample-prompt rendering is billed separately at standard SDXL / SD1 image-generation rates. Use whatif=true (the default for the Preview cost button on the <RecipeRun> widgets above) to see the exact pre-flight charge before committing.

ConfigurationBuzz
SDXL, epochs: 10500 + samples
SDXL, epochs: 5250 + samples
SD1, epochs: 1005000 + samples
SD1, epochs: 201000 + samples

Troubleshooting

SymptomLikely causeFix
400 with "epochs out of range"epochs outside 120The hard cap is 20. For very-many-epoch SD1 runs (rare), submit multiple training workflows and chain them.
400 with "model not found"model URN points at a checkpoint that isn't the right ecosystem (e.g. an SD1 model on ecosystem: "sdxl")Use a urn:air:sdxl:checkpoint:... AIR for SDXL; urn:air:sd1:checkpoint:... for SD1.
400 with "trainingData.sourceUrl not reachable"Signed URL expired, or zip behind authR2 signed URLs expire — regenerate. Prefer Civitai R2 AIRs for stable references.
400 with "count mismatch"trainingData.count doesn't match the actual image count in the zipInspect the zip contents and update count.
Step failed, output moderationStatus: "Rejected"Dataset failed automated content moderationReplace flagged images and resubmit. Don't retry the same dataset.
Trained LoRA looks under-trainedToo few steps for the datasetRaise epochs or numberOfRepeats; or increase lr.
Trained LoRA overfits / memorizesToo many steps, dim too high, or alpha = dim with high lrLower epochs, drop networkDim to 16–24, or set networkAlpha to half of networkDim.

Civitai Developer Documentation