Superigni commited on
Commit
59ec49b
·
verified ·
1 Parent(s): 136d95f

fix path model

Browse files
Files changed (1) hide show
  1. app.py +74 -47
app.py CHANGED
@@ -3,7 +3,6 @@ import gradio as gr
3
  import torch
4
  import requests
5
  from PIL import Image
6
- from io import BytesIO
7
  import numpy as np
8
  import os
9
  from tqdm import tqdm # Добавляем импорт tqdm
@@ -30,11 +29,22 @@ def download_file(url, local_filename):
30
  total_size_in_bytes = int(response.headers.get('content-length', 0))
31
  block_size = 8192 # 8 Kibibytes
32
 
33
- with tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True, desc=f"Скачивание {local_filename}") as progress_bar:
34
- with open(local_filename, 'wb') as f:
35
- for chunk in response.iter_content(chunk_size=block_size):
 
 
 
 
 
 
 
 
36
  progress_bar.update(len(chunk))
37
- f.write(chunk)
 
 
 
38
 
39
  print(f"Скачивание завершено: {local_filename}")
40
  return local_filename
@@ -55,36 +65,41 @@ LOCAL_SAFETENSOR_FILENAME = "ultrareal_fine_tune_fp8_full.safetensors"
55
  # ControlNet модель с Hugging Face
56
  CONTROLNET_MODEL_ID = "ABDALLALSWAITI/FLUX.1-dev-ControlNet-Union-Pro-2.0-fp8"
57
 
 
 
 
 
58
  # --- Скачиваем SafeTensor модель (выполнится при запуске скрипта в Space) ---
59
  print("Начинаю скачивание базовой модели...")
60
  downloaded_base_model_path = download_file(CIVITAI_SAFETENSOR_URL, LOCAL_SAFETENSOR_FILENAME)
61
 
62
- if not downloaded_base_model_path or not os.path.exists(downloaded_base_model_path):
63
- # Если скачивание не удалось или файл не существует после попытки
64
- print(f"Критическая ошибка: Не удалось получить файл базовой модели по пути: {LOCAL_SAFETENSOR_FILENAME}")
65
- print("Проверьте логи Space на наличие ошибок скачивания.")
66
- # Возможно, здесь стоит выбросить исключение или как-то иначе остановить приложение
67
- # Для примера, просто присвоим None и приложение не сможет загрузить пайплайн
68
- pipeline = None
69
- else:
70
- # --- Загрузка моделей и создание пайплайна ---
71
- def load_pipeline_components(base_model_path, controlnet_model_id):
72
- """Загружает базовую модель из локального файла, ControlNet и собирает пайплайн."""
73
- print(f"Загрузка ControlNet модели: {controlnet_model_id}")
74
- # Загрузка ControlNet с Hugging Face Hub - кешируется автоматически Space
75
  controlnet = ControlNetModel.from_pretrained(controlnet_model_id, torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32)
 
 
 
 
76
 
77
- print(f"Загрузка базовой модели из локального файла: {base_model_path} с использованием from_single_file")
78
  # Используем from_single_file для загрузки пайплайна из одного SafeTensor файла
79
- # Этот метод специально предназначен для загрузки чекпойнтов (Safetensors/CKPT)
80
  try:
81
  pipe = StableDiffusionPipeline.from_single_file(
82
  base_model_path, # Указываем путь к локальному файлу .safetensors
83
  torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
84
- # from_single_file часто пытается загрузить необходимую конфигурацию
85
- # (tokenizer, scheduler, VAE) из стандартных источников или default config.
86
- # Если у вас очень нестандартная модель, может потребоваться указать config_files=...
87
- # Но для большинства SD 1.5/2.x моделей from_single_file работает хорошо.
88
  )
89
  # Отключение safety checker после загрузки, если он был загружен
90
  if hasattr(pipe, 'safety_checker') and pipe.safety_checker is not None:
@@ -94,14 +109,13 @@ else:
94
 
95
  except Exception as e:
96
  print(f"Ошибка при загрузке базовой модели из файла {base_model_path}: {e}")
97
- print("Убедитесь, что файл не поврежден и соответствует формату StableDiffusion.")
98
- # Важно: Если загрузка базовой модели не удалась, мы не можем продолжить.
99
- # Возвращаем None или выбрасываем исключение.
100
- return None # Возвращаем None, чтобы функция generate_image_gradio могла проверить это.
101
-
102
- # Теперь объединяем базовый пайплайн с ControlNet
103
- # Создаем StableDiffusionControlNetPipeline на основе загруженного базового пайплайна
104
- print("Создание пайплайна StableDiffusionControlNetPipeline...")
105
  controlnet_pipe = StableDiffusionControlNetPipeline(
106
  vae=pipe.vae,
107
  text_encoder=pipe.text_encoder,
@@ -109,7 +123,7 @@ else:
109
  unet=pipe.unet,
110
  controlnet=controlnet, # Передаем загруженный ControlNet
111
  scheduler=pipe.scheduler, # Используем планировщик из базового пайплайна
112
- safety_checker=None,
113
  feature_extractor=pipe.feature_extractor
114
  )
