SanskarModi commited on
Commit
600587b
·
1 Parent(s): 09a9be4

updated code to auto downlaod loras

Browse files
.gitignore ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+ #poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ #pdm.lock
116
+ #pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ #pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # SageMath parsed files
135
+ *.sage.py
136
+
137
+ # Environments
138
+ .env
139
+ .envrc
140
+ .venv
141
+ env/
142
+ venv/
143
+ ENV/
144
+ env.bak/
145
+ venv.bak/
146
+
147
+ # Spyder project settings
148
+ .spyderproject
149
+ .spyproject
150
+
151
+ # Rope project settings
152
+ .ropeproject
153
+
154
+ # mkdocs documentation
155
+ /site
156
+
157
+ # mypy
158
+ .mypy_cache/
159
+ .dmypy.json
160
+ dmypy.json
161
+
162
+ # Pyre type checker
163
+ .pyre/
164
+
165
+ # pytype static type analyzer
166
+ .pytype/
167
+
168
+ # Cython debug symbols
169
+ cython_debug/
170
+
171
+ # PyCharm
172
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
173
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
175
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
176
+ #.idea/
177
+
178
+ # Abstra
179
+ # Abstra is an AI-powered process automation framework.
180
+ # Ignore directories containing user credentials, local state, and settings.
181
+ # Learn more at https://abstra.io/docs
182
+ .abstra/
183
+
184
+ # Visual Studio Code
185
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
+ # you could uncomment the following to ignore the entire vscode folder
189
+ # .vscode/
190
+
191
+ # Ruff stuff:
192
+ .ruff_cache/
193
+
194
+ # PyPI configuration file
195
+ .pypirc
196
+
197
+ # Cursor
198
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
199
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
200
+ # refer to https://docs.cursor.com/context/ignore-files
201
+ .cursorignore
202
+ .cursorindexingignore
203
+
204
+ # Marimo
205
+ marimo/_static/
206
+ marimo/_lsp/
207
+ __marimo__/
208
+
209
+ src/assets
210
+ *.ckpt
211
+ *.safetensors
212
+ *.pt
213
+ *.bin
214
+ *.pth
README.md CHANGED
@@ -5,162 +5,179 @@ sdk: gradio
5
  sdk_version: 6.0.2
6
  ---
7
 
8
- # Stable Diffusion Image Generator Toolkit
9
 
