Zhofang commited on
Commit
6100c3e
·
verified ·
1 Parent(s): 0f559ef

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -121
app.py CHANGED
@@ -6,112 +6,79 @@ import os
6
  from PIL import Image
7
  from deep_translator import GoogleTranslator
8
 
9
- # os.makedirs('assets', exist_ok=True) # Tidak terlalu dibutuhkan jika icon.jpg ada di root
10
  if not os.path.exists('icon.jpg'):
11
- print("Downloading icon.jpg...")
12
  os.system("wget -O icon.jpg https://i.pinimg.com/564x/64/49/88/644988c59447eb00286834c2e70fdd6b.jpg")
13
- print("Icon downloaded.")
14
-
15
- API_URL_DEV = "https://lol-v2.mxflower.eu.org/api-inference.huggingface.co/models/black-forest-labs/FLUX.1-dev"
16
- API_URL = "https://lol-v2.mxflower.eu.org/api-inference.huggingface.co/models/black-forest-labs/FLUX.1-schnell"
17
  timeout = 100
18
 
19
- def query(prompt, negative_prompt_str, steps=30, cfg_scale=7, sampler="DPM++ 2M Karras", seed=-1, strength=0.7, huggingface_api_key_ui=None, use_dev=False):
20
  # Determine which API URL to use
21
  api_url = API_URL_DEV if use_dev else API_URL
22
 
23
- # Determine the API token to use
24
- api_token_to_use = None
25
- if huggingface_api_key_ui and huggingface_api_key_ui.strip(): # Cek apakah UI key diisi dan bukan hanya spasi
26
- api_token_to_use = huggingface_api_key_ui.strip()
27
- print("Using API key from UI input.")
28
- else:
29
- env_token = os.getenv("HF_READ_TOKEN")
30
- if env_token and env_token.strip(): # Cek apakah environment variable ada dan bukan hanya spasi
31
- api_token_to_use = env_token.strip()
32
- print("Using API key from HF_READ_TOKEN environment variable.")
33
-
34
- if not api_token_to_use:
35
- raise gr.Error("Hugging Face API Key is required. Please provide it in the UI (Advanced Settings -> Hugging Face API Key) or set the HF_READ_TOKEN environment variable.")
36
 
37
- headers = {"Authorization": f"Bearer {api_token_to_use}"}
 
 
 
 
 
 
 
 
38
 
39
- if not prompt or prompt.strip() == "":
40
- # Anda bisa mengembalikan gambar placeholder atau pesan error
41
- # Untuk saat ini, kita kembalikan None, Gradio mungkin akan menampilkan error atau kosong
42
- gr.Warning("Prompt cannot be empty.")
43
- return None, seed # Atau raise gr.Error("Prompt cannot be empty.")
44
 
45
  key = random.randint(0, 999)
46
 
47
- # Terjemahkan prompt
48
- try:
49
- translated_prompt = GoogleTranslator(source='auto', target='en').translate(prompt) # 'auto' lebih fleksibel
50
- except Exception as e:
51
- print(f"Error translating prompt: {e}. Using original prompt.")
52
- translated_prompt = prompt # Fallback ke prompt asli jika translasi gagal
53
-
54
- print(f'\033[1mGeneration {key} translation:\033[0m {translated_prompt}')
55
 
56
- # Tambahkan detail ke prompt
57
- final_prompt = f"{translated_prompt} | ultra detail, ultra elaboration, ultra quality, perfect."
58
- print(f'\033[1mGeneration {key}:\033[0m {final_prompt}')
59
 
60
- # Jika seed adalah -1, generate seed acak
61
  if seed == -1:
62
  seed = random.randint(1, 1000000000)
63
 
64
  payload = {
65
- "inputs": final_prompt,
 
66
  "steps": steps,
67
  "cfg_scale": cfg_scale,
68
  "seed": seed,
69
- "strength": strength,
70
- "sampler": sampler # Menambahkan sampler ke payload
71
  }
72
 
