initial setup: ComfyUI + kohya_ss scripts, LoRA config, workflows
This commit is contained in:
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# models - too large for git
|
||||
models/
|
||||
*.safetensors
|
||||
*.ckpt
|
||||
*.pt
|
||||
*.pth
|
||||
*.bin
|
||||
|
||||
# generated outputs
|
||||
output/
|
||||
outputs/
|
||||
|
||||
# venvs / installs
|
||||
comfyui/venv/
|
||||
comfyui/__pycache__/
|
||||
kohya_ss/venv/
|
||||
kohya_ss/__pycache__/
|
||||
kohya_ss/logs/
|
||||
|
||||
# training data (images)
|
||||
training_data/
|
||||
|
||||
# ComfyUI user data / cache
|
||||
comfyui/user/
|
||||
comfyui/temp/
|
||||
comfyui/custom_nodes/**/node_modules/
|
||||
|
||||
# misc
|
||||
*.log
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
72
README.md
Normal file
72
README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# animepics
|
||||
|
||||
Anime image generation + LoRA training setup.
|
||||
|
||||
## Stack
|
||||
|
||||
- **ComfyUI** — image generation UI
|
||||
- **NoobAI-XL** — base anime model (SDXL-based, SFW+NSFW)
|
||||
- **kohya_ss** — LoRA training
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.10+ installed and in PATH
|
||||
- Git installed
|
||||
- NVIDIA GPU with CUDA (4070 recommended)
|
||||
- ~20GB free disk space for models
|
||||
|
||||
## Setup
|
||||
|
||||
Run once to install everything:
|
||||
|
||||
```powershell
|
||||
.\setup.ps1
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Clone ComfyUI and install dependencies
|
||||
2. Clone kohya_ss and install dependencies
|
||||
3. Install ComfyUI custom nodes (AnimateDiff, ControlNet, etc.)
|
||||
4. Download the NoobAI-XL base model + VAE
|
||||
|
||||
## Launch
|
||||
|
||||
```powershell
|
||||
# Start image generation UI (opens browser at localhost:8188)
|
||||
.\launch_comfyui.ps1
|
||||
|
||||
# Start LoRA training UI (opens browser at localhost:7860)
|
||||
.\launch_kohya.ps1
|
||||
```
|
||||
|
||||
## LoRA Training
|
||||
|
||||
1. Put your training images in `training_data/<your_lora_name>/img/10_<trigger_word>/`
|
||||
2. Copy `training/example_lora_config.toml` and edit it
|
||||
3. Launch kohya and use the GUI, or run `.\train_lora.ps1 <config_file>`
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
animepics/
|
||||
├── comfyui/ # ComfyUI install (gitignored venv)
|
||||
├── kohya_ss/ # kohya_ss install (gitignored venv)
|
||||
├── models/ # shared model storage (gitignored)
|
||||
│ ├── checkpoints/ # base models (.safetensors)
|
||||
│ ├── loras/ # trained LoRAs
|
||||
│ ├── vae/ # VAE models
|
||||
│ ├── embeddings/ # textual inversions
|
||||
│ └── controlnet/ # ControlNet models
|
||||
├── training_data/ # LoRA training images (gitignored)
|
||||
├── output/ # generated images (gitignored)
|
||||
├── training/ # LoRA training configs
|
||||
└── workflows/ # ComfyUI workflow JSON files
|
||||
```
|
||||
|
||||
## Model Downloads
|
||||
|
||||
Base model (NoobAI-XL Vpred):
|
||||
- https://civitai.com/models/833294
|
||||
|
||||
Good NSFW VAE:
|
||||
- Already baked into NoobAI, but sdxl_vae.safetensors from stabilityai works too
|
||||
11
config/extra_model_paths.yaml
Normal file
11
config/extra_model_paths.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
# ComfyUI extra model paths — points to shared models/ directory
|
||||
# so both ComfyUI and kohya_ss use the same model storage
|
||||
|
||||
animepics:
|
||||
base_path: E:/animepics/models
|
||||
checkpoints: checkpoints
|
||||
loras: loras
|
||||
vae: vae
|
||||
embeddings: embeddings
|
||||
controlnet: controlnet
|
||||
upscale_models: upscale_models
|
||||
12
launch_comfyui.ps1
Normal file
12
launch_comfyui.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# launch_comfyui.ps1 — start ComfyUI
|
||||
|
||||
$root = $PSScriptRoot
|
||||
Set-Location "$root/comfyui"
|
||||
|
||||
.\venv\Scripts\Activate.ps1
|
||||
python main.py `
|
||||
--listen 127.0.0.1 `
|
||||
--port 8188 `
|
||||
--extra-model-paths-config "$root/comfyui/extra_model_paths.yaml" `
|
||||
--preview-method auto
|
||||
8
launch_kohya.ps1
Normal file
8
launch_kohya.ps1
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# launch_kohya.ps1 — start kohya_ss GUI
|
||||
|
||||
$root = $PSScriptRoot
|
||||
Set-Location "$root/kohya_ss"
|
||||
|
||||
.\venv\Scripts\Activate.ps1
|
||||
python kohya_gui.py --listen 127.0.0.1 --server_port 7860
|
||||
88
setup.ps1
Normal file
88
setup.ps1
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# setup.ps1 — one-time install of ComfyUI + kohya_ss
|
||||
|
||||
$root = $PSScriptRoot
|
||||
Set-Location $root
|
||||
|
||||
Write-Host "==> setting up animepics environment" -ForegroundColor Cyan
|
||||
|
||||
# create model dirs
|
||||
$model_dirs = @(
|
||||
"models/checkpoints",
|
||||
"models/loras",
|
||||
"models/vae",
|
||||
"models/embeddings",
|
||||
"models/controlnet",
|
||||
"models/upscale_models",
|
||||
"training_data",
|
||||
"output"
|
||||
)
|
||||
foreach ($dir in $model_dirs) {
|
||||
New-Item -ItemType Directory -Force -Path "$root/$dir" | Out-Null
|
||||
}
|
||||
Write-Host " created model directories" -ForegroundColor Green
|
||||
|
||||
# --- ComfyUI ---
|
||||
Write-Host "`n==> installing ComfyUI" -ForegroundColor Cyan
|
||||
if (-not (Test-Path "$root/comfyui")) {
|
||||
git clone https://github.com/comfyanonymous/ComfyUI.git "$root/comfyui"
|
||||
} else {
|
||||
Write-Host " comfyui already cloned, pulling latest" -ForegroundColor Yellow
|
||||
git -C "$root/comfyui" pull
|
||||
}
|
||||
|
||||
Push-Location "$root/comfyui"
|
||||
python -m venv venv
|
||||
.\venv\Scripts\Activate.ps1
|
||||
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
|
||||
pip install -r requirements.txt
|
||||
deactivate
|
||||
Pop-Location
|
||||
Write-Host " ComfyUI installed" -ForegroundColor Green
|
||||
|
||||
# ComfyUI custom nodes
|
||||
Write-Host "`n==> installing ComfyUI custom nodes" -ForegroundColor Cyan
|
||||
$custom_nodes = @(
|
||||
@{ name="ComfyUI-Manager"; url="https://github.com/ltdrdata/ComfyUI-Manager.git" },
|
||||
@{ name="ComfyUI_IPAdapter_plus"; url="https://github.com/cubiq/ComfyUI_IPAdapter_plus.git" },
|
||||
@{ name="ComfyUI-Advanced-ControlNet"; url="https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git" },
|
||||
@{ name="was-node-suite-comfyui"; url="https://github.com/WASasquatch/was-node-suite-comfyui.git" }
|
||||
)
|
||||
New-Item -ItemType Directory -Force -Path "$root/comfyui/custom_nodes" | Out-Null
|
||||
foreach ($node in $custom_nodes) {
|
||||
$node_path = "$root/comfyui/custom_nodes/$($node.name)"
|
||||
if (-not (Test-Path $node_path)) {
|
||||
git clone $node.url $node_path
|
||||
Write-Host " cloned $($node.name)" -ForegroundColor Green
|
||||
} else {
|
||||
git -C $node_path pull
|
||||
Write-Host " updated $($node.name)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# copy extra_model_paths config so ComfyUI finds our shared models dir
|
||||
Copy-Item -Force "$root/config/extra_model_paths.yaml" "$root/comfyui/extra_model_paths.yaml"
|
||||
Write-Host " copied extra_model_paths.yaml" -ForegroundColor Green
|
||||
|
||||
# --- kohya_ss ---
|
||||
Write-Host "`n==> installing kohya_ss" -ForegroundColor Cyan
|
||||
if (-not (Test-Path "$root/kohya_ss")) {
|
||||
git clone https://github.com/bmaltais/kohya_ss.git "$root/kohya_ss"
|
||||
} else {
|
||||
Write-Host " kohya_ss already cloned, pulling latest" -ForegroundColor Yellow
|
||||
git -C "$root/kohya_ss" pull
|
||||
}
|
||||
|
||||
Push-Location "$root/kohya_ss"
|
||||
python -m venv venv
|
||||
.\venv\Scripts\Activate.ps1
|
||||
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
|
||||
pip install -r requirements.txt
|
||||
deactivate
|
||||
Pop-Location
|
||||
Write-Host " kohya_ss installed" -ForegroundColor Green
|
||||
|
||||
Write-Host "`n==> setup complete!" -ForegroundColor Cyan
|
||||
Write-Host " next: download your base model into models/checkpoints/" -ForegroundColor White
|
||||
Write-Host " recommended: NoobAI-XL from https://civitai.com/models/833294" -ForegroundColor White
|
||||
Write-Host "`n then run: .\launch_comfyui.ps1" -ForegroundColor White
|
||||
23
train_lora.ps1
Normal file
23
train_lora.ps1
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# train_lora.ps1 — run LoRA training from a config file
|
||||
# usage: .\train_lora.ps1 training/my_lora.toml
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$config_file
|
||||
)
|
||||
|
||||
$root = $PSScriptRoot
|
||||
|
||||
if (-not (Test-Path "$root/$config_file")) {
|
||||
Write-Host "config file not found: $config_file" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Set-Location "$root/kohya_ss"
|
||||
.\venv\Scripts\Activate.ps1
|
||||
|
||||
accelerate launch `
|
||||
--num_cpu_threads_per_process 2 `
|
||||
train_network.py `
|
||||
--config_file "$root/$config_file"
|
||||
54
training/example_lora_config.toml
Normal file
54
training/example_lora_config.toml
Normal file
@@ -0,0 +1,54 @@
|
||||
# example LoRA training config for kohya_ss (SDXL)
|
||||
# copy this, rename it, and edit the paths/settings for your lora
|
||||
# then train with: .\train_lora.ps1 training/my_lora.toml
|
||||
|
||||
[model_arguments]
|
||||
pretrained_model_name_or_path = "E:/animepics/models/checkpoints/noobai-xl.safetensors"
|
||||
# set to true for vpred models (NoobAI-XL uses vpred)
|
||||
v_parameterization = true
|
||||
zero_terminal_snr = true
|
||||
|
||||
[saving_arguments]
|
||||
save_every_n_epochs = 1
|
||||
save_model_as = "safetensors"
|
||||
output_dir = "E:/animepics/models/loras"
|
||||
output_name = "my_lora_v1"
|
||||
|
||||
[dataset_arguments]
|
||||
# dataset dir structure: training_data/<lora_name>/img/<repeats>_<trigger>/
|
||||
train_data_dir = "E:/animepics/training_data/my_lora/img"
|
||||
resolution = "1024,1024"
|
||||
enable_bucket = true
|
||||
min_bucket_reso = 512
|
||||
max_bucket_reso = 2048
|
||||
bucket_reso_steps = 64
|
||||
caption_extension = ".txt"
|
||||
shuffle_caption = true
|
||||
keep_tokens = 1
|
||||
|
||||
[training_arguments]
|
||||
output_dir = "E:/animepics/models/loras"
|
||||
logging_dir = "E:/animepics/kohya_ss/logs"
|
||||
max_train_epochs = 10
|
||||
train_batch_size = 1
|
||||
gradient_accumulation_steps = 1
|
||||
gradient_checkpointing = true
|
||||
mixed_precision = "bf16"
|
||||
save_precision = "bf16"
|
||||
seed = 42
|
||||
max_token_length = 225
|
||||
xformers = true
|
||||
# learning rates — good defaults for NoobAI-XL
|
||||
learning_rate = 0.0001
|
||||
unet_lr = 0.0001
|
||||
text_encoder_lr = 0.00005
|
||||
lr_scheduler = "cosine_with_restarts"
|
||||
lr_warmup_steps = 100
|
||||
optimizer_type = "AdamW8bit"
|
||||
|
||||
[network_arguments]
|
||||
network_module = "networks.lora"
|
||||
network_dim = 32 # rank — higher = more capacity, 16-64 is typical
|
||||
network_alpha = 16 # usually half of dim
|
||||
# optional: train only specific layers
|
||||
# network_args = ["conv_dim=16", "conv_alpha=8"]
|
||||
120
workflows/anime_txt2img.json
Normal file
120
workflows/anime_txt2img.json
Normal file
@@ -0,0 +1,120 @@
|
||||
{
|
||||
"last_node_id": 9,
|
||||
"last_link_id": 9,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 4,
|
||||
"type": "CheckpointLoaderSimple",
|
||||
"pos": [26, 474],
|
||||
"size": [315, 98],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{"name": "MODEL", "type": "MODEL", "links": [1], "slot_index": 0},
|
||||
{"name": "CLIP", "type": "CLIP", "links": [3, 5], "slot_index": 1},
|
||||
{"name": "VAE", "type": "VAE", "links": [8], "slot_index": 2}
|
||||
],
|
||||
"properties": {"Node name for S&R": "CheckpointLoaderSimple"},
|
||||
"widgets_values": ["noobai-xl.safetensors"]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [415, 186],
|
||||
"size": [422, 164],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [{"name": "clip", "type": "CLIP", "link": 3}],
|
||||
"outputs": [{"name": "CONDITIONING", "type": "CONDITIONING", "links": [4], "slot_index": 0}],
|
||||
"properties": {"Node name for S&R": "CLIPTextEncode"},
|
||||
"widgets_values": ["1girl, anime, masterpiece, best quality, highly detailed, beautiful face, solo"]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [415, 400],
|
||||
"size": [422, 164],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [{"name": "clip", "type": "CLIP", "link": 5}],
|
||||
"outputs": [{"name": "CONDITIONING", "type": "CONDITIONING", "links": [6], "slot_index": 0}],
|
||||
"properties": {"Node name for S&R": "CLIPTextEncode"},
|
||||
"widgets_values": ["worst quality, low quality, bad anatomy, extra limbs, poorly drawn face, ugly, watermark, text"]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "EmptyLatentImage",
|
||||
"pos": [473, 609],
|
||||
"size": [315, 106],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [{"name": "LATENT", "type": "LATENT", "links": [2], "slot_index": 0}],
|
||||
"properties": {"Node name for S&R": "EmptyLatentImage"},
|
||||
"widgets_values": [832, 1216, 1]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "KSampler",
|
||||
"pos": [863, 186],
|
||||
"size": [315, 474],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{"name": "model", "type": "MODEL", "link": 1},
|
||||
{"name": "positive", "type": "CONDITIONING", "link": 4},
|
||||
{"name": "negative", "type": "CONDITIONING", "link": 6},
|
||||
{"name": "latent_image", "type": "LATENT", "link": 2}
|
||||
],
|
||||
"outputs": [{"name": "LATENT", "type": "LATENT", "links": [7], "slot_index": 0}],
|
||||
"properties": {"Node name for S&R": "KSampler"},
|
||||
"widgets_values": [42, "fixed", 28, 7, "dpmpp_2m", "karras", 1]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "VAEDecode",
|
||||
"pos": [1209, 186],
|
||||
"size": [210, 46],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{"name": "samples", "type": "LATENT", "link": 7},
|
||||
{"name": "vae", "type": "VAE", "link": 8}
|
||||
],
|
||||
"outputs": [{"name": "IMAGE", "type": "IMAGE", "links": [9], "slot_index": 0}],
|
||||
"properties": {"Node name for S&R": "VAEDecode"}
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "SaveImage",
|
||||
"pos": [1451, 186],
|
||||
"size": [210, 58],
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [{"name": "images", "type": "IMAGE", "link": 9}],
|
||||
"properties": {"Node name for S&R": "SaveImage"},
|
||||
"widgets_values": ["anime"]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[1, 4, 0, 3, 0, "MODEL"],
|
||||
[2, 5, 0, 3, 3, "LATENT"],
|
||||
[3, 4, 1, 6, 0, "CLIP"],
|
||||
[4, 6, 0, 3, 1, "CONDITIONING"],
|
||||
[5, 4, 1, 7, 0, "CLIP"],
|
||||
[6, 7, 0, 3, 2, "CONDITIONING"],
|
||||
[7, 3, 0, 8, 0, "LATENT"],
|
||||
[8, 4, 2, 8, 1, "VAE"],
|
||||
[9, 8, 0, 9, 0, "IMAGE"]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {"ds": {"scale": 0.8, "offset": [0, 0]}},
|
||||
"version": 0.4
|
||||
}
|
||||
Reference in New Issue
Block a user