115
 
@@ -117,22 +131,35 @@ else:
117
  # Обновляем планировщик в новом ControlNet пайплайне
118
  controlnet_pipe.scheduler = UniPCMultistepScheduler.from_config(controlnet_pipe.scheduler.config)
119
 
120
- # Удаляем старый базовый пайплайн для освобождения памяти
121
  del pipe
122
  if torch.cuda.is_available():
123
  torch.cuda.empty_cache()
 
 
124
 
125
  # Перемещ��ем ControlNet пайплайн на GPU, если доступно
126
  if torch.cuda.is_available():
127
  controlnet_pipe = controlnet_pipe.to("cuda")
128
- print("Пайплайн перемещен на GPU.")
129
  else:
130
- print("GPU не найдено. Пайплайн будет работать на CPU (будет медленно).") # В Space на CPU работать не будет эффективно
131
 
132
- return controlnet_pipe
133
 
134
- # Загружаем пайплайн при запуске скрипта, только если файл модели успешно скачан
 
 
 
 
 
 
 
 
135
  pipeline = load_pipeline_components(downloaded_base_model_path, CONTROLNET_MODEL_ID)
 
 
 
136
 
137
 
138
  # --- Функция рендеринга для Gradio ---
@@ -145,6 +172,7 @@ def generate_image_gradio(controlnet_image: np.ndarray, prompt: str, negative_pr
145
  """
146
  # Проверяем, успешно ли загрузился пайплайн
147
  if pipeline is None:
 
148
  return None, "Ошибка: Пайплайн модели не загружен. Проверьте логи Space."
149
 
150
  if controlnet_image is None:
@@ -154,10 +182,13 @@ def generate_image_gradio(controlnet_image: np.ndarray, prompt: str, negative_pr
154
  print(f"Размер входного изображения: {controlnet_image.shape}")
155
 
156
  # Gradio возвращает изображение как numpy array. Преобразуем в PIL Image для пайплайна.
 
157
  input_image_pil = Image.fromarray(controlnet_image).convert("RGB")
158
 
159
  # Выполняем рендеринг с помощью пайплайна
160
  try:
 
 
161
  output = pipeline(
162
  prompt=prompt,
163
  image=input_image_pil, # Входное изображение для ControlNet
@@ -165,7 +196,6 @@ def generate_image_gradio(controlnet_image: np.ndarray, prompt: str, negative_pr
165
  guidance_scale=guidance_scale,
166
  num_inference_steps=num_inference_steps,
167
  controlnet_conditioning_scale=controlnet_conditioning_scale
168
- # Здесь можно добавить generator=... (для сидов), width=..., height=..., etc.
169
  )
170
 
171
  # Результат находится в output.images[0]
@@ -175,6 +205,7 @@ def generate_image_gradio(controlnet_image: np.ndarray, prompt: str, negative_pr
175
  return generated_image_pil, "Успех!"
176
  except Exception as e:
177
  print(f"Ошибка при генерации: {e}")
 
178
  return None, f"Ошибка при генерации: {e}"
179
 
180
 
@@ -193,7 +224,7 @@ status_text_comp = gr.Textbox(label="Статус")
193
 
194
  # Создаем интерфейс Gradio
195
  # Поскольку мы в Space, Gradio SDK сам вызовет interface.launch()
196
- # Нам просто нужно определить интерфейс
197
  interface = gr.Interface(
198
  fn=generate_image_gradio,
199
  inputs=[
@@ -205,13 +236,9 @@ interface = gr.Interface(
205
  controlnet_conditioning_scale_comp
206
  ],
207
  outputs=[output_image_comp, status_text_comp],
208
- title="Stable Diffusion ControlNet Interface (SafeTensor Base Model)",
209
  description="Загрузите изображение для ControlNet, введите промт и нажмите 'Generate'. Используется локальная SafeTensor модель и ControlNet с Hugging Face."
210
  )
211
 
212
- # Важно: Не вызывайте interface.launch() в блоке if __name__ == "__main__":
213
- # Gradio SDK в Space сделает это автоматически.
214
- # Если вы оставите if __name__ == "__main__": interface.launch(), оно тоже будет работать,
215
- # но в среде Space это менее критично, чем при локальном запуске.
216
- # Для ясности в Space можно убрать блок if __name__ == "__main__":
217
- # Я оставил его в коде выше, но знайте, что SDK вызовет interface.launch() независимо от него.
 
3
  import torch
4
  import requests
5
  from PIL import Image
 
6
  import numpy as np
7
  import os
8
  from tqdm import tqdm # Добавляем импорт tqdm
 
29
  total_size_in_bytes = int(response.headers.get('content-length', 0))
30
  block_size = 8192 # 8 Kibibytes
31
 
32
+ # Используем tqdm для индикатора прогресса, только если размер известен
33
+ if total_size_in_bytes > 0:
34
+ progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True, desc=f"Скачивание {local_filename}")
35
+ else:
36
+ print("Размер файла неизвестен, скачивание без индикатора прогресса.")
37
+ progress_bar = None
38
+
39
+
40
+ with open(local_filename, 'wb') as f:
41
+ for chunk in response.iter_content(chunk_size=block_size):
42
+ if progress_bar:
43
  progress_bar.update(len(chunk))
44
+ f.write(chunk)
45
+
46
+ if progress_bar:
47
+ progress_bar.close()
48
 
49
  print(f"Скачивание завершено: {local_filename}")
50
  return local_filename
 
65
  # ControlNet модель с Hugging Face
66
  CONTROLNET_MODEL_ID = "ABDALLALSWAITI/FLUX.1-dev-ControlNet-Union-Pro-2.0-fp8"
67
 
68
+ # Переменная для хранения пайплайна (будет загружен при запуске скрипта)
69
+ pipeline = None
70
+ downloaded_base_model_path = None # Переменная для пути к скачанному файлу
71
+
72
  # --- Скачиваем SafeTensor модель (выполнится при запуске скрипта в Space) ---
73
  print("Начинаю скачивание базовой модели...")
74
  downloaded_base_model_path = download_file(CIVITAI_SAFETENSOR_URL, LOCAL_SAFETENSOR_FILENAME)
75
 
76
+ # --- Загрузка моделей и создание пайплайна ---
77
+ # Эта функция вызывается один раз при запуске скрипта
78
+ def load_pipeline_components(base_model_path, controlnet_model_id):
79
+ """Загружает базовую модель из локального файла, ControlNet и собирает пайплайн."""
80
+ if not base_model_path or not os.path.exists(base_model_path):
81
+ print(f"Ошибка загрузки: Файл базовой модели не найден по пути: {base_model_path}")
82
+ return None # Не можем загрузить пайплайн без файла модели
83
+
84
+ print(f"Загрузка ControlNet модели: {controlnet_model_id}")
85
+ # Загрузка ControlNet с Hugging Face Hub - кешируется автоматически Space
86
+ try:
 
 
87
  controlnet = ControlNetModel.from_pretrained(controlnet_model_id, torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32)
88
+ except Exception as e:
89
+ print(f"Ошибка загрузки ControlNet модели с HF Hub: {controlnet_model_id}. Проверьте ID или соединение.")
90
+ print(f"Ошибка: {e}")
91
+ return None # Не можем загрузить пайплайн без ControlNet
92
 
93
+ print(f"Загрузка базовой модели из локального файла: {base_model_path} с использованием from_single_file")
94
  # Используем from_single_file для загрузки пайплайна из одного SafeTensor файла
 
95
  try:
96
  pipe = StableDiffusionPipeline.from_single_file(
97
  base_model_path, # Указываем путь к локальному файлу .safetensors
98
  torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
99
+ # from_single_file пытается найти конфигурацию VAE, tokenizer и scheduler.
100
+ # Если ваша модель требует специфической конфигурации, возможно,
101
+ # потребуется указать путь к папке с конфигом или загрузить их отдельно.
102
+ # Для большинства Safetensor SD 1.5/2.x from_single_file работает из коробки.
103
  )
104
  # Отключение safety checker после загрузки, если он был загружен
105
  if hasattr(pipe, 'safety_checker') and pipe.safety_checker is not None:
 
109
 
110
  except Exception as e:
111
  print(f"Ошибка при загрузке базовой модели из файла {base_model_path}: {e}")
112
+ print("Убедитесь, что файл не поврежден, соответствует формату StableDiffusion и from_single_file может его обработать.")
113
+ return None # Возвращаем None, если загрузка базовой модели не удалась
114
+
115
+ # --- Создание пайплайна StableDiffusionControlNetPipeline из компонентов ---
116
+ # Этот блок выполняется ТОЛЬКО если базовая модель и ControlNet успешно загружены
117
+ print("Создание финального пайплайна StableDiffusionControlNetPipeline...")
118
+ try:
 
119
  controlnet_pipe = StableDiffusionControlNetPipeline(
120
  vae=pipe.vae,
121
  text_encoder=pipe.text_encoder,
 
123
  unet=pipe.unet,
124
  controlnet=controlnet, # Передаем загруженный ControlNet
125
  scheduler=pipe.scheduler, # Используем планировщик из базового пайплайна
126
+ safety_checker=None, # Убираем safety_checker здесь при создании нового пайплайна
127
  feature_extractor=pipe.feature_extractor
128
  )
129
 
 
131
  # Обновляем планировщик в новом ControlNet пайплайне
132
  controlnet_pipe.scheduler = UniPCMultistepScheduler.from_config(controlnet_pipe.scheduler.config)
133
 
134
+ # Удаляем старый объект пайплайна для освобождения памяти GPU
135
  del pipe
136
  if torch.cuda.is_available():
137
  torch.cuda.empty_cache()
138
+ print("Память GPU очищена после создания ControlNet пайплайна.")
139
+
140
 
141
  # Перемещ��ем ControlNet пайплайн на GPU, если доступно
142
  if torch.cuda.is_available():
143
  controlnet_pipe = controlnet_pipe.to("cuda")
144
+ print("Финальный пайплайн перемещен на GPU.")
145
  else:
146
+ print("GPU не найдено. Пайплайн будет работать на CPU (крайне медленно).") # В Space на CPU работать не будет эффективно
147
 
148
+ return controlnet_pipe # Возвращаем готовый пайплайн
149
 
150
+ except Exception as e:
151
+ print(f"Ошибка при создании финального StableDiffusionControlNetPipeline: {e}")
152
+ print("Проверьте совместимость компонентов (базовая модель и ControlNet).")
153
+ return None # Возвращаем None, если собрать финальный пайплайн не удалось
154
+
155
+
156
+ # --- Загружаем пайплайн при запуске скрипта, только если файл модели успешно скачан ---
157
+ # Этот код выполняется после скачивания файла
158
+ if downloaded_base_model_path and os.path.exists(downloaded_base_model_path):
159
  pipeline = load_pipeline_components(downloaded_base_model_path, CONTROLNET_MODEL_ID)
160
+ else:
161
+ print("Пропуск загрузки пайплайна из-за ошибки скачивания или отсутствия файла.")
162
+ pipeline = None # Убеждаемся, что pipeline равен None при ошибке
163
 
164
 
165
  # --- Функция рендеринга для Gradio ---
 
172
  """
173
  # Проверяем, успешно ли загрузился пайплайн
174
  if pipeline is None:
175
+ print("Попытка генерации, но пайплайн модели не загружен.")
176
  return None, "Ошибка: Пайплайн модели не загружен. Проверьте логи Space."
177
 
178
  if controlnet_image is None:
 
182
  print(f"Размер входного изображения: {controlnet_image.shape}")
183
 
184
  # Gradio возвращает изображение как numpy array. Преобразуем в PIL Image для пайплайна.
185
+ # diffusers ControlNet ожидают изображение в формате PIL Image или PyTorch Tensor в RGB
186
  input_image_pil = Image.fromarray(controlnet_image).convert("RGB")
187
 
188
  # Выполняем рендеринг с помощью пайплайна
189
  try:
190
+ # Здесь вы можете добавить generator=... (для сидов), width=..., height=..., etc.
191
+ # Передаем все параметры в вызов пайплайна
192
  output = pipeline(
193
  prompt=prompt,
194
  image=input_image_pil, # Входное изображение для ControlNet
 
196
  guidance_scale=guidance_scale,
197
  num_inference_steps=num_inference_steps,
198
  controlnet_conditioning_scale=controlnet_conditioning_scale
 
199
  )
200
 
201
  # Результат находится в output.images[0]
 
205
  return generated_image_pil, "Успех!"
206
  except Exception as e:
207
  print(f"Ошибка при генерации: {e}")
208
+ # Возвращаем None и сообщение об ошибке в интерфейс Gradio
209
  return None, f"Ошибка при генерации: {e}"
210
 
211
 
 
224
 
225
  # Создаем интерфейс Gradio
226
  # Поскольку мы в Space, Gradio SDK сам вызовет interface.launch()
227
+ # Нам просто нужно определить объект интерфейса
228
  interface = gr.Interface(
229
  fn=generate_image_gradio,
230
  inputs=[
 
236
  controlnet_conditioning_scale_comp
237
  ],
238
  outputs=[output_image_comp, status_text_comp],
239
+ title="Stable Diffusion ControlNet Interface (SafeTensor Base Model on HF Space)",
240
  description="Загрузите изображение для ControlNet, введите промт и нажмите 'Generate'. Используется локальная SafeTensor модель и ControlNet с Hugging Face."
241
  )
242
 
243
+ # Нет необходимости вызывать interface.launch() в блоке if __name__ == "__main__":
244
+ # Gradio SDK в Space сделает это автоматически при запуске скрипта.