-
-
Notifications
You must be signed in to change notification settings - Fork 2
Architecture
System design overview for contributors and advanced users.
Browser (Next.js Frontend) ──HTTP/WS──→ FastAPI Backend ──→ Service Layer ──→ Kohya SS (Training)
│
├── HuggingFace Hub
├── Civitai API
└── ComfyUI (Generation)
FastAPI route handlers that accept HTTP requests from the frontend and delegate to the service layer.
| File | Purpose |
|---|---|
api/main.py |
FastAPI app entry point, CORS, WebSocket setup |
api/routes/dataset.py |
Dataset upload, browse, delete |
api/routes/training.py |
Training config validation and execution |
api/routes/models.py |
Model downloads (HuggingFace / Civitai) |
api/routes/utilities.py |
LoRA resize, merge, HuggingFace upload |
api/routes/config.py |
Configuration management |
api/routes/files.py |
File operations and tree browsing |
api/routes/settings.py |
Application settings persistence |
api/routes/civitai.py |
Civitai API proxy |
api/routes/debug.py |
Debug and diagnostic endpoints |
Key detail: api/main.py sets asyncio.WindowsProactorEventLoopPolicy() on Windows — do not remove. Server bind to 0.0.0.0 (required for cloud deployment). Routes never call Kohya scripts directly.
Business logic layer. Route handlers call services; services call the training backend. This is the core of the application.
services/
├── core/ # Foundation
│ ├── exceptions.py # Exception hierarchy
│ ├── validation.py # Path validation (security)
│ └── log_parser.py # Kohya/WD14 log parsing
├── models/ # Pydantic schemas
│ ├── training.py # TrainingConfig (~140 fields)
│ ├── tagging.py # Tagging config
│ ├── dataset.py # Dataset models
│ ├── caption.py # Caption models
│ ├── lora.py # LoRA utility models
│ ├── job.py # Job tracking models
│ └── common.py # Shared base models
├── jobs/ # Job management
│ ├── job.py # Job dataclass
│ ├── job_store.py # In-memory storage (dict-based)
│ └── job_manager.py # Subprocess monitoring
├── trainers/ # Training backends
│ ├── base.py # BaseTrainer ABC
│ ├── kohya.py # KohyaTrainer implementation
│ └── kohya_toml.py # TOML config generation
├── training_service.py # Training orchestration
├── tagging_service.py # WD14 tagging
├── captioning_service.py # BLIP/GIT captioning
├── dataset_service.py # Dataset file operations
├── caption_service.py # Caption file editing
├── lora_service.py # LoRA utilities
├── websocket.py # WebSocket handlers
└── __init__.py # Service exports
~3200 lines across 24 files. All services are fully built.
- Small files — each <200 lines
- Pydantic first — data validation from the start
-
Async by default — non-blocking subprocess execution via
asyncio.create_subprocess_exec -
Job tracking built-in — all long operations return a
job_id -
Strategy pattern —
BaseTrainerABC allows swapping training backends -
Never hardcode paths — use
sys.executableandos.path.join()
Every long-running operation (training, tagging, captioning) creates a job:
- In-memory store (dict-based, no database required)
- Log buffer: last 1000 lines
- Status updates: 500ms intervals via WebSocket
- Progress: parsed from Kohya/WD14 tqdm output
BaseTrainer (ABC)
└── KohyaTrainer (current)
└── MultiGPUKohyaTrainer (future)
└── ROCmTrainer (future)
All trainers share the same interface. TOML generation is handled by kohya_toml.py which produces:
-
dataset.toml— dataset config (paths, resolution, batch size) -
config.toml— training hyperparameters
Next.js 16 with React 19, TypeScript, and Tailwind CSS v4.
- Framework: Next.js 16.2.4 (App Router)
- UI Components: shadcn/ui (Radix primitives)
-
API Integration: Centralized
lib/api.tswith typed modules - State Management: React hooks + TanStack Query
- Real-time: Native WebSocket API
- Styling: Tailwind CSS v4 with CSS custom properties
| Route | Purpose |
|---|---|
/ |
Homepage |
/dataset |
Dataset uploader |
/dataset/[name]/tags |
Tag editor with image gallery |
/dataset/[name]/auto-tag |
Auto-tagging interface |
/files |
File manager with tree view |
/models |
Model downloader |
/training |
Training configuration |
/calculator |
LoRA step calculator |
/utilities |
Post-training utilities |
/settings |
Application settings |
frontend/
├── app/ # Next.js App Router pages
├── components/
│ ├── ui/ # shadcn/ui components
│ ├── blocks/ # Page sections (navbar, footer, hero)
│ ├── training/ # Training-specific components
│ └── effects/ # Visual effects library
├── lib/
│ └── api.ts # Centralized API client
└── hooks/ # Custom React hooks
- All backend communication through
lib/api.ts— never fetch the backend directly from components - Typed modules:
datasetAPI,trainingAPI,fileAPI,modelsAPI,utilitiesAPI,captioningAPI - WebSocket connections:
trainingAPI.connectLogs(),datasetAPI.connectTaggingLogs(), etc. - Environment variable:
NEXT_PUBLIC_API_URL(default:http://localhost:8000/api)
- Mandatory: Use shadcn/ui components — never raw HTML form elements
-
TypeScript everywhere — no
.jsfiles infrontend/ -
Use
@/path alias, not relative paths - Accessibility is mandatory — semantic HTML, keyboard navigation, ARIA attributes
-
'use client'for components with hooks or browser APIs - Server components preferred when no client-side features needed
Vendored Kohya SS distribution (committed directly, not a git submodule):
| Directory | Purpose |
|---|---|
sd_scripts/ |
Kohya SS training scripts |
lycoris/ |
LyCORIS library (DoRA, LoHa, LoKr) |
custom_scheduler/ |
Custom optimizers (CAME, Compass, LPFAdamW) |
Do not modify vendored backend files unless explicitly instructed. Upstream bug fixes are documented in docs/upstream-bug-fixes-2026-05-05.md (20 bugs fixed across sd-scripts and LyCORIS).
| Script | Platform | Purpose |
|---|---|---|
install.bat / install.sh
|
Windows / Linux | Install dependencies |
installer.py |
Both | Python dependency installer |
start_services_local.bat / .sh
|
Both | Start locally |
start_services_vastai.sh |
VastAI | Supervisor-managed startup |
provision_runpod.sh |
RunPod | Direct port binding startup |
vastai_setup.sh |
VastAI | One-time provisioning |
restart.bat / restart.sh
|
Both | Quick restart (no rebuild) |
fetch-restart.sh |
Linux | Pull + rebuild + restart |
diagnose.bat / diagnose.sh
|
Both | Diagnostic collection |
clean_slate.py |
Both | Remove build artifacts |
Two TOML files auto-generated from web UI form inputs:
-
trainer/runtime_store/dataset.toml— dataset config -
trainer/runtime_store/config.toml— hyperparameters
The kohya_toml.py service handles generation. The TOML files are consumed by KohyaTrainer which launches Kohya SS as a subprocess.
User fills form → Pydantic validates → kohya_toml.py generates TOML →
KohyaTrainer launches subprocess → Job manager monitors →
Logs stream via WebSocket → Frontend displays progress
When adding or modifying features, maintain consistency across all three layers:
-
Frontend (
lib/api.ts+lib/validation.ts) — TypeScript types and Zod schemas -
API Route (
api/routes/) — FastAPI endpoint with route-level Pydantic model -
Service Layer (
services/) — Business logic with service-level Pydantic model
Field names, types, and defaults must match across all layers.
- Contributing — development process and code standards
- Upstream-Reference — vendored Kohya SS and LyCORIS documentation