73
- # Logika untuk negative prompt:
74
- # API Anda (lol-v2.mxflower.eu.org) sepertinya mengharapkan string negative prompt
75
- # dikirim melalui field "is_negative" berdasarkan kode asli Anda.
76
- # Jika API sebenarnya mengharapkan boolean untuk "is_negative" dan string di field lain (mis. "negative_prompt"),
77
- # ini perlu disesuaikan.
78
- # Untuk saat ini, saya mengikuti struktur asli dimana string negative_prompt_str dikirim sebagai "is_negative".
79
- if negative_prompt_str and negative_prompt_str.strip():
80
- payload["is_negative"] = negative_prompt_str.strip()
81
- # Jika tidak, kita tidak mengirim field "is_negative" sama sekali jika API lebih suka begitu
82
- # atau payload["is_negative"] = "" (tergantung preferensi API)
83
-
84
- print(f"Payload to API: {payload}")
85
-
86
  response = requests.post(api_url, headers=headers, json=payload, timeout=timeout)
87
  if response.status_code != 200:
88
  print(f"Error: Failed to get image. Response status: {response.status_code}")
89
  print(f"Response content: {response.text}")
90
  if response.status_code == 503:
91
- raise gr.Error(f"{response.status_code} : The model is being loaded or is unavailable. Details: {response.text[:500]}")
92
- raise gr.Error(f"API Error {response.status_code}: {response.text[:500]}")
93
 
94
  try:
95
  image_bytes = response.content
96
  image = Image.open(io.BytesIO(image_bytes))
97
- print(f'\033[1mGeneration {key} completed!\033[0m ({final_prompt})')
98
 
99
- # Simpan gambar ke file dan kembalikan path file dan seed
100
- # Pastikan direktori output ada jika Anda mau menyimpannya di subdirektori
101
- # os.makedirs('outputs', exist_ok=True)
102
- # output_path = f"./outputs/output_{key}.png"
103
- output_path = f"./output_{key}.png" # Simpan di root untuk kesederhanaan
104
  image.save(output_path)
105
 
106
  return output_path, seed
107
  except Exception as e:
108
- print(f"Error when trying to open or save the image: {e}")
109
- print(f"Response content that caused error: {response.content[:200]}") # Tampilkan sebagian konten jika bukan gambar
110
- raise gr.Error(f"Failed to process image from API response. {e}")
111
 
112
  css = """
113
  #app-container {
114
- max-width: 700px; /* Sedikit lebih lebar untuk kenyamanan */
115
  margin-left: auto;
116
  margin-right: auto;
117
  }
@@ -119,76 +86,51 @@ css = """
119
  display: flex;
120
  align-items: center;
121
  justify-content: center;
122
- margin-bottom: 15px; /* Tambah margin bawah */
123
  }
124
  #title-icon {
125
- width: 40px; /* Sedikit lebih besar */
126
  height: auto;
127
- margin-right: 10px;
128
  }
129
  #title-text {
130
- font-size: 28px; /* Sedikit lebih besar */
131
  font-weight: bold;
132
  }
133
- #gen-button {
134
- margin-top: 10px;
135
- }
136
  """
137
 
138
  with gr.Blocks(theme='Nymbo/Nymbo_Theme', css=css) as app:
139
  gr.HTML("""
