PaulinaAa commited on
Commit
8f2ab11
·
verified ·
1 Parent(s): 1b06caa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -103
app.py CHANGED
@@ -1,55 +1,39 @@
1
- # -*- coding: utf-8 -*- # Dodajemy kodowanie na wszelki wypadek
2
 
3
  import gradio as gr
4
- # `requests` nie jest już bezpośrednio używany, ale może być przydatny w przyszłości
5
- # import requests
6
- from PIL import Image, ImageOps # Dodajemy ImageOps do skalowania
7
  import io
8
  import os
9
  import traceback
10
- # Poprawny import dla gradio_client
11
  from gradio_client import Client, file
12
- import uuid # Do unikalnych nazw folderów tymczasowych
13
- import shutil # Do usuwania folderów
14
- # Dodajemy obsługę wyjątków specyficznych dla gradio_client
15
  from gradio_client.exceptions import AppError
16
 
17
  print("--- Plik app.py - Start ładowania ---")
18
 
19
  # --- Konfiguracja ---
20
- # Odczytanie sekretu (API Token) ustawionego w Space
21
  API_TOKEN = os.getenv("HUGGINGFACE_API_TOKEN")
22
-
23
- # Sprawdzenie, czy token został załadowany
24
  if not API_TOKEN:
25
  print("!!! OSTRZEŻENIE: Nie znaleziono sekretu HUGGINGFACE_API_TOKEN. Klient Gradio spróbuje połączyć się anonimowo (mogą obowiązywać limity). !!!")
26
  else:
27
  print("--- Sekret HUGGINGFACE_API_TOKEN załadowany. ---")
28
 
29
- # Profesjonalny prompt, który chcemy uzyskać
30
  LINKEDIN_PROMPT = (
31
  "linkedin professional profile photo, corporate headshot, high quality, realistic photograph, "
32
- "person wearing a dark business suit or elegant blouse, plain white background, " # Usunięto potencjalnie problematyczne tagi man/woman
33
  "soft studio lighting, sharp focus, looking at camera, slight smile, natural skin texture"
34
  )
35
-
36
- # Identyfikator publicznego Space'a z InstantID dla gradio_client
37
  TARGET_SPACE_ID = "InstantX/InstantID"
38
-
39
- # Kontrolny print
40
  print(f"--- Konfiguracja załadowana. Cel dla gradio_client: {TARGET_SPACE_ID} ---")
41
 
42
 
43
  # --- Logika aplikacji ---
44
  def generate_photo(input_selfie, current_prompt):
45
- """
46
- Główna funkcja wywoływana po kliknięciu przycisku.
47
- Skaluje obraz wejściowy, łączy się ze zdalnym Space'em InstantID
48
- za pomocą gradio_client, wysyła dane, odbiera wynik i zwraca obrazek.
49
- """
50
  print("\n--- Funkcja generate_photo (gradio_client) została wywołana ---")
51
 
52
- # 1. Walidacja danych wejściowych
53
  if input_selfie is None:
54
  print("BŁĄD: Nie wgrano zdjęcia wejściowego.")
55
  raise gr.Error("Proszę najpierw wgrać swoje selfie!")
@@ -62,13 +46,11 @@ def generate_photo(input_selfie, current_prompt):
62
  print(f"Otrzymano obrazek typu: {type(input_selfie)}, Oryginalny rozmiar: {input_selfie.size}")
63
  print(f"Otrzymano prompt (początek): {current_prompt[:100]}...")
64
 
65
- # 2. Przeskalowanie obrazka wejściowego
66
- input_selfie_resized = None # Inicjalizacja
67
  try:
68
- max_size = (1024, 1024) # Maksymalny rozsądny rozmiar
69
- # Pracujemy na kopii, aby nie modyfikować oryginalnego obiektu
70
  input_selfie_resized = input_selfie.copy()
71
- # Używamy thumbnail do proporcjonalnego zmniejszenia, jeśli obraz jest większy niż max_size
72
  input_selfie_resized.thumbnail(max_size, Image.Resampling.LANCZOS)
73
  print(f"Obrazek przeskalowany do (maksymalnie) {max_size}. Nowy rozmiar: {input_selfie_resized.size}")
74
  except Exception as e_resize:
@@ -76,14 +58,12 @@ def generate_photo(input_selfie, current_prompt):
76
  traceback.print_exc()