10
  ![appdemo](https://drive.google.com/uc?export=view&id=1dO2bnYmEEj3fNU0-dV692icUPSwyP93G)
11
 
 
12
 
13
- A modular image generation system built on **HuggingFace Diffusers**, with support for multiple Stable Diffusion pipelines, configurable inference parameters, a clean **Gradio UI**, and a lightweight local **history/metadata store**.
 
 
14
 
15
- The system supports **text-to-image**, **image-to-image**, and **super-resolution upscaling** using **Real-ESRGAN (NCNN)**.
16
- Designed with a focus on **extensibility**, **clean code**, and **practical deployment constraints** (CPU or low-memory environments).
17
 
18
- [Visit App](https://huggingface.co/spaces/SanskarModi/sd-image-gen-toolkit)
19
 
20
  ---
21
 
22
- # Core Features
23
 
24
- ## Text-to-Image Generation
 
 
 
 
 
 
 
 
 
25
 
26
- * Stable Diffusion pipelines (SD 1.5, Turbo)
27
- * Adjustable **CFG scale**, **inference steps**, resolution, and seed
28
- * Structured metadata (JSON) for reproducibility
29
- * Style presets with recommended parameters
 
 
30
 
31
- ## Image-to-Image (Img2Img)
 
 
 
 
32
 
33
- * Pipeline reuse to avoid model reload cost
34
- * Alpha-preserving prompt transforms
35
- * Configurable denoising strength
36
- * Deterministic or stochastic sampling
 
 
37
 
38
- ## Upscaling (Real-ESRGAN NCNN)
39
 
40
- * Lightweight **NCNN backend** (GPU not required)
41
- * Supports and scaling
42
- * Optional SD-upscaler backend planned
43
- * Minimal dependencies, fast on CPU
44
 
45
- ## Prompt History & Metadata Tracking
 
 
 
 
 
 
 
46
 
47
- * Local metadata index with atomic writes
48
- * Thumbnail + full-size image storage
49
- * JSON schema for portability
50
- * History browser UI
51
 
52
- ## Multi-Model Runtime Switching
53
 
54
- * Multiple pipelines loaded once
55
- * Selection at inference without reload
56
- * Shared tokenizer/encoder where possible
57
- * Warm-up logic for fast Turbo inference
58
 
59
  ---
60
 
61
- # Architecture Overview
62
 
63
  ```
64
- src/sdgen/
65
-
66
- ├── sd/
67
- ├── pipeline.py # pipeline loader, warmup, dtype/device logic
68
- │ ├── generator.py # text-to-image
69
- │ ├── img2img.py # image-to-image
70
- └── models.py # config/metadata dataclasses
 
 
71
 
72
- ├── ui/
73
- │ ├── layout.py # top-level UI composition
74
- │ └── tabs/ # individual UI components
 
 
 
 
 
75
 
76
- ├── presets/
77
- │ └── styles.py # curated style presets
78
 
79
- ├── upscaler/
80
- └── realesrgan.py # NCNN Real-ESRGAN backend
 
81
 
82
- ├── utils/
83
- │ ├── history.py # persistence layer
84
- │ ├── common.py # PIL/NumPy helpers
85
- │ └── logger.py # structured logging
86
 
87
- └── config/
88
- ├── settings.py # runtime config/env
89
- └── paths.py # project paths
90
- ```
91
 
92
- ---
93
-
94
- # Technical Highlights
95
 
96
- ### Efficient CPU Deployment
97
 
98
- HF Spaces have **no GPU**, 16 GB RAM.
99
- Generation speed is optimized via:
100
 
101
- * latent consistency (Turbo)
102
- * reduced step ranges
103
- * VAE tiling for memory distribution
104
- * attention slicing
105
- * deferring safety checker if private
106
 
107
- This reduces **CPU inference from ~220s → <70s** for 512px prompts, without unacceptable quality loss.
 
108
 
109
- ### Multi-Pipeline Switching
110
 
111
- Both SD pipelines are instantiated once.
112
- The UI passes `model_choice` to the handler, which selects the correct pipeline **without rebuilding**.
 
 
 
 
113
 
114
- This avoids 4-7 GB reload cost per click.
 
115
 
116
  ---
117
 
118
- # Local Installation
119
-
120
- ### 1. Clone
121
 
 
122
  ```bash
123
  git clone https://github.com/sanskarmodi8/stable-diffusion-image-generator
124
  cd stable-diffusion-image-generator
125
- ```
126
 
127
- ### 2. Environment
128
 
129
  ```bash
130
  python -m venv .venv
131
  source .venv/bin/activate
132
  ```
133
 
134
- ### 3. Install Dependencies
135
-
136
- Install PyTorch for GPU (leave if on CPU):
137
-
138
- ```bash
139
- pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
140
- ```
141
-
142
- Install core libs:
143
 
144
  ```bash
145
  pip install -r requirements.txt
146
  pip install -e .
147
  ```
148
 
149
- ### 4. HuggingFace Login (optional)
150
 
151
  ```bash
152
- huggingface-cli login
 
153
  ```
154
 
155
  ---
156
 
157
- # Running
158
 
159
  ```bash
160
  python src/sdgen/main.py
161
  ```
162
 
163
- UI available at:
164
 
165
  ```
166
  http://127.0.0.1:7860
@@ -168,191 +185,62 @@ http://127.0.0.1:7860
168
 
169
  ---
170
 
171
- # Roadmap (Focused, High-Impact Features)
172
-
173
- This project is under active development. The next milestones focus on **practical model customization and multi-model support**, optimized for **CPU-only deployment environments** such as Hugging Face Spaces.
174
-
175
- The roadmap is intentionally **lean** to maximize value within limited compute constraints.
176
-
177
- ---
178
-
179
- ## 1. LoRA Runtime Inference (Core Feature)
180
 
181
- Add lightweight **Low-Rank Adaptation** support for Stable Diffusion pipelines without modifying base model weights.
182
 
183
- ### Scope
184
- - Load external **`.safetensors` LoRA adapters** into UNet
185
- - Apply LoRA modules dynamically at inference
186
- - **Alpha (weight) slider** to control influence
187
- - **UI dropdown** for selecting LoRA adapters
188
- - **Automatic discovery** of LoRAs under:
189
  ```
190
-
191
  src/assets/loras/
192
-
193
- ```
194
-
195
- ### Deliverables
196
- - `lora_loader.py` utility
197
- - integration into existing `load_pipeline()`
198
- - UI: LoRA selector + alpha parameter
199
- - history metadata with:
200
- - `lora_paths`
201
- - `lora_weights`
202
-
203
- ---
204
-
205
- ## 2. Multi-LoRA Mixing (2 adapters)
206
-
207
- Support mixing **two LoRA adapters** with independent weights.
208
-
209
- ### Scope
210
- - Simple weighted merge at attention processors
211
- - UI:
212
- - LoRA A dropdown + alpha
213
- - LoRA B dropdown + alpha
214
- - Conflict handling for overlapping layers
215
-
216
- ### Deliverables
217
- - `apply_lora_mix()` utility
218
- - metadata persistence
219
-
220
- ---
221
-
222
- ## 3. SDXL-Turbo Pipeline Support
223
-
224
- Add a **third runtime model**:
225
  ```
226
 
227
- stabilityai/stable-diffusion-xl-base
228
- stabilityai/sdxl-turbo
229
 
230
- ````
231
-
232
- ### Scope
233
- - instantiate SDXL Turbo pipeline
234
- - auto configure:
235
- - steps (1-4)
236
- - CFG (0-1)
237
- - model selection integrated in UI
238
- - reproducible metadata
239
-
240
- ### Notes
241
- SDXL Turbo is optimized for **fast generation** and works well on constrained environments with reduced steps.
242
 
243
  ---
244
 
245
- ## 4. Enhanced Presets
246
 
247
- Presets currently define only prompts. Extend them to define **full recommended parameter sets** per use case.
 
248
 
249
- ### Scope
250
- Each preset can define:
251
- - prompt
252
- - negative prompt
253
- - inference steps
254
- - CFG scale
255
- - resolution
256
- - recommended model
257
- - recommended LoRA (+alpha)
258
-
259
- ### Example
260
- ```json
261
- {
262
- "preset": "Anime Portrait",
263
- "prompt": "...",
264
- "negative": "...",
265
- "steps": 15,
266
- "cfg": 6,
267
- "width": 512,
268
- "height": 768,
269
- "model": "SD1.5",
270
- "lora": {
271
- "path": "anime_face.safetensors",
272
- "alpha": 0.8
273
- }
274
- }
275
- ````
276
-
277
- ---
278
-
279
- ## 5. Metadata Improvements
280
-
281
- Enhance metadata tracking for **reproducibility**.
282
 
283
- ### Added Fields
284
-
285
- * `model_id`
286
- * `lora_names`
287
- * `lora_alphas`
288
- * `preset_used`
289
- * `resolution`
290
- * provenance timestamp
291
-
292
- This enables exact replication of generated images.
293
 
294
  ---
295
 
296
- ## 6. Example LoRA & Training Scripts (No UI)
297
-
298
- Provide **self-contained example** to demonstrate training:
299
-
300
- * a Colab notebook for **LoRA fine-tuning**
301
- * a small 20-image dataset
302
- * training duration < 45 minutes on free GPU
303
- * export `.safetensors` file
304
- * use it in presets
305
 
306
- ### Deliverables
307
 
308
- * `examples/train_lora.ipynb`
309
- * resulting LoRA stored at `assets/loras/example.safetensors`
310
-
311
- ---
312
-
313
- # Contributing
314
 
315
- This repo is configured with **pre-commit**:
316
 
317
- * black
318
  * ruff
 
319
  * isort
320
- * docstring linting (Google style)
321
 
322
- Install hooks:
323
-
324
- ```bash
325
- pre-commit install
326
- ```
327
-
328
- Test formatting:
329
 
330
  ```bash
331
  ruff check .
332
  black .
333
  ```
334
 
335
- Branching convention:
336
-
337
- ```
338
- feat/<feature>
339
- fix/<issue>
340
- refactor/<module>
341
- ```
342
-
343
  ---
344
 
345
- # License
346
 
347
- This project is licensed under [MIT License](LICENSE).
 
348
 
349
  ---
350
 
351
- # Author
352
-
353
- **Sanskar Modi**
354
-
355
- Machine Learning Engineer
356
- Focused on production-grade ML systems.
357
 
358
- GitHub: [https://github.com/sanskarmodi8](https://github.com/sanskarmodi8)
 
5
  sdk_version: 6.0.2
6
  ---
7
 
8
+ # Stable Diffusion Image Generation Toolkit
9
 
10
  ![appdemo](https://drive.google.com/uc?export=view&id=1dO2bnYmEEj3fNU0-dV692icUPSwyP93G)
11
 
12
+ [**Live Demo**](https://huggingface.co/spaces/SanskarModi/sd-image-gen-toolkit)
13
 
14
+ ---
15
+
16
+ ## Overview
17
 
18
+ A modular, lightweight image generation toolkit built on **Hugging Face Diffusers**, designed for **CPU-friendly deployment**, clean architecture, and practical usability.
 
19
 
20
+ It supports **Text → Image**, **Image → Image**, and **Upscaling**, with a **preset system**, optional **LoRA adapters**, and a local **metadata history** for reproducibility.
21
 
22
  ---
23
 
24
+ ## Features
25
 
26
+ ### TextImage
27
+ - Stable Diffusion **1.5** and **Turbo**
28
+ - Configurable prompt parameters:
29
+ - prompt / negative prompt
30
+ - steps
31
+ - guidance (CFG)
32
+ - resolution
33
+ - seed (optional)
34
+ - JSON metadata output
35
+ - Style presets for quick experimentation
36
 
37
+ ### Image Image
38
+ - Modify existing images via the SD Img2Img pipeline
39
+ - Denoising strength control
40
+ - Full parameter configuration
41
+ - Shared preset system
42
+ - History saved for reproducibility
43
 
44
+ ### Upscaling (Real-ESRGAN NCNN)
45
+ - **2× and 4×** upscaling
46
+ - NCNN backend (no GPU required)
47
+ - Minimal dependencies
48
+ - Fast on CPU environments (HF Spaces)
49
 
50
+ ### LoRA Adapter Support
51
+ - Runtime loading of `.safetensors` adapters
52
+ - Up to **two adapters** with independent weights
53
+ - Alpha range `-2 → +2` per adapter
54
+ - Automatic discovery under:
55
+ ```
56
 
57
+ src/assets/loras/
58
 
59
+ ```
60
+ - LoRA UI is **disabled for Turbo**, since Turbo does not benefit from LoRA injection
 
 
61
 
62
+ ### Metadata History
63
+ Every generation stores:
64
+ - model id
65
+ - prompt + negative prompt
66
+ - steps, cfg, resolution
67
+ - seed
68
+ - LoRA names + weights
69
+ - timestamp
70
 
71
+ All generated data is stored in a tree structure under:
72
+ ```
 
 
73
 
74
+ src/assets/history/
75
 
76
+ ```
 
 
 
77
 
78
  ---
79
 
80
+ ## Architecture
81
 
82
  ```
83
+
84
+ src/
85
+ └── sdgen/
86
+ ├── sd/ # Stable Diffusion runtime
87
+ │ ├── pipeline.py # model loading, device config
88
+ │ ├── generator.py # text-to-image inference
89
+ ├── img2img.py # image-to-image inference
90
+ │ ├── lora_loader.py # LoRA discovery & injection
91
+ │ └── models.py # typed config & metadata objects
92
 
93
+ ├── ui/ # Gradio UI components
94
+ │ ├── layout.py # composition root for UI
95
+ │ └── tabs/ # modular tabs
96
+ │ ├── txt2img_tab.py
97
+ │ ├── img2img_tab.py
98
+ │ ├── upscaler_tab.py
99
+ │ ├── presets_tab.py
100
+ │ └── history_tab.py
101
 
102
+ ├── presets/ # curated basic presets
103
+ │ └── styles.py # preset registry
104
 
105
+ ├── upscaler/ # Real-ESRGAN NCNN backend
106
+ ├── upscaler.py # interface + metadata
107
+ │ └── realesrgan.py # NCNN wrapper
108
 
109
+ ├── utils/ # shared utilities
110
+ │ ├── history.py # atomic storage format
111
+ │ ├── common.py # PIL helpers
112
+ │ └── logger.py # structured logging
113
 
114
+ └── config/ # static configuration
115
+ ├── paths.py # resolved directories
116
+ └── settings.py # environment settings
 
117
 
118
+ ````
 
 
119
 
120
+ ---
121
 
122
+ ## Presets (Included)
 
123
 
124
+ The project includes **four style presets**, each defining:
 
 
 
 
125
 
126
+ - prompt
127
+ - negative prompt
128
 
129
+ These presets are neutral and work with both **SD1.5** and **Turbo**:
130
 
131
+ | Name | Style |
132
+ |--------------------|----------------------------|
133
+ | Realistic Photo | 35mm, photorealistic |
134
+ | Anime | clean anime illustration |
135
+ | Cinematic / Moody | cinematic lighting/grain |
136
+ | Oil Painting | classical oil painting |
137
 
138
+ Presets do **not include LoRA parameters**.
139
+ Users may manually combine presets with LoRA adapters.
140
 
141
  ---
142
 
143
+ ## Installation
 
 
144
 
145
+ ### Clone
146
  ```bash
147
  git clone https://github.com/sanskarmodi8/stable-diffusion-image-generator
148
  cd stable-diffusion-image-generator
149
+ ````
150
 
151
+ ### Environment
152
 
153
  ```bash
154
  python -m venv .venv
155
  source .venv/bin/activate
156
  ```
157
 
158
+ ### Install Dependencies (CPU)
 
 
 
 
 
 
 
 
159
 
160
  ```bash
161
  pip install -r requirements.txt
162
  pip install -e .
163
  ```
164
 
165
+ ### GPU (optional)
166
 
167
  ```bash
168
+ pip install torch torchvision torchaudio \
169
+ --index-url https://download.pytorch.org/whl/cu121
170
  ```
171
 
172
  ---
173
 
174
+ ## Run
175
 
176
  ```bash
177
  python src/sdgen/main.py
178
  ```
179
 
180
+ Open in browser:
181
 
182
  ```
183
  http://127.0.0.1:7860
 
185
 
186
  ---
187
 
188
+ ## Adding LoRA Models
 
 
 
 
 
 
 
 
189
 
190
+ Place `.safetensors` files here:
191
 
 
 
 
 
 
 
192
  ```
 
193
  src/assets/loras/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  ```
195
 
196
+ They will be automatically detected and displayed in the UI (SD1.5 only).
 
197
 
198
+ This repository **does not include** LoRA files.
 
 
 
 
 
 
 
 
 
 
 
199
 
200
  ---
201
 
202
+ ## Third-Party LoRA Models
203
 
204
+ The app supports optional LoRA adapters.
205
+ LoRA weights are **not included** and are **the property of their respective authors**.
206
 
207
+ If you choose to download LoRA files automatically (see `lora_urls.py`), they are fetched directly from their original sources (**Civitai**).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
 
209
+ This project does **not** redistribute LoRA weights.
210
+ Refer to each model’s license on Civitai.
 
 
 
 
 
 
 
 
211
 
212
  ---
213
 
214
+ ## Development
 
 
 
 
 
 
 
 
215
 
216
+ The repo uses `pre-commit` hooks for consistency:
217
 
218
+ ```bash
219
+ pre-commit install
220
+ ```
 
 
 
221
 
222
+ Tools:
223
 
 
224
  * ruff
225
+ * black
226
  * isort
 
227
 
228
+ Check formatting:
 
 
 
 
 
 
229
 
230
  ```bash
231
  ruff check .
232
  black .
233
  ```
234
 
 
 
 
 
 
 
 
 
235
  ---
236
 
237
+ ## License
238
 
239
+ This project is licensed under the **MIT License**.
240
+ See the [`LICENSE`](LICENSE) file.
241
 
242
  ---
243
 
244
+ ## Author
 
 
 
 
 
245
 
246
+ [**Sanskar Modi**](https://github.com/sanskarmodi8)
src/sdgen/config/__init__.py CHANGED
@@ -6,6 +6,7 @@ so they can be imported directly from `sdgen.config`.
6
 
7
  from __future__ import annotations
8
 
 
9
  from .paths import (
10
  ASSETS_ROOT,
11
  HISTORY_ENTRIES_DIR,
@@ -26,4 +27,5 @@ __all__ = [
26
  "HISTORY_THUMBS_DIR",
27
  "HISTORY_FULL_DIR",
28
  "LOGS_ROOT",
 
29
  ]
 
6
 
7
  from __future__ import annotations
8
 
9
+ from .lora_urls import LORA_URLS
10
  from .paths import (
11
  ASSETS_ROOT,
12
  HISTORY_ENTRIES_DIR,
 
27
  "HISTORY_THUMBS_DIR",
28
  "HISTORY_FULL_DIR",
29
  "LOGS_ROOT",
30
+ "LORA_URLS",
31
  ]
src/sdgen/config/lora_urls.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """URLs for external LoRA adapters.
2
+
3
+ These URLs point directly to the original creators' downloads on Civitai.
4
+ We download the adapters at runtime if they are not present locally.
5
+
6
+ Legal note:
7
+ We do NOT redistribute LoRA weights in this repository.
8
+ Users download them from the original source at runtime.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Dict
14
+
15
+ # Direct API download endpoints from Civitai.
16
+ # we expect to have under `assets/loras/`.
17
+ LORA_URLS: Dict[str, str] = {
18
+ "DetailTweak.safetensors": "https://civitai.com/api/download/models/62833?type=Model&format=SafeTensor",
19
+ "MangaPanels.safetensors": "https://civitai.com/api/download/models/28907?type=Model&format=SafeTensor&size=full&fp=fp16",
20
+ "AnimeTarotCards.safetensors": "https://civitai.com/api/download/models/28609?type=Model&format=SafeTensor&size=full&fp=fp16",
21
+ }
src/sdgen/main.py CHANGED
@@ -16,10 +16,10 @@ import torch
16
  from dotenv import load_dotenv
17
 
18
  from sdgen.config import AppSettings
19
- from sdgen.sd.img2img import prepare_img2img_pipeline
20
- from sdgen.sd.pipeline import load_pipeline, warmup_pipeline
21
  from sdgen.ui import build_ui
22
  from sdgen.utils.logger import get_logger
 
23
 
24
  logger = get_logger(__name__)
25
  load_dotenv()
@@ -47,6 +47,12 @@ def main() -> None:
47
 
48
  device = "cpu"
49
 
 
 
 
 
 
 
50
  logger.info("Loading pipeline %s", model_id1)
51
  pipes = {
52
  "SD1.5": load_pipeline(
 
16
  from dotenv import load_dotenv
17
 
18
  from sdgen.config import AppSettings
19
+ from sdgen.sd import load_pipeline, prepare_img2img_pipeline, warmup_pipeline
 
20
  from sdgen.ui import build_ui
21
  from sdgen.utils.logger import get_logger
22
+ from sdgen.utils.lora_downloader import ensure_loras
23
 
24
  logger = get_logger(__name__)
25
  load_dotenv()
 
47
 
48
  device = "cpu"
49
 
50
+ # Download LoRAs (runtime)
51
+ try:
52
+ ensure_loras()
53
+ except Exception as exc:
54
+ logger.warning("LoRA download issue: %s", exc)
55
+
56
  logger.info("Loading pipeline %s", model_id1)
57
  pipes = {
58
  "SD1.5": load_pipeline(
src/sdgen/utils/lora_downloader.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Runtime downloader for external LoRA adapters.
2
+
3
+ If a LoRA file is not found locally under `assets/loras/`,
4
+ we download it from the original source URL.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import os
10
+ import shutil
11
+ from pathlib import Path
12
+
13
+ import requests
14
+
15
+ from sdgen.config.lora_urls import LORA_URLS
16
+ from sdgen.config.paths import ASSETS_ROOT
17
+ from sdgen.utils.logger import get_logger
18
+
19
+ logger = get_logger(__name__)
20
+
21
+ LORA_DIR: Path = ASSETS_ROOT / "loras"
22
+
23
+
24
+ def ensure_lora_dir() -> None:
25
+ """Create lora directory if missing."""
26
+ LORA_DIR.mkdir(parents=True, exist_ok=True)
27
+
28
+
29
+ def download_file(url: str, dst: Path, chunk: int = 8192) -> None:
30
+ """Stream download a file to destination path."""
31
+ with requests.get(url, stream=True, timeout=60) as r:
32
+ r.raise_for_status()
33
+ with open(dst, "wb") as f:
34
+ shutil.copyfileobj(r.raw, f)
35
+ logger.info("Downloaded LoRA: %s", dst.name)
36
+
37
+
38
+ def ensure_loras() -> None:
39
+ """Download missing LoRA weights at runtime."""
40
+ ensure_lora_dir()
41
+
42
+ for filename, url in LORA_URLS.items():
43
+ path = LORA_DIR / filename
44
+ if path.exists() and path.stat().st_size > 0:
45
+ logger.info("LoRA exists: %s", filename)
46
+ continue
47
+
48
+ logger.info("Downloading LoRA: %s", filename)
49
+ try:
50
+ download_file(url, path)
51
+ except Exception as exc: # noqa: BLE001
52
+ logger.exception("Failed to download LoRA %s: %s", filename, exc)
53
+ # cleanup partial file
54
+ if path.exists():
55
+ try:
56
+ os.remove(path)
57
+ except Exception:
58
+ pass