140
- <div id="title-container">
141
- <img id="title-icon" src="file/icon.jpg" alt="Icon"> <!-- Perbaiki path jika icon.jpg di root -->
142
- <h1 id="title-text">FLUX Capacitor</h1>
143
- </div>
144
- """) # Menggunakan </center> tidak standar, div dengan margin auto lebih baik untuk centering global
 
 
145
 
146
  with gr.Column(elem_id="app-container"):
147
  with gr.Row():
148
- text_prompt = gr.Textbox(label="Prompt", placeholder="Enter a prompt here", lines=3, elem_id="prompt-text-input")
149
-
150
- with gr.Accordion("Advanced Settings", open=False):
151
- negative_prompt_ui = gr.Textbox(label="Negative Prompt", placeholder="What should not be in the image", value="(deformed, distorted, disfigured), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation, misspellings, typos", lines=3, elem_id="negative-prompt-text-input")
152
- steps_ui = gr.Slider(label="Sampling steps", value=35, minimum=1, maximum=100, step=1)
153
- cfg_ui = gr.Slider(label="CFG Scale", value=7, minimum=1, maximum=20, step=1)
154
- method_ui = gr.Radio(label="Sampling method", value="DPM++ 2M Karras", choices=["DPM++ 2M Karras", "DPM++ SDE Karras", "Euler", "Euler a", "Heun", "DDIM"])
155
- strength_ui = gr.Slider(label="Strength (for Img2Img/SDEdit, might not apply here)", value=0.7, minimum=0, maximum=1, step=0.001)
156
- seed_ui = gr.Slider(label="Seed (-1 for random)", value=-1, minimum=-1, maximum=1000000000, step=1)
157
- huggingface_api_key_ui_input = gr.Textbox(
158
- label="Hugging Face API Key (optional, uses HF_READ_TOKEN if empty)",
159
- placeholder="Enter your Hugging Face API Key (e.g., hf_xxxx)",
160
- type="password",
161
- elem_id="api-key"
162
- )
163
- use_dev_ui = gr.Checkbox(label="Use Dev API (potentially unstable)", value=False, elem_id="use-dev-checkbox")
164
 
165
  with gr.Row():
166
- text_button = gr.Button("Generate Image", variant='primary', elem_id="gen-button", scale=3) # scale untuk mengambil lebih banyak ruang jika diinginkan
167
-
168
  with gr.Row():
169
- image_output = gr.Image(type="filepath", label="Generated Image", elem_id="gallery") # type="filepath" lebih baik untuk output path
170
- seed_output = gr.Textbox(label="Seed Used", elem_id="seed-output", interactive=False)
171
 
172
- # Sesuaikan fungsi click untuk menyertakan input API key dan use_dev
173
- # Pastikan urutan input di sini sesuai dengan urutan argumen di fungsi query
174
- text_button.click(
175
- query,
176
- inputs=[
177
- text_prompt,
178
- negative_prompt_ui,
179
- steps_ui,
180
- cfg_ui,
181
- method_ui,
182
- seed_ui,
183
- strength_ui,
184
- huggingface_api_key_ui_input,
185
- use_dev_ui
186
- ],
187
- outputs=[image_output, seed_output]
188
- )
189
-
190
- # Jika Anda menjalankan di environment seperti Hugging Face Spaces, share=True biasanya diperlukan atau default.
191
- # TypeError: argument of type 'bool' is not iterable (dari log Anda) sering terkait dengan show_api=True
192
- # pada versi Gradio tertentu. Memperbarui Gradio atau menyetel show_api=False dapat membantu.
193
- # Untuk tujuan demo ini, show_api=False bisa lebih stabil jika Anda masih menghadapi error tersebut.
194
- app.launch(show_api=False, share=True) # show_api=False untuk menghindari potensi error schema, share=True untuk aksesibilitas
 
6
  from PIL import Image
7
  from deep_translator import GoogleTranslator
8
 
9
+ # os.makedirs('assets', exist_ok=True)
10
  if not os.path.exists('icon.jpg'):
 
11
  os.system("wget -O icon.jpg https://i.pinimg.com/564x/64/49/88/644988c59447eb00286834c2e70fdd6b.jpg")
12
+ API_URL_DEV = "https://api-inference.huggingface.co/models/black-forest-labs/FLUX.1-dev"
13
+ API_URL = "https://api-inference.huggingface.co/models/black-forest-labs/FLUX.1-schnell"
 
 
14
  timeout = 100
15
 
16
+ def query(prompt, is_negative=False, steps=30, cfg_scale=7, sampler="DPM++ 2M Karras", seed=-1, strength=0.7, huggingface_api_key=None, use_dev=False):
17
  # Determine which API URL to use
18
  api_url = API_URL_DEV if use_dev else API_URL
19
 
20
+ # Check if the request is an API call by checking for the presence of the huggingface_api_key
21
+ is_api_call = huggingface_api_key is not None
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ if is_api_call:
24
+ # Use the environment variable for the API key in GUI mode
25
+ API_TOKEN = os.getenv("HF_READ_TOKEN")
26
+ headers = {"Authorization": f"Bearer {API_TOKEN}"}
27
+ else:
28
+ # Validate the API key if it's an API call
29
+ if huggingface_api_key == "":
30
+ raise gr.Error("API key is required for API calls.")
31
+ headers = {"Authorization": f"Bearer {huggingface_api_key}"}
32
 
33
+ if prompt == "" or prompt is None:
34
+ return None
 
 
 
35
 
36
  key = random.randint(0, 999)
37
 
38
+ prompt = GoogleTranslator(source='ru', target='en').translate(prompt)
39
+ print(f'\033[1mGeneration {key} translation:\033[0m {prompt}')
 
 
 
 
 
 
40
 
41
+ prompt = f"{prompt} | ultra detail, ultra elaboration, ultra quality, perfect."
42
+ print(f'\033[1mGeneration {key}:\033[0m {prompt}')
 
43
 
44
+ # If seed is -1, generate a random seed and use it
45
  if seed == -1:
46
  seed = random.randint(1, 1000000000)
47
 
48
  payload = {
49
+ "inputs": prompt,
50
+ "is_negative": is_negative,
51
  "steps": steps,
52
  "cfg_scale": cfg_scale,
53
  "seed": seed,
54
+ "strength": strength
 
55
  }
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  response = requests.post(api_url, headers=headers, json=payload, timeout=timeout)
58
  if response.status_code != 200:
59
  print(f"Error: Failed to get image. Response status: {response.status_code}")
60
  print(f"Response content: {response.text}")
61
  if response.status_code == 503:
62
+ raise gr.Error(f"{response.status_code} : The model is being loaded")
63
+ raise gr.Error(f"{response.status_code}")
64
 
65
  try:
66
  image_bytes = response.content
67
  image = Image.open(io.BytesIO(image_bytes))
68
+ print(f'\033[1mGeneration {key} completed!\033[0m ({prompt})')
69
 
70
+ # Save the image to a file and return the file path and seed
71
+ output_path = f"./output_{key}.png"
 
 
 
72
  image.save(output_path)
73
 
74
  return output_path, seed
75
  except Exception as e:
76
+ print(f"Error when trying to open the image: {e}")
77
+ return None, None
 
78
 
79
  css = """