77
  raise gr.Error(f"Nie można przeskalować obrazka wejściowego: {e_resize}")
78
 
79
- # 3. Przygotowanie pliku tymczasowego dla przeskalowanego obrazka
80
- temp_dir = f"temp_input_{uuid.uuid4()}" # Unikalny folder
81
- input_image_path = None # Ścieżka do pliku
82
  try:
83
  os.makedirs(temp_dir, exist_ok=True)
84
  input_image_path = os.path.join(temp_dir, "input_selfie.jpg")
85
-
86
- # Upewnijmy się, że przeskalowany obraz jest w RGB przed zapisem jako JPEG
87
  rgb_image = input_selfie_resized
88
  if rgb_image.mode == 'RGBA':
89
  print("Konwertuję przeskalowany obraz RGBA na RGB z białym tłem...")
@@ -93,37 +73,27 @@ def generate_photo(input_selfie, current_prompt):
93
  print(f"Konwertuję przeskalowany obraz z trybu {rgb_image.mode} na RGB...")
94
  final_image = rgb_image.convert('RGB')
95
  else:
96
- final_image = rgb_image # Już jest RGB
97
-
98
- # Zapisz finalny obraz jako JPEG
99
  final_image.save(input_image_path, format="JPEG")
100
  print(f"Przeskalowany obrazek wejściowy zapisany tymczasowo w: {input_image_path}")
101
-
102
  except Exception as e_save:
103
  print(f"BŁĄD podczas zapisywania obrazu tymczasowego: {e_save}")
104
  traceback.print_exc()
105
- # Spróbuj posprzątać, jeśli się da
106
  if os.path.exists(temp_dir):
107
- try:
108
- shutil.rmtree(temp_dir)
109
- print(f"Folder tymczasowy {temp_dir} usunięty po błędzie zapisu.")
110
- except Exception as e_clean:
111
- print(f"OSTRZEŻENIE: Nie udało się usunąć folderu tymczasowego {temp_dir} po błędzie zapisu: {e_clean}")
112
  raise gr.Error(f"Problem z przygotowaniem obrazu do wysłania: {e_save}")
113
 
114
- # 4. Wywołanie zdalnego API Gradio za pomocą gradio_client
115
- output_image = None # Zmienna na wynikowy obrazek PIL
116
- client = None # Zmienna na obiekt klienta
117
  try:
118
- # Używamy TARGET_SPACE_ID zdefiniowanej globalnie
119
  print(f"Łączenie z docelowym Space Gradio: {TARGET_SPACE_ID}")
120
- # Inicjalizacja klienta
121
  client = Client(TARGET_SPACE_ID, hf_token=API_TOKEN)
122
- print(f"Połączono. Adres API: {client.space_host}") # Pokaż faktyczny adres używany przez klienta
 
123
 
124
  print("Próbuję wywołać funkcję na zdalnym Space...")
125
-
126
- # Konfiguracja parametrów dla InstantX/InstantID
127
  negative_prompt = "ugly, deformed, noisy, blurry, low contrast, text, signature, watermark, duplicate, multiple people, cartoon, drawing, illustration, sketch, bad anatomy, worst quality, low quality"
128
  style_name = "Realistic"
129
  cn_scale = 0.8
@@ -138,31 +108,28 @@ def generate_photo(input_selfie, current_prompt):
138
  print(f" ControlNet Scale: {cn_scale}")
139
  print(f" IP-Adapter Scale: {ip_scale}")
140
 
141
- # Wywołanie funkcji 'predict' na zdalnym kliencie
142
- # Używamy file() do przesłania obrazka
143
- # UWAGA: file() jest przestarzałe, ale powinno jeszcze działać. W przyszłości może wymagać zmiany na handle_file().
144
  result = client.predict(
145
- file(input_image_path), # Obraz twarzy
146
- None, # Obraz pozy (opcjonalny)
147
- current_prompt, # Prompt
148
- negative_prompt, # Negatywny prompt
149
- style_name, # Styl
150
- cn_scale, # Skala ControlNet
151
- ip_scale, # Skala IP-Adapter (tożsamość)
152
- api_name=api_endpoint_name # Nazwa endpointu API
153
  )
154
 
155
- # Przetwarzanie wyniku
156
  print(f"Otrzymano wynik od klienta: {type(result)}")
157
- print(f"Wynik (fragment): {str(result)[:500]}") # Drukujemy fragment dla diagnostyki
158
 
