You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
348 lines
13 KiB
348 lines
13 KiB
# Stable Diffusion Python WebUI
|
|
|
|
> This project is based on a script from https://github.com/imanslab/poc-uncensored-stable-diffusion/
|
|
|
|
A local web interface for generating images with Stable Diffusion, designed for fast iteration with the model kept loaded in memory.
|
|
|
|
This is basically a very simplified reimplementation of Automatic1111
|
|
|
|
This README will guide you through setup and basic usage.
|
|
|
|

|
|
|
|
---
|
|
|
|
**Warning** A lot of this project was made with claude code because I just wanted to have a working SD webui and Automation1111 refused to work for me. The whole thing was made in two days. This is not aiming to be a maintainable project. It's best to run claude, tell it to read this README and have it make the changes you want.
|
|
|
|
I have AMD RX 6600 XT, which is not supported by ROCm, but works fine with `HSA_OVERRIDE_GFX_VERSION=10.3.0` in env. That essentially lies about the GPU you have, and somehow a lie is sufficient here. Welcome to ML python.
|
|
|
|
This will work best with NVIDIA, but you will need some adjustments as I optimized it for my AMD card.
|
|
|
|
---
|
|
|
|
## Legal Disclaimer
|
|
|
|
THIS GENERATOR IS FOR LOCAL USE ONLY AND MUST NOT BE EXPOSED TO THE INTERNET
|
|
|
|
- **No Responsibility**: The creators of this project bear no responsibility for how the software is used.
|
|
- **An uncensored model has no guardrails**.
|
|
- **You are responsible for anything you do with the tool and the model you downloaded**, just as you are responsible for anything you do with any dangerous object.
|
|
- **Publishing anything this model generates is the same as publishing it yourself**.
|
|
- Ensure compliance with all applicable laws and regulations in your jurisdiction.
|
|
- If you unintentionally generate something illegal, delete it immediately and permanently (not to recycle bin)
|
|
- All pictures are saved in the `out/` folder
|
|
- Clear browser cache and other relevant caches
|
|
|
|
### Safety checker
|
|
|
|
Some models have a built-in safety (NSFW) checker. You can try enabling it, but in my experience, it blacks out even totally safe results.
|
|
|
|
By default, safety checker is disabled. To enable it, remove this piece from the pipeline: `, safety_checker=None`
|
|
|
|
e.g. in `StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16, safety_checker=None)`
|
|
|
|
## Prerequisites
|
|
|
|
- **Python 3.11+**
|
|
- Compatible GPU (default config is for AMD with ROCm) - ROCm must be installed system-wide
|
|
|
|
Optional:
|
|
- **Git**
|
|
- **Git LFS** (Large File Storage) - Required for downloading models. Install from [git-lfs.github.com](https://git-lfs.github.com)
|
|
|
|
## Setup
|
|
|
|
### Create directories
|
|
|
|
- models
|
|
- lora (if using)
|
|
- out
|
|
|
|
these are in gitignore.
|
|
|
|
### Install Python dependencies
|
|
|
|
```bash
|
|
# Create Virtual Environment
|
|
python -m venv .venv
|
|
source .venv/bin/activate
|
|
|
|
# Install Dependencies
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
You may need to edit the requirements file to fit your particular setup.
|
|
|
|
You also need system-wide install of ROCm and amdgpu.ids - it will complain if they are missing
|
|
|
|
### Download a model
|
|
|
|
Models go in the `models/` directory.
|
|
|
|
**Supported formats:**
|
|
- `.safetensors` - Single-file safetensors format
|
|
- `.ckpt` - Single-file checkpoint format
|
|
- Directory - Diffusers pretrained model directory
|
|
|
|
You can use any Stable Diffusion 1.5 or SDXL model.
|
|
|
|
The simplest way is to download them from civitai.com (safetensors format)
|
|
|
|
For diffusers format (e.g. from Huggingface.co), e.g.:
|
|
|
|
https://huggingface.co/stablediffusionapi/realistic-vision-v51
|
|
|
|
```bash
|
|
mkdir -p models
|
|
cd models
|
|
git lfs install # Needed once
|
|
|
|
# Download using git lfs
|
|
git clone https://huggingface.co/stablediffusionapi/realistic-vision-v51
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Model Configuration
|
|
|
|
Use environment variables to configure which model to load:
|
|
|
|
| Variable | Values | Default | Description |
|
|
|----------|--------|---------|-------------|
|
|
| `SD_MODEL_PATH` | path | `./models/my-diffusers-model` | Path to model file or directory |
|
|
| `SD_MODEL_TYPE` | `sd15`, `sdxl` | `sd15` | Model architecture type |
|
|
| `SD_LOW_VRAM` | `1`, `true`, `yes` | disabled | Enable for GPUs with <12GB VRAM |
|
|
| `SD_LORA_STACK` | see below | none | LoRA files to load with weights |
|
|
|
|
```bash
|
|
# SD 1.5 safetensors file
|
|
SD_MODEL_PATH=./models/my_sd15_model.safetensors ./run_web.sh
|
|
|
|
# SDXL safetensors file
|
|
SD_MODEL_TYPE=sdxl SD_MODEL_PATH=./models/my_sdxl_model.safetensors ./run_web.sh
|
|
|
|
# SDXL on GPU with <12GB VRAM (slower but works)
|
|
SD_MODEL_TYPE=sdxl SD_MODEL_PATH=./models/my_sdxl_model.safetensors SD_LOW_VRAM=1 ./run_web.sh
|
|
|
|
# SD 1.5 ckpt checkpoint file
|
|
SD_MODEL_PATH=./models/my_model.ckpt ./run_web.sh
|
|
|
|
# Diffusers directory (default)
|
|
SD_MODEL_PATH=./models/my-diffusers-model ./run_web.sh
|
|
```
|
|
|
|
### LoRA Configuration
|
|
|
|
Load one or more LoRA files using the `SD_LORA_STACK` environment variable.
|
|
|
|
Note: I'm not sure if this actually works, in my experience it more degraded the picture quality.
|
|
|
|
**Format:** `path/to/lora.safetensors:WEIGHT,path/to/other.safetensors:WEIGHT`
|
|
|
|
- Paths are comma-separated
|
|
- Weight is optional (defaults to 1.0)
|
|
- Weight range: 0.0 to 1.0+ (higher values = stronger effect)
|
|
|
|
```bash
|
|
# Single LoRA with default weight (1.0)
|
|
SD_LORA_STACK=./loras/style.safetensors ./run_web.sh
|
|
|
|
# Single LoRA with custom weight
|
|
SD_LORA_STACK=./loras/style.safetensors:0.8 ./run_web.sh
|
|
|
|
# Multiple LoRAs stacked
|
|
SD_LORA_STACK=./loras/style.safetensors:0.7,./loras/character.safetensors:0.5 ./run_web.sh
|
|
```
|
|
|
|
LoRAs are loaded at startup and applied to all generations. Make sure your LoRAs are compatible with your base model type (SD 1.5 LoRAs for SD 1.5 models, SDXL LoRAs for SDXL models).
|
|
|
|
### Frontend
|
|
|
|
Frontend constants in `templates/index.html`, normally this does not need changing.
|
|
|
|
```javascript
|
|
const CONFIG = {
|
|
GUIDANCE_MIN: 1,
|
|
GUIDANCE_MAX: 20,
|
|
GUIDANCE_SPREAD: 2.5, // Range spread when syncing to slider
|
|
STEPS_MIN: 1,
|
|
STEPS_MAX: 100,
|
|
STEPS_SPREAD: 15, // Range spread when syncing to slider
|
|
DEFAULT_TIME_ESTIMATE: 20 // Seconds, for first image progress bar
|
|
};
|
|
```
|
|
|
|
## Run the POC to verify config
|
|
|
|
Download a diffusers model e.g. `realistic-vision-v51` using the example above.
|
|
|
|
Run `run_poc.sh` (modify it as needed).
|
|
|
|
It will generate a picture to `out/` and open it in your image viewer.
|
|
|
|
|
|
## Run the Server
|
|
|
|
1. Copy `run_web_example.sh` to `run_web.sh` and customize the env vars to fit your needs - choice of mode, special options for your GPU etc.
|
|
|
|
2. Start the server
|
|
|
|
```bash
|
|
./run_web.sh
|
|
```
|
|
|
|
Or manually:
|
|
```bash
|
|
source .venv/bin/activate
|
|
python app.py
|
|
```
|
|
|
|
Open http://localhost:5000 in your browser.
|
|
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Browser │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ index.html + style.css │ │
|
|
│ │ - Form controls for generation parameters │ │
|
|
│ │ - Real-time progress bar with ETA │ │
|
|
│ │ - Streaming image display via SSE │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────┬───────────────────────────────────┘
|
|
│ HTTP + Server-Sent Events
|
|
┌─────────────────────────▼───────────────────────────────────┐
|
|
│ Flask Server (app.py) │
|
|
│ - GET / → Serve UI │
|
|
│ - POST /generate → Stream generated images via SSE │
|
|
│ - GET /out/<file> → Serve saved images │
|
|
└─────────────────────────┬───────────────────────────────────┘
|
|
│
|
|
┌─────────────────────────▼───────────────────────────────────┐
|
|
│ Pipeline Manager (sd_pipeline.py) │
|
|
│ - Singleton pattern keeps model in GPU memory │
|
|
│ - Thread-safe generation with locking │
|
|
│ - Yields images one-by-one for streaming │
|
|
└─────────────────────────┬───────────────────────────────────┘
|
|
│
|
|
┌─────────────────────────▼───────────────────────────────────┐
|
|
│ Stable Diffusion Model │
|
|
│ - Loaded once at startup │
|
|
│ - Persists between requests for fast regeneration │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Technologies
|
|
|
|
| Component | Technology | Purpose |
|
|
|--------------|--------------------------|-------------------------------------|
|
|
| Backend | Flask | Lightweight Python web framework |
|
|
| Frontend | Vanilla HTML/CSS/JS | No build step, minimal dependencies |
|
|
| ML Framework | PyTorch + Diffusers | Stable Diffusion inference |
|
|
| Streaming | Server-Sent Events (SSE) | Real-time image delivery |
|
|
| GPU | CUDA/ROCm | Hardware acceleration |
|
|
|
|
## File Structure
|
|
|
|
```
|
|
poc-uncensored-stable-diffusion/
|
|
├── app.py # Flask application with routes
|
|
├── sd_pipeline.py # Singleton pipeline manager
|
|
├── models.py # Data classes (GenerationOptions, ImageResult, etc.)
|
|
├── templates/
|
|
│ └── index.html # Main UI with embedded JS
|
|
├── static/
|
|
│ └── style.css # Styling with dark theme
|
|
├── run_web.sh # Startup script with env vars
|
|
├── requirements.txt # Python dependencies
|
|
├── out/ # Generated images output
|
|
└── models/ # Model files (SD 1.5, SDXL)
|
|
```
|
|
|
|
## Features
|
|
|
|
### Generation Parameters
|
|
|
|
- **Prompt**: Text description for image generation
|
|
- **Negative Prompt**: Things to avoid in the image
|
|
- **Seed**: Reproducible generation (random button generates 9-digit seed)
|
|
- **Steps**: Number of inference steps (1-100, default 20)
|
|
- **Guidance Scale**: CFG scale (1-20, default 7.5)
|
|
- **Number of Images**: Batch generation (1-10)
|
|
- **Quality Keywords**: Optional suffix for enhanced quality
|
|
|
|
### Variation Modes
|
|
|
|
- **Increment Seed**: Each image in batch gets seed+1 (default on)
|
|
- **Vary Guidance**: Sweep guidance scale across a range
|
|
- **Vary Steps**: Sweep step count across a range
|
|
|
|
When vary modes are enabled, the corresponding slider hides and low/high range inputs appear. Range inputs stay synchronized with slider values when vary mode is off.
|
|
|
|
### Progress Indication
|
|
|
|
- Spinner animation during generation
|
|
- Progress bar with percentage and ETA countdown
|
|
- First image assumes 20s estimate, subsequent images use measured time
|
|
- After 90%, progress slows asymptotically until image arrives
|
|
- Measured time persists across generations for accurate estimates
|
|
|
|
### Streaming Results
|
|
|
|
- Images appear immediately as they complete (Server-Sent Events)
|
|
- No waiting for entire batch to finish
|
|
- Each image card shows: seed, steps, guidance scale, prompt, link to saved file
|
|
|
|
### Settings Management
|
|
|
|
- **Export**: Download current settings as JSON file
|
|
- **Import**: Load settings from JSON file
|
|
- All parameters preserved including vary mode ranges
|
|
|
|
### Responsive Layout
|
|
|
|
- **Narrow screens**: Stacked layout (form above results)
|
|
- **Wide screens (>1200px)**: Side-by-side layout
|
|
- Left panel: Fixed-width control form with scrollbar
|
|
- Right panel: Scrollable results grid
|
|
|
|
### Output Files
|
|
|
|
Each generated image saves two files to `out/`:
|
|
- `YY-MM-DD_HH-MM-SS_SEED.jpg` - The image
|
|
- `YY-MM-DD_HH-MM-SS_SEED.json` - Metadata file in a format that can be imported to the web UI to re-apply the settings.
|
|
|
|
## API
|
|
|
|
### POST /generate
|
|
|
|
Request (JSON):
|
|
```json
|
|
{
|
|
"prompt": "your prompt",
|
|
"negative_prompt": "things to avoid",
|
|
"seed": 12345,
|
|
"steps": 20,
|
|
"guidance_scale": 7.5,
|
|
"count": 1,
|
|
"width": 512,
|
|
"height": 512,
|
|
"add_quality_keywords": true,
|
|
"increment_seed": true,
|
|
"vary_guidance": false,
|
|
"guidance_low": 5.0,
|
|
"guidance_high": 12.0,
|
|
"vary_steps": false,
|
|
"steps_low": 20,
|
|
"steps_high": 80
|
|
}
|
|
```
|
|
|
|
Response (SSE stream):
|
|
```
|
|
data: {"index":1,"total":1,"filename":"...","seed":12345,"steps":20,"guidance_scale":7.5,"width":512,"height":512,"prompt":"...","negative_prompt":"...","full_prompt":"...","url":"/out/...","base64":"data:image/jpeg;base64,..."}
|
|
|
|
data: {"done":true}
|
|
```
|
|
|