80
  #app-container {
81
+ max-width: 600px;
82
  margin-left: auto;
83
  margin-right: auto;
84
  }
 
86
  display: flex;
87
  align-items: center;
88
  justify-content: center;
 
89
  }
90
  #title-icon {
91
+ width: 32px; /* Adjust the width of the icon as needed */
92
  height: auto;
93
+ margin-right: 10px; /* Space between icon and title */
94
  }
95
  #title-text {
96
+ font-size: 24px; /* Adjust font size as needed */
97
  font-weight: bold;
98
  }
 
 
 
99
  """
100
 
101
  with gr.Blocks(theme='Nymbo/Nymbo_Theme', css=css) as app:
102
  gr.HTML("""
103
+ <center>
104
+ <div id="title-container">
105
+ <img id="title-icon" src="icon.jpg" alt="Icon">
106
+ <h1 id="title-text">FLUX Capacitor</h1>
107
+ </div>
108
+ </center>
109
+ """)
110
 
111
  with gr.Column(elem_id="app-container"):
112
  with gr.Row():
113
+ with gr.Column(elem_id="prompt-container"):
114
+ with gr.Row():
115
+ text_prompt = gr.Textbox(label="Prompt", placeholder="Enter a prompt here", lines=2, elem_id="prompt-text-input")
116
+ with gr.Row():
117
+ with gr.Accordion("Advanced Settings", open=False):
118
+ negative_prompt = gr.Textbox(label="Negative Prompt", placeholder="What should not be in the image", value="(deformed, distorted, disfigured), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation, misspellings, typos", lines=3, elem_id="negative-prompt-text-input")
119
+ steps = gr.Slider(label="Sampling steps", value=35, minimum=1, maximum=100, step=1)
120
+ cfg = gr.Slider(label="CFG Scale", value=7, minimum=1, maximum=20, step=1)
121
+ method = gr.Radio(label="Sampling method", value="DPM++ 2M Karras", choices=["DPM++ 2M Karras", "DPM++ SDE Karras", "Euler", "Euler a", "Heun", "DDIM"])
122
+ strength = gr.Slider(label="Strength", value=0.7, minimum=0, maximum=1, step=0.001)
123
+ seed = gr.Slider(label="Seed", value=-1, minimum=-1, maximum=1000000000, step=1)
124
+ huggingface_api_key = gr.Textbox(label="Hugging Face API Key (required for API calls)", placeholder="Enter your Hugging Face API Key here", type="password", elem_id="api-key")
125
+ use_dev = gr.Checkbox(label="Use Dev API", value=False, elem_id="use-dev-checkbox")
 
 
 
126
 
127
  with gr.Row():
128
+ text_button = gr.Button("Run", variant='primary', elem_id="gen-button")
 
129
  with gr.Row():
130
+ image_output = gr.Image(type="pil", label="Image Output", elem_id="gallery")
131
+ seed_output = gr.Textbox(label="Seed Used", elem_id="seed-output")
132
 
133
+ # Adjust the click function to include the API key and use_dev as inputs
134
+ text_button.click(query, inputs=[text_prompt, negative_prompt, steps, cfg, method, seed, strength, huggingface_api_key, use_dev], outputs=[image_output, seed_output])
135
+
136
+ app.launch(show_api=True, share=False)