159
- # Sprawdzamy, czy wynik jest listą ścieżek do plików
160
  if isinstance(result, list) and len(result) > 0 and isinstance(result[0], str) and os.path.exists(result[0]):
161
  output_file_path = result[0]
162
  print(f"Przetwarzam pierwszy obrazek wynikowy ze ścieżki: {output_file_path}")
163
  output_image = Image.open(output_file_path)
164
  print(f"Obrazek wynikowy załadowany pomyślnie. Rozmiar: {output_image.size}")
165
- # Sprawdzamy, czy wynik jest pojedynczą ścieżką
166
  elif isinstance(result, str) and os.path.exists(result):
167
  output_file_path = result
168
  print(f"Przetwarzam obrazek wynikowy ze ścieżki: {output_file_path}")
@@ -172,16 +139,12 @@ def generate_photo(input_selfie, current_prompt):
172
  print(f"BŁĄD: Otrzymano nieoczekiwany format wyniku od gradio_client: {type(result)}")
173
  raise gr.Error(f"Nie udało się przetworzyć wyniku ze zdalnego API. Otrzymano: {str(result)[:200]}")
174
 
175
- # --- Obsługa Błędów ---
176
  except AppError as e:
177
- # Błąd zgłoszony przez zdalną aplikację Gradio
178
  print(f"BŁĄD APLIKACJI ZDALNEJ (AppError): {e}")
179
  traceback.print_exc()
180
- # Bardziej pomocny komunikat dla użytkownika
181
  error_message = f"Zdalny serwis ({TARGET_SPACE_ID}) zgłosił wewnętrzny błąd. Może to być spowodowane problemami z obrazkiem (np. brak wykrytej twarzy, nietypowy format), niedostępnością modelu lub przeciążeniem serwisu. Spróbuj z innym, wyraźnym zdjęciem twarzy lub spróbuj ponownie później."
182
  raise gr.Error(error_message)
183
  except ValueError as e:
184
- # Potencjalnie błąd "Could not fetch config" lub inny ValueError
185
  print(f"BŁĄD WARTOŚCI (ValueError): {e}")
186
  traceback.print_exc()
187
  error_message = f"Wystąpił błąd wartości: {e}. "
@@ -189,7 +152,6 @@ def generate_photo(input_selfie, current_prompt):
189
  error_message = f"Nie można pobrać konfiguracji zdalnego serwisu ({TARGET_SPACE_ID}). Może być chwilowo niedostępny, niekompatybilny lub wymagać logowania. Sprawdź status serwisu lub spróbuj później."
190
  raise gr.Error(error_message)
191
  except Exception as e:
192
- # Inne, ogólne błędy (np. problem sieciowy, błąd w naszym kodzie)
193
  print(f"NIEOCZEKIWANY BŁĄD: {e}")
194
  traceback.print_exc()
195
  error_message = f"Wystąpił nieoczekiwany błąd: {e}. Sprawdź logi aplikacji."
@@ -198,25 +160,22 @@ def generate_photo(input_selfie, current_prompt):
198
  elif "queue full" in str(e).lower():
199
  error_message = "Kolejka w zdalnym serwisie jest pełna. Spróbuj ponownie za chwilę."
200
  raise gr.Error(error_message)
201
- # ------------------------
202
 
203
  finally:
204
- # 5. Sprzątanie - ZAWSZE próbuj usunąć folder tymczasowy
205
- if input_image_path and os.path.exists(temp_dir): # Sprawdź czy ścieżka istnieje
206
  try:
207
  shutil.rmtree(temp_dir)
208
  print(f"Folder tymczasowy {temp_dir} usunięty.")
209
  except Exception as e_clean:
210
  print(f"OSTRZEŻENIE: Nie udało się usunąć folderu tymczasowego {temp_dir}: {e_clean}")
211
 
212
- # 6. Zwróć wynik (załadowany obrazek PIL), jeśli wszystko się udało
213
  if output_image:
214
  print("Zwracam wygenerowany obrazek do interfejsu Gradio.")
215
  return output_image
216
  else:
217
- # Jeśli doszliśmy tutaj bez błędu, ale nie ma obrazka, to coś jest bardzo źle
218
  print("BŁĄD KRYTYCZNY: Brak obrazka wynikowego, a nie zgłoszono błędu.")
