Lora dataset prep
Prepare image datasets for LoRA training (Ostris AI Toolkit / Z-Image Turbo): quality checks, captioning (templates / Claude Vision / Florence-2), 20+ validation rules. Agent Skill for Claude Code & Cursor + standalone CLI.
npx -y skills add afloy011-spec/lora-dataset-prepAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when preparing image datasets for LoRA training in Ostris AI Toolkit / Z-Image Turbo. Covers character LoRA image selection (15-30 imgs, shot variety, 1024px), captioning rules (natural language, media type, trigger token), folder structure, .txt sidecars, validation, VLM auto-captioning, and resize. Use when the user wants to organize raw photos, write captions, choose a trigger word, or validate a character dataset before training.
SKILL.md
9.9 KB, as published. Nobody here has run it
LoRA Dataset Preparation
Skill for preparing image datasets for Ostris AI Toolkit / Z-Image Turbo LoRA training.
Primary target: character LoRA. Also supports style, object, clothing, environment.
Two files in this skill folder:
prepare_dataset.py— the tool (dry-run by default,--executeto apply)reference.md— full captioning guide: character LoRA formula, include/omit tables, good/bad examples, per-type caption strategies, complete validation list. Read it whenever you write or review captions.
Quick Start
# Interactive mode — asks all questions:
python prepare_dataset.py
# One-liner dry-run (shows plan, does nothing):
python prepare_dataset.py --source ./raw_photos --output ./my_dataset \
--type character --trigger mychar01
# Execute with template captions:
python prepare_dataset.py --source ./raw_photos --output ./my_dataset \
--type character --trigger mychar01 --captions template --copy --execute
# Execute with VLM auto-captioning (requires: pip install anthropic):
python prepare_dataset.py --source ./raw_photos --output ./my_dataset \
--type character --trigger mychar01 --captions vlm --execute
# With resize and repeats:
python prepare_dataset.py --source ./raw_photos --output ./my_dataset \
--type character --trigger mychar01 --resize 1024 --repeats 10 --execute
# Validate an existing dataset after editing captions (read-only):
python prepare_dataset.py --validate-only --output ./my_dataset --trigger mychar01
What the Script Does
- Scans the source folder for
.jpg,.jpeg,.pngimages (WebP optional with--convert-webp; subfolders with--recursive) - Runs image quality checks: dimensions, blur detection, EXIF-rotation flags, duplicate detection
- Copies (or moves) images into
dataset/train/with sequential zero-padded names - Optionally resizes images to target resolution (
--resize) - Writes
.txtsidecar caption files (template, minimal, VLM, or local auto-captioned) - Creates
dataset/README.mdanddataset/metadata.json - Validates the result (missing captions, empty captions, unsafe filenames, trigger presence, image quality)
Output Structure
my_dataset/
├── train/ (or N_trigger/ with --repeats N)
│ ├── 01.png
│ ├── 01.txt
│ ├── 02.png
│ ├── 02.txt
│ └── ...
├── raw/ ← originals (backup)
├── README.md
└── metadata.json
01,02for datasets under 100 images001,002for datasets 100+ images- No spaces, non-ASCII characters, emojis, or special chars in any filename
Options Reference
| Flag | Default | Notes |
|---|---|---|
--source | (ask) | Folder with raw images |
--output | (ask) | Output dataset folder (created) |
--type | (ask) | character / style / object / clothing / environment |
--trigger | (ask) | Unique trigger token, e.g. mychar01 |
--captions | template | minimal / template / vlm / local |
--copy | yes | Copy files, keep originals |
--move | no | Move files, delete originals |
--no-backup | off | Skip raw/ backup |
--recursive | off | Scan subfolders too (hidden folders skipped; backup names are flattened) |
--convert-webp | off | Convert .webp to .png (needs Pillow) |
--resize PX | off | Resize shortest side to PX (e.g. 1024); bakes EXIF rotation into pixels. Needs Pillow |
--repeats N | off | Create N_trigger/ folder instead of train/ (kohya/Ostris repeats) |
--vlm-model | claude-sonnet-4-6 | Model for VLM captioning |
--local-model | Salesforce/blip-image-captioning-large | Model for local captioning (use microsoft/Florence-2-large for better quality) |
--no-quality-check | off | Skip image quality checks |
--blur-threshold N | 100 | Blur heuristic sensitivity; lower it on false positives, 0 disables |
--validate-only | off | Validate an existing dataset, read-only. Use with --output and --trigger (trigger auto-read from metadata.json if omitted) |
--execute | off | Actually run (default is dry-run) |
Caption Modes
| Mode | What it writes | When to use |
|---|---|---|
template | Varied templates with [BRACKET] placeholders (default) | Start here for any LoRA — fill in placeholders per image |
minimal | mychar01, portrait photo | Bare minimum; fill captions entirely by hand |
vlm | Auto-generated by Claude Vision API | Best quality — real descriptions of each image. Requires pip install anthropic and ANTHROPIC_API_KEY env var |
local | Auto-generated by a local model (Florence-2 or BLIP) | Offline captioning. Raw BLIP output must be rewritten by hand — see reference.md |
Template mode: always fill in [BRACKET] placeholders before training — they are
not valid training captions. The script cannot see the images in this mode; it only
creates structured templates.
VLM mode: captions are tailored to the LoRA type and follow the captioning rules
automatically. If the API fails for an image, the script falls back to a template
caption with a # VLM_FAILED marker; validation flags these.
Local mode: requires pip install transformers torch. The default BLIP model
emits generic captions that violate the caption formula — read the warning section
in reference.md before relying on it. Prefer --local-model microsoft/Florence-2-large.
Image Quality Checks
Runs automatically before processing (disable with --no-quality-check):
| Check | What it detects | Threshold |
|---|---|---|
| Dimensions | Images smaller than 512px on any side | min 512px |
| EXIF rotation | Phone photos stored rotated with only an EXIF flag (train sideways as-is; --resize bakes the rotation in) | orientation ≠ 1 |
| Blur | Blurry/out-of-focus images via edge variance | score < 100 (tune: --blur-threshold) |
| Exact duplicates | Identical files by SHA-256 hash | exact match |
| Near-duplicates | Visually similar images via perceptual hash (dHash) | hamming distance <= 10 |
Blur detection is a heuristic — smooth studio portraits can false-positive.
Treat warnings as "review this image", and tune or disable via --blur-threshold.
Trigger Token Rules
- Use a meaningless made-up token — invented word with no semantic collision in the model
- Recommended pattern:
[letters][numbers]— e.g.mychar01,zvqmark,zbxobj - Always lowercase, no spaces, no special characters
- First word in every caption, exactly once per caption
- Use the same token in every sample prompt in your training config
Good: asxgirl, zvqmark, zbxshoe, envtown, stlmono
Bad: woman, style, person, the, beautiful (real words — model won't isolate the concept)
Captioning Cheat Sheet (Character LoRA)
Describe what you do NOT want the LoRA to learn. Everything not in the caption gets bound to the trigger token.
FORMULA:
[trigger], [media type], [shot type] of a man/woman, [clothing], [pose/action],
[expression], [background/setting], [lighting]
INCLUDE: clothing, pose, expression, angle, background, lighting, media type
OMIT: face, eyes, skin, quality tags, repeated adjectives
LENGTH: 15–35 words
LANGUAGE: natural language, not tags
TRIGGER: first word, once
Full guide with include/omit tables, good/bad examples, typical mistakes, and
strategies for style/object/clothing/environment LoRA: reference.md.
Validation
After execution (or standalone via --validate-only) the script checks: image↔caption
pairing, trigger presence and position, caption length (15–35 words target), unfilled
[BRACKET] placeholders, filler phrases, multiple subjects, attribute-sticking
(repeated phrases in ≥50% of captions), unsafe filenames, image size, blur, exact and
near-duplicates, VLM_FAILED markers. Full list in reference.md.
Supported Formats
| Format | Support |
|---|---|
.jpg, .jpeg, .png | native |
.webp | opt-in via --convert-webp (needs Pillow) |
| Other | skipped, warned |
Avoid WebP in training datasets — some training pipelines cannot read it.
Optional Dependencies
| Package | What it enables |
|---|---|
Pillow | WebP conversion, image resize, quality checks (dimensions, blur) |
anthropic | VLM auto-captioning via Claude Vision API (--captions vlm) |
transformers + torch | Local auto-captioning (--captions local, Florence-2 / BLIP) |
Install: pip install Pillow anthropic (plus pip install transformers torch for local mode)
Dataset Size Guidance (Z-Image Turbo)
| LoRA type | Min images | Recommended | Notes |
|---|---|---|---|
| Character | 15 | 15–30 (~20 optimal) | Varied angle/expression/lighting/background; avoid duplicates |
| Object | 20 | 30–50 | Multi-angle + detail close-ups |
| Clothing | 10 | 20–40 | On-body + flat lay + details |
| Style | 30 | 50–100 | Diverse subjects in the style |
| Environment | 30 | 50–100 | Wide + detail, varied lighting |
After Dataset Prep
- Review captions — if VLM/local mode, check accuracy. If template mode, fill in
[BRACKET]placeholders - Run validation —
python prepare_dataset.py --validate-only --output ./my_dataset(read-only, never touches files) - Create training config — YAML for Ostris AI Toolkit with rank/steps/LR for your hardware
- Set sample prompts using the trigger token — add 3–5 fixed-seed prompts to the config
- Upload dataset to your training machine (local GPU or a cloud pod) and launch