Add support for local LoRA from /workspace/loras/
Browse files
app.py
CHANGED
|
@@ -151,7 +151,7 @@ def resize_image(input_image, max_size=1024):
|
|
| 151 |
# Папка для локальных LoRA
|
| 152 |
LOCAL_LORA_DIR = "/workspace/loras"
|
| 153 |
|
| 154 |
-
# Базовые LoRA из HuggingFace Hub
|
| 155 |
HUB_LORAS = {
|
| 156 |
"Realism": {
|
| 157 |
"repo": "flymy-ai/qwen-image-realism-lora",
|
|
@@ -164,13 +164,8 @@ HUB_LORAS = {
|
|
| 164 |
"trigger": "Japanese modern anime style, ",
|
| 165 |
"weights": "pytorch_lora_weights.safetensors",
|
| 166 |
"source": "hub"
|
| 167 |
-
},
|
| 168 |
-
"Analog Film": {
|
| 169 |
-
"repo": "janekm/analog_film",
|
| 170 |
-
"trigger": "fifthel",
|
| 171 |
-
"weights": "converted_complete.safetensors",
|
| 172 |
-
"source": "hub"
|
| 173 |
}
|
|
|
|
| 174 |
}
|
| 175 |
|
| 176 |
def scan_local_loras():
|
|
@@ -220,8 +215,9 @@ logger.info(f" Total available LoRAs: {len(AVAILABLE_LORAS)}")
|
|
| 220 |
|
| 221 |
def load_lora_weights(pipeline, lora_name, lora_scale, hf_token):
|
| 222 |
"""
|
| 223 |
-
Загружает LoRA веса в pipeline
|
| 224 |
-
|
|
|
|
| 225 |
"""
|
| 226 |
if lora_name == "None" or lora_name not in AVAILABLE_LORAS:
|
| 227 |
return None
|
|
@@ -230,20 +226,27 @@ def load_lora_weights(pipeline, lora_name, lora_scale, hf_token):
|
|
| 230 |
|
| 231 |
try:
|
| 232 |
if lora_info['source'] == 'hub':
|
| 233 |
-
#
|
| 234 |
logger.info(f" Loading LoRA from Hub: {lora_info['repo']}")
|
|
|
|
|
|
|
| 235 |
pipeline.load_lora_weights(
|
| 236 |
lora_info['repo'],
|
| 237 |
weight_name=lora_info.get('weights', 'pytorch_lora_weights.safetensors'),
|
| 238 |
token=hf_token
|
| 239 |
)
|
|
|
|
|
|
|
| 240 |
else:
|
| 241 |
-
# Загрузка локального файла
|
| 242 |
logger.info(f" Loading local LoRA: {lora_info['path']}")
|
|
|
|
| 243 |
pipeline.load_lora_weights(
|
| 244 |
lora_info['path'],
|
| 245 |
adapter_name=lora_name
|
| 246 |
)
|
|
|
|
|
|
|
| 247 |
|
| 248 |
# Устанавливаем scale
|
| 249 |
if hasattr(pipeline, 'set_adapters'):
|
|
|
|
| 151 |
# Папка для локальных LoRA
|
| 152 |
LOCAL_LORA_DIR = "/workspace/loras"
|
| 153 |
|
| 154 |
+
# Базовые LoRA из HuggingFace Hub (загружаются по требованию)
|
| 155 |
HUB_LORAS = {
|
| 156 |
"Realism": {
|
| 157 |
"repo": "flymy-ai/qwen-image-realism-lora",
|
|
|
|
| 164 |
"trigger": "Japanese modern anime style, ",
|
| 165 |
"weights": "pytorch_lora_weights.safetensors",
|
| 166 |
"source": "hub"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
}
|
| 168 |
+
# Другие LoRA положите в /workspace/loras/ как .safetensors файлы
|
| 169 |
}
|
| 170 |
|
| 171 |
def scan_local_loras():
|
|
|
|
| 215 |
|
| 216 |
def load_lora_weights(pipeline, lora_name, lora_scale, hf_token):
|
| 217 |
"""
|
| 218 |
+
Загружает LoRA веса в pipeline (ленивая загрузка)
|
| 219 |
+
Hub LoRA скачиваются только при использовании
|
| 220 |
+
Локальные LoRA загружаются из /workspace/loras/
|
| 221 |
"""
|
| 222 |
if lora_name == "None" or lora_name not in AVAILABLE_LORAS:
|
| 223 |
return None
|
|
|
|
| 226 |
|
| 227 |
try:
|
| 228 |
if lora_info['source'] == 'hub':
|
| 229 |
+
# Ленивая загрузка с HuggingFace Hub (скачивается при первом использовании)
|
| 230 |
logger.info(f" Loading LoRA from Hub: {lora_info['repo']}")
|
| 231 |
+
logger.info(f" (Downloading if not cached...)")
|
| 232 |
+
|
| 233 |
pipeline.load_lora_weights(
|
| 234 |
lora_info['repo'],
|
| 235 |
weight_name=lora_info.get('weights', 'pytorch_lora_weights.safetensors'),
|
| 236 |
token=hf_token
|
| 237 |
)
|
| 238 |
+
|
| 239 |
+
logger.info(f" ✓ Hub LoRA loaded (cached for future use)")
|
| 240 |
else:
|
| 241 |
+
# Загрузка локального файла из /workspace/loras/
|
| 242 |
logger.info(f" Loading local LoRA: {lora_info['path']}")
|
| 243 |
+
|
| 244 |
pipeline.load_lora_weights(
|
| 245 |
lora_info['path'],
|
| 246 |
adapter_name=lora_name
|
| 247 |
)
|
| 248 |
+
|
| 249 |
+
logger.info(f" ✓ Local LoRA loaded")
|
| 250 |
|
| 251 |
# Устанавливаем scale
|
| 252 |
if hasattr(pipeline, 'set_adapters'):
|