219
- # Zwróćmy błąd do UI, chociaż idealnie obsługa błędów powinna to wyłapać wcześniej
220
  raise gr.Error("Nie udało się uzyskać obrazka wynikowego z nieznanego powodu.")
221
 
222
 
@@ -233,40 +192,23 @@ with gr.Blocks(css="footer {display: none !important;}", title="Generator Zdję
233
  * Generowanie może potrwać **od 30 sekund do kilku minut** (zwłaszcza za pierwszym razem). Bądź cierpliwy!
234
  """
235
  )
236
-
237
  with gr.Row():
238
  with gr.Column(scale=1):
239
- input_image = gr.Image(
240
- label="1. Wgraj swoje selfie (JPG/PNG)",
241
- type="pil",
242
- # Określmy źródła dla bezpieczeństwa i wygody
243
- sources=["upload", "webcam"]
244
- )
245
- prompt_input = gr.Textbox(
246
- label="2. Opis pożądanego zdjęcia (prompt)",
247
- value=LINKEDIN_PROMPT,
248
- lines=4
249
- )
250
- generate_button = gr.Button("✨ Generuj Zdjęcie Biznesowe ✨", variant="primary", scale=1) # Przycisk rozciągnięty
251
-
252
  with gr.Column(scale=1):
253
- output_image = gr.Image(
254
- label="Oto Twoje wygenerowane zdjęcie:",
255
- type="pil"
256
- )
257
 
258
- # --- Podłączenie akcji do przycisku ---
259
  generate_button.click(
260
- fn=generate_photo, # Funkcja do wywołania
261
- inputs=[input_image, prompt_input], # Wejścia dla funkcji
262
- outputs=[output_image] # Gdzie umieścić wynik
263
  )
264
-
265
  print("--- Interfejs Gradio zdefiniowany ---")
266
 
267
  # --- Uruchomienie aplikacji ---
268
  if __name__ == "__main__":
269
  print("--- Uruchamianie demo.launch() ---")
270
- # Uruchamiamy aplikację Gradio w Space
271
- demo.launch() # Domyślnie share=False, debug=False w środowisku HF Spaces
272
- print("--- Aplikacja Gradio zakończyła działanie (jeśli serwer nie jest trwały) ---")
 
1
+ # -*- coding: utf-8 -*-
2
 
3
  import gradio as gr
4
+ # import requests # Nadal nieużywany bezpośrednio
5
+ from PIL import Image, ImageOps
 
6
  import io
7
  import os
8
  import traceback
 
9
  from gradio_client import Client, file
10
+ import uuid
11
+ import shutil
 
12
  from gradio_client.exceptions import AppError
13
 
14
  print("--- Plik app.py - Start ładowania ---")
15
 
16
  # --- Konfiguracja ---
 
17
  API_TOKEN = os.getenv("HUGGINGFACE_API_TOKEN")
 
 
18
  if not API_TOKEN:
19
  print("!!! OSTRZEŻENIE: Nie znaleziono sekretu HUGGINGFACE_API_TOKEN. Klient Gradio spróbuje połączyć się anonimowo (mogą obowiązywać limity). !!!")
20
  else:
21
  print("--- Sekret HUGGINGFACE_API_TOKEN załadowany. ---")
22
 
 
23
  LINKEDIN_PROMPT = (
24
  "linkedin professional profile photo, corporate headshot, high quality, realistic photograph, "
25
+ "person wearing a dark business suit or elegant blouse, plain white background, "
26
  "soft studio lighting, sharp focus, looking at camera, slight smile, natural skin texture"
27
  )
 
 
28
  TARGET_SPACE_ID = "InstantX/InstantID"
 
 
29
  print(f"--- Konfiguracja załadowana. Cel dla gradio_client: {TARGET_SPACE_ID} ---")
30
 
31
 
32
  # --- Logika aplikacji ---
33
  def generate_photo(input_selfie, current_prompt):
 
 
 
 
 
34
  print("\n--- Funkcja generate_photo (gradio_client) została wywołana ---")
35
 
36
+ # 1. Walidacja
37
  if input_selfie is None:
38
  print("BŁĄD: Nie wgrano zdjęcia wejściowego.")
39
  raise gr.Error("Proszę najpierw wgrać swoje selfie!")
 
46
  print(f"Otrzymano obrazek typu: {type(input_selfie)}, Oryginalny rozmiar: {input_selfie.size}")
47
  print(f"Otrzymano prompt (początek): {current_prompt[:100]}...")
48
 
49
+ # 2. Skalowanie obrazka
50
+ input_selfie_resized = None
51
  try:
52
+ max_size = (1024, 1024)
 
53
  input_selfie_resized = input_selfie.copy()
 
54
  input_selfie_resized.thumbnail(max_size, Image.Resampling.LANCZOS)
55
  print(f"Obrazek przeskalowany do (maksymalnie) {max_size}. Nowy rozmiar: {input_selfie_resized.size}")
56
  except Exception as e_resize:
 
58
  traceback.print_exc()
59
  raise gr.Error(f"Nie można przeskalować obrazka wejściowego: {e_resize}")
60
 
61
+ # 3. Przygotowanie pliku tymczasowego
62
+ temp_dir = f"temp_input_{uuid.uuid4()}"
63
+ input_image_path = None
64
  try:
65
  os.makedirs(temp_dir, exist_ok=True)
66
  input_image_path = os.path.join(temp_dir, "input_selfie.jpg")
 
 
67
  rgb_image = input_selfie_resized
68
  if rgb_image.mode == 'RGBA':
69
  print("Konwertuję przeskalowany obraz RGBA na RGB z białym tłem...")
 
73
  print(f"Konwertuję przeskalowany obraz z trybu {rgb_image.mode} na RGB...")
74
  final_image = rgb_image.convert('RGB')
75
  else:
76
+ final_image = rgb_image
 
 
77
  final_image.save(input_image_path, format="JPEG")
78
  print(f"Przeskalowany obrazek wejściowy zapisany tymczasowo w: {input_image_path}")
 
79
  except Exception as e_save:
80
  print(f"BŁĄD podczas zapisywania obrazu tymczasowego: {e_save}")
81
  traceback.print_exc()
 
82
  if os.path.exists(temp_dir):
83
+ try: shutil.rmtree(temp_dir)
84
+ except Exception as e_clean: print(f"OSTRZEŻENIE: Nie udało się usunąć {temp_dir}: {e_clean}")
 
 
 
85
  raise gr.Error(f"Problem z przygotowaniem obrazu do wysłania: {e_save}")
86
 
87
+ # 4. Wywołanie zdalnego API Gradio
88
+ output_image = None
89
+ client = None
90
  try:
 
91
  print(f"Łączenie z docelowym Space Gradio: {TARGET_SPACE_ID}")
 
92
  client = Client(TARGET_SPACE_ID, hf_token=API_TOKEN)
93
+ # Usunięto odwołanie do client.space_host, zastąpiono prostszym printem:
94
+ print(f"Połączono z {TARGET_SPACE_ID}. Klient zainicjalizowany.")
95
 
96
  print("Próbuję wywołać funkcję na zdalnym Space...")
 
 
97
  negative_prompt = "ugly, deformed, noisy, blurry, low contrast, text, signature, watermark, duplicate, multiple people, cartoon, drawing, illustration, sketch, bad anatomy, worst quality, low quality"
98
  style_name = "Realistic"
99
  cn_scale = 0.8
 
108
  print(f" ControlNet Scale: {cn_scale}")
109
  print(f" IP-Adapter Scale: {ip_scale}")
110
 
111
+ # UWAGA: file() jest przestarzałe. Jeśli pojawią się błędy, spróbuj Client(..., serialize=False)
112
+ # i przekazuj pełną ścieżkę jako string: input_image_path zamiast file(input_image_path)
113
+ # Ale na razie zostawiamy file()
114
  result = client.predict(
115
+ file(input_image_path),
116
+ None,
117
+ current_prompt,
118
+ negative_prompt,
119
+ style_name,
120
+ cn_scale,
121
+ ip_scale,
122
+ api_name=api_endpoint_name
123
  )
124
 
 
125
  print(f"Otrzymano wynik od klienta: {type(result)}")
126
+ print(f"Wynik (fragment): {str(result)[:500]}")
127
 
 
128
  if isinstance(result, list) and len(result) > 0 and isinstance(result[0], str) and os.path.exists(result[0]):
129
  output_file_path = result[0]
130
  print(f"Przetwarzam pierwszy obrazek wynikowy ze ścieżki: {output_file_path}")
131
  output_image = Image.open(output_file_path)
132
  print(f"Obrazek wynikowy załadowany pomyślnie. Rozmiar: {output_image.size}")
 
133
  elif isinstance(result, str) and os.path.exists(result):
134
  output_file_path = result
135
  print(f"Przetwarzam obrazek wynikowy ze ścieżki: {output_file_path}")
 
139
  print(f"BŁĄD: Otrzymano nieoczekiwany format wyniku od gradio_client: {type(result)}")
140
  raise gr.Error(f"Nie udało się przetworzyć wyniku ze zdalnego API. Otrzymano: {str(result)[:200]}")
141
 
 
142
  except AppError as e:
 
143
  print(f"BŁĄD APLIKACJI ZDALNEJ (AppError): {e}")
144
  traceback.print_exc()
 
145
  error_message = f"Zdalny serwis ({TARGET_SPACE_ID}) zgłosił wewnętrzny błąd. Może to być spowodowane problemami z obrazkiem (np. brak wykrytej twarzy, nietypowy format), niedostępnością modelu lub przeciążeniem serwisu. Spróbuj z innym, wyraźnym zdjęciem twarzy lub spróbuj ponownie później."
146
  raise gr.Error(error_message)
147
  except ValueError as e:
 
148
  print(f"BŁĄD WARTOŚCI (ValueError): {e}")
149
  traceback.print_exc()
150
  error_message = f"Wystąpił błąd wartości: {e}. "
 
152
  error_message = f"Nie można pobrać konfiguracji zdalnego serwisu ({TARGET_SPACE_ID}). Może być chwilowo niedostępny, niekompatybilny lub wymagać logowania. Sprawdź status serwisu lub spróbuj później."
153
  raise gr.Error(error_message)
154
  except Exception as e:
 
155
  print(f"NIEOCZEKIWANY BŁĄD: {e}")
156
  traceback.print_exc()
157
  error_message = f"Wystąpił nieoczekiwany błąd: {e}. Sprawdź logi aplikacji."
 
160
  elif "queue full" in str(e).lower():
161
  error_message = "Kolejka w zdalnym serwisie jest pełna. Spróbuj ponownie za chwilę."
162
  raise gr.Error(error_message)
 
163
 
164
  finally:
165
+ # 5. Sprzątanie
166
+ if input_image_path and os.path.exists(temp_dir):
167
  try:
168
  shutil.rmtree(temp_dir)
169
  print(f"Folder tymczasowy {temp_dir} usunięty.")
170
  except Exception as e_clean:
171
  print(f"OSTRZEŻENIE: Nie udało się usunąć folderu tymczasowego {temp_dir}: {e_clean}")
172
 
173
+ # 6. Zwróć wynik
174
  if output_image:
175
  print("Zwracam wygenerowany obrazek do interfejsu Gradio.")
176
  return output_image
177
  else:
 
178
  print("BŁĄD KRYTYCZNY: Brak obrazka wynikowego, a nie zgłoszono błędu.")
 
179
  raise gr.Error("Nie udało się uzyskać obrazka wynikowego z nieznanego powodu.")
180
 
181
 
 
192
  * Generowanie może potrwać **od 30 sekund do kilku minut** (zwłaszcza za pierwszym razem). Bądź cierpliwy!
193
  """
194
  )
 
195
  with gr.Row():
196
  with gr.Column(scale=1):
197
+ input_image = gr.Image(label="1. Wgraj swoje selfie (JPG/PNG)", type="pil", sources=["upload", "webcam"])
198
+ prompt_input = gr.Textbox(label="2. Opis pożądanego zdjęcia (prompt)", value=LINKEDIN_PROMPT, lines=4)
199
+ generate_button = gr.Button("✨ Generuj Zdjęcie Biznesowe ✨", variant="primary", scale=1)
 
 
 
 
 
 
 
 
 
 
200
  with gr.Column(scale=1):
201
+ output_image = gr.Image(label="Oto Twoje wygenerowane zdjęcie:", type="pil")
 
 
 
202
 
 
203
  generate_button.click(
204
+ fn=generate_photo,
205
+ inputs=[input_image, prompt_input],
206
+ outputs=[output_image]
207
  )
 
208
  print("--- Interfejs Gradio zdefiniowany ---")
209
 
210
  # --- Uruchomienie aplikacji ---
211
  if __name__ == "__main__":
212
  print("--- Uruchamianie demo.launch() ---")
213
+ demo.launch()
214
+ print("--- Aplikacja Gradio zakończyła działanie ---")