Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import requests # Dodajemy od razu, bo będzie potrzebny
|
3 |
+
from PIL import Image # Dodajemy od razu
|
4 |
+
import io # Dodajemy od razu
|
5 |
+
import os # Do odczytu sekretu
|
6 |
+
import traceback # Do lepszego śledzenia błędów
|
7 |
+
|
8 |
+
print("--- Plik app.py - Start ładowania ---")
|
9 |
+
|
10 |
+
# --- Konfiguracja ---
|
11 |
+
# Odczytanie sekretu (API Token) ustawionego w Space
|
12 |
+
# PAMIĘTAJ, ABY DODAĆ TEN SEKRET W USTAWIENIACH SPACE'A!
|
13 |
+
# Settings -> Repository secrets -> New secret
|
14 |
+
# Name: HUGGINGFACE_API_TOKEN
|
15 |
+
# Value: <twój skopiowany token API>
|
16 |
+
API_TOKEN = os.getenv("HUGGINGFACE_API_TOKEN")
|
17 |
+
|
18 |
+
# Sprawdzenie, czy token został załadowany
|
19 |
+
if not API_TOKEN:
|
20 |
+
print("!!! OSTRZEŻENIE: Nie znaleziono sekretu HUGGINGFACE_API_TOKEN !!!")
|
21 |
+
# Można tu rzucić błąd, ale na razie tylko ostrzegamy
|
22 |
+
# raise ValueError("Nie ustawiono sekretu HUGGINGFACE_API_TOKEN w ustawieniach Space!")
|
23 |
+
|
24 |
+
# Endpoint modelu InstantID na Hugging Face Inference API
|
25 |
+
API_URL = "https://api-inference.huggingface.co/models/Sxela/instant-id"
|
26 |
+
|
27 |
+
# Profesjonalny prompt, który chcemy uzyskać
|
28 |
+
# Możesz go później dostosować
|
29 |
+
LINKEDIN_PROMPT = (
|
30 |
+
"linkedin professional profile photo, corporate headshot, high quality, realistic photograph, "
|
31 |
+
"man/woman [choose one or remove] wearing a dark business suit or elegant blouse, plain white background, "
|
32 |
+
"soft studio lighting, sharp focus, looking at camera, slight smile, natural skin texture"
|
33 |
+
)
|
34 |
+
# Uwaga: InstantID może nie być idealny w zmianie ubrań, skupia się na twarzy.
|
35 |
+
# Prompt pomaga nadać ogólny styl.
|
36 |
+
|
37 |
+
# --- Logika aplikacji ---
|
38 |
+
# Na razie pusta funkcja, którą podłączymy do przycisku
|
39 |
+
def generate_photo(input_selfie):
|
40 |
+
print("\n--- Funkcja generate_photo została wywołana ---")
|
41 |
+
if input_selfie is None:
|
42 |
+
print("Błąd: Nie wgrano zdjęcia wejściowego.")
|
43 |
+
raise gr.Error("Proszę najpierw wgrać swoje selfie!") # Pokaż błąd w UI
|
44 |
+
|
45 |
+
print(f"Otrzymano obrazek typu: {type(input_selfie)}")
|
46 |
+
|
47 |
+
# --- Tutaj dodamy logikę wywołania API (w kolejnym kroku) ---
|
48 |
+
print("Symulacja generowania - na razie zwracam placeholder.")
|
49 |
+
|
50 |
+
# Na razie zwróćmy tekst, aby sprawdzić przepływ
|
51 |
+
# return "Generowanie w toku... (jeszcze nie zaimplementowane)"
|
52 |
+
|
53 |
+
# Lub spróbujmy zwrócić pusty obrazek lub None (jeśli output to gr.Image)
|
54 |
+
# return None
|
55 |
+
|
56 |
+
# Zwrócmy oryginalne selfie, żeby zobaczyć czy działa przekazanie
|
57 |
+
return input_selfie
|
58 |
+
|
59 |
+
|
60 |
+
# --- Budowa Interfejsu Gradio ---
|
61 |
+
print("--- Definiowanie interfejsu Gradio ---")
|
62 |
+
with gr.Blocks(css="footer {display: none !important}") as demo: # Ukrywamy domyślny footer Gradio
|
63 |
+
gr.Markdown(
|
64 |
+
"""
|
65 |
+
# Generator Profesjonalnych Zdjęć Profilowych
|
66 |
+
Wgraj swoje selfie, a my postaramy się stworzyć profesjonalne zdjęcie w stylu LinkedIn!
|
67 |
+
**Ważne:** Najlepsze efekty uzyskasz wgrywając wyraźne zdjęcie twarzy, patrzącej w miarę prosto, dobrze oświetlonej.
|
68 |
+
"""
|
69 |
+
)
|
70 |
+
|
71 |
+
with gr.Row():
|
72 |
+
with gr.Column(scale=1):
|
73 |
+
input_image = gr.Image(
|
74 |
+
label="1. Wgraj swoje selfie (JPG/PNG)",
|
75 |
+
type="pil" # Chcemy obiekt PIL w funkcji Pythona
|
76 |
+
)
|
77 |
+
prompt_input = gr.Textbox( # Dodajemy pole na prompt, z domyślną wartością
|
78 |
+
label="Opcjonalnie: Dostosuj opis zdjęcia (prompt)",
|
79 |
+
value=LINKEDIN_PROMPT,
|
80 |
+
lines=4
|
81 |
+
)
|
82 |
+
generate_button = gr.Button("✨ Generuj Zdjęcie Biznesowe ✨", variant="primary")
|
83 |
+
|
84 |
+
with gr.Column(scale=1):
|
85 |
+
output_image = gr.Image(
|
86 |
+
label="Oto Twoje wygenerowane zdjęcie:",
|
87 |
+
type="pil" # Oczekujemy obiektu PIL jako wynik
|
88 |
+
)
|
89 |
+
# Można dodać informację o stanie
|
90 |
+
status_info = gr.Textbox(label="Status", interactive=False)
|
91 |
+
|
92 |
+
# --- Podłączenie akcji do przycisku ---
|
93 |
+
# Kiedy przycisk zostanie kliknięty, wywołaj funkcję 'generate_photo'
|
94 |
+
# Przekaż zawartość 'input_image' jako argument do funkcji
|
95 |
+
# Wynik funkcji umieść w komponencie 'output_image'
|
96 |
+
generate_button.click(
|
97 |
+
fn=generate_photo,
|
98 |
+
inputs=[input_image], # Lista komponentów wejściowych
|
99 |
+
outputs=[output_image] # Lista komponentów wyjściowych (na razie jeden)
|
100 |
+
# inputs=[input_image, prompt_input], # Jeśli chcemy przekazać też prompt
|
101 |
+
# outputs=[output_image, status_info] # Jeśli chcemy aktualizować też status
|
102 |
+
)
|
103 |
+
|
104 |
+
print("--- Interfejs Gradio zdefiniowany ---")
|
105 |
+
|
106 |
+
# --- Uruchomienie aplikacji ---
|
107 |
+
if __name__ == "__main__":
|
108 |
+
print("--- Uruchamianie demo.launch() ---")
|
109 |
+
demo.launch() # Uruchamia aplikację Gradio
|
110 |
+
print("--- demo.launch() zakończone (?) ---") # Ten print może się nie pojawić od razu w logach
|