Varhal commited on
Commit
cba75f5
·
verified ·
1 Parent(s): 594a3b5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -65
app.py CHANGED
@@ -7,21 +7,27 @@ from PIL import Image, ImageDraw, ImageFont
7
  import gradio as gr
8
  import base64
9
  import mimetypes
10
-
11
  from google import genai
12
  from google.genai import types
13
 
 
14
  def save_binary_file(file_name, data):
15
  with open(file_name, "wb") as f:
16
  f.write(data)
17
 
18
- def generate(text, file_name, api_key, model="gemini-2.0-flash-exp"):
19
- # Initialize client using provided api_key (or fallback to env variable)
20
- client = genai.Client(api_key=(api_key.strip() if api_key and api_key.strip() != ""
21
- else os.environ.get("GEMINI_API_KEY")))
22
-
 
 
 
 
 
 
23
  files = [ client.files.upload(file=file_name) ]
24
-
25
  contents = [
26
  types.Content(
27
  role="user",
@@ -34,6 +40,7 @@ def generate(text, file_name, api_key, model="gemini-2.0-flash-exp"):
34
  ],
35
  ),
36
  ]
 
37
  generate_content_config = types.GenerateContentConfig(
38
  temperature=1,
39
  top_p=0.95,
@@ -45,7 +52,7 @@ def generate(text, file_name, api_key, model="gemini-2.0-flash-exp"):
45
 
46
  text_response = ""
47
  image_path = None
48
- # Create a temporary file to potentially store image data.
49
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
50
  temp_path = tmp.name
51
  for chunk in client.models.generate_content_stream(
@@ -56,49 +63,50 @@ def generate(text, file_name, api_key, model="gemini-2.0-flash-exp"):
56
  if not chunk.candidates or not chunk.candidates[0].content or not chunk.candidates[0].content.parts:
57
  continue
58
  candidate = chunk.candidates[0].content.parts[0]
59
- # Check for inline image data
60
  if candidate.inline_data:
61
  save_binary_file(temp_path, candidate.inline_data.data)
62
  print(f"File of mime type {candidate.inline_data.mime_type} saved to: {temp_path} and prompt input: {text}")
63
  image_path = temp_path
64
- # If an image is found, we assume that is the desired output.
65
  break
66
  else:
67
- # Accumulate text response if no inline_data is present.
68
  text_response += chunk.text + "\n"
69
-
70
- del files
 
 
71
  return image_path, text_response
72
 
73
- def process_image_and_prompt(composite_pil, prompt, gemini_api_key):
 
74
  try:
75
- # Save the composite image to a temporary file.
76
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
77
  composite_path = tmp.name
78
  composite_pil.save(composite_path)
79
-
80
- file_name = composite_path
81
- input_text = prompt
82
- model = "gemini-2.0-flash-exp"
83
 
84
- image_path, text_response = generate(text=input_text, file_name=file_name, api_key=gemini_api_key, model=model)
85
-
 
 
 
 
 
86
  if image_path:
87
- # Load and convert the image if needed.
88
  result_img = Image.open(image_path)
89
  if result_img.mode == "RGBA":
90
  result_img = result_img.convert("RGB")
91
- return [result_img], "" # Return image in gallery and empty text output.
92
  else:
93
- # Return no image and the text response.
94
  return None, text_response
 
95
  except Exception as e:
 
 
 
96
  raise gr.Error(f"Error Getting {e}", duration=5)
97
 
98
-
99
- # Build a Blocks-based interface with a custom HTML header and CSS
100
  with gr.Blocks(css_paths="style.css",) as demo:
101
- # Custom HTML header with proper class for styling
102
  gr.HTML(
103
  """
104
  <div class="header-container">
@@ -107,32 +115,29 @@ with gr.Blocks(css_paths="style.css",) as demo:
107
  </div>
108
  <div>
109
  <h1>Gemini for Image Editing</h1>
110
- <p>Powered by <a href="https://gradio.app/">Gradio</a>⚡️|
111
- <a href="https://huggingface.co/spaces/ameerazam08/Gemini-Image-Edit?duplicate=true">Duplicate</a> this Repo |
112
- <a href="https://aistudio.google.com/apikey">Get an API Key</a> |
113
- Follow me on Twitter: <a href="https://x.com/Ameerazam18">Ameerazam18</a></p>
114
  </div>
115
  </div>
116
  """
117
  )
118
-
 
119
  with gr.Accordion("⚠️ API Configuration ⚠️", open=False, elem_classes="config-accordion"):
120
  gr.Markdown("""
121
- - **Issue:** Sometimes the model returns text instead of an image.
122
- ### 🔧 Steps to Address:
123
- 1. **🛠️ Duplicate the Repository**
124
- - Create a separate copy for modifications.
125
- 2. **🔑 Use Your Own Gemini API Key**
126
- - You **must** configure your own Gemini key for generation!
127
  """)
128
 
129
  with gr.Accordion("📌 Usage Instructions", open=False, elem_classes="instructions-accordion"):
130
  gr.Markdown("""
131
- ### 📌 Usage
132
- - Upload an image and enter a prompt to generate outputs.
133
- - If text is returned instead of an image, it will appear in the text output.
134
- - Upload Only PNG Image
135
- - ❌ **Do not use NSFW images!**
136
  """)
137
 
138
  with gr.Row(elem_classes="main-content"):
@@ -144,12 +149,13 @@ with gr.Blocks(css_paths="style.css",) as demo:
144
  elem_id="image-input",
145
  elem_classes="upload-box"
146
  )
147
- gemini_api_key = gr.Textbox(
148
- lines=1,
149
- placeholder="Enter Gemini API Key (optional)",
150
- label="Gemini API Key (optional)",
151
- elem_classes="api-key-input"
152
- )
 
153
  prompt_input = gr.Textbox(
154
  lines=2,
155
  placeholder="Enter prompt here...",
@@ -157,38 +163,39 @@ with gr.Blocks(css_paths="style.css",) as demo:
157
  elem_classes="prompt-input"
158
  )
159
  submit_btn = gr.Button("Generate", elem_classes="generate-btn")
160
-
161
  with gr.Column(elem_classes="output-column"):
162
  output_gallery = gr.Gallery(label="Generated Outputs", elem_classes="output-gallery")
163
  output_text = gr.Textbox(
164
- label="Gemini Output",
165
  placeholder="Text response will appear here if no image is generated.",
166
  elem_classes="output-text"
167
  )
168
 
169
- # Set up the interaction with two outputs.
170
  submit_btn.click(
171
  fn=process_image_and_prompt,
172
- inputs=[image_input, prompt_input, gemini_api_key],
173
  outputs=[output_gallery, output_text],
174
  )
175
-
176
  gr.Markdown("## Try these examples", elem_classes="gr-examples-header")
177
-
 
178
  examples = [
179
- ["data/1.webp", 'change text to "AMEER"', ""],
180
- ["data/2.webp", "remove the spoon from hand only", ""],
181
- ["data/3.webp", 'change text to "Make it "', ""],
182
- ["data/1.jpg", "add joker style only on face", ""],
183
- ["data/1777043.jpg", "add joker style only on face", ""],
184
- ["data/2807615.jpg", "add lipstick on lip only", ""],
185
- ["data/76860.jpg", "add lipstick on lip only", ""],
186
- ["data/2807615.jpg", "make it happy looking face only", ""],
187
  ]
188
-
189
  gr.Examples(
190
  examples=examples,
191
- inputs=[image_input, prompt_input,],
192
  elem_id="examples-grid"
193
  )
194
 
 
7
  import gradio as gr
8
  import base64
9
  import mimetypes
 
10
  from google import genai
11
  from google.genai import types
12
 
13
+ # Функція для збереження бінарного файлу (залишаємо без змін)
14
  def save_binary_file(file_name, data):
15
  with open(file_name, "wb") as f:
16
  f.write(data)
17
 
18
+ # Модифікована функція generate - прибираємо api_key як параметр
19
+ def generate(text, file_name, model="gemini-2.0-flash-exp"):
20
+ # Ініціалізуємо клієнта, читаючи ключ зі змінної оточення geminigoogle
21
+ # Переконайтеся, що змінна geminigoogle встановлена у ваших налаштуваннях Space
22
+ api_key = os.environ.get("geminigoogle")
23
+ if not api_key:
24
+ raise ValueError("GEMINI_API_KEY environment variable (geminigoogle) not set.")
25
+
26
+ client = genai.Client(api_key=api_key)
27
+
28
+ # Решта функції generate залишається без змін
29
  files = [ client.files.upload(file=file_name) ]
30
+
31
  contents = [
32
  types.Content(
33
  role="user",
 
40
  ],
41
  ),
42
  ]
43
+
44
  generate_content_config = types.GenerateContentConfig(
45
  temperature=1,
46
  top_p=0.95,
 
52
 
53
  text_response = ""
54
  image_path = None
55
+
56
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
57
  temp_path = tmp.name
58
  for chunk in client.models.generate_content_stream(
 
63
  if not chunk.candidates or not chunk.candidates[0].content or not chunk.candidates[0].content.parts:
64
  continue
65
  candidate = chunk.candidates[0].content.parts[0]
66
+
67
  if candidate.inline_data:
68
  save_binary_file(temp_path, candidate.inline_data.data)
69
  print(f"File of mime type {candidate.inline_data.mime_type} saved to: {temp_path} and prompt input: {text}")
70
  image_path = temp_path
 
71
  break
72
  else:
 
73
  text_response += chunk.text + "\n"
74
+
75
+ # Видаляємо завантажені файли після використання
76
+ del files
77
+
78
  return image_path, text_response
79
 
80
+ # Модифікована функція process_image_and_prompt - прибираємо gemini_api_key як параметр
81
+ def process_image_and_prompt(composite_pil, prompt):
82
  try:
 
83
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
84
  composite_path = tmp.name
85
  composite_pil.save(composite_path)
 
 
 
 
86
 
87
+ file_name = composite_path
88
+ input_text = prompt
89
+ model = "gemini-2.0-flash-exp" # Модель вказується тут
90
+
91
+ # Викликаємо generate без api_key
92
+ image_path, text_response = generate(text=input_text, file_name=file_name, model=model)
93
+
94
  if image_path:
 
95
  result_img = Image.open(image_path)
96
  if result_img.mode == "RGBA":
97
  result_img = result_img.convert("RGB")
98
+ return [result_img], ""
99
  else:
 
100
  return None, text_response
101
+
102
  except Exception as e:
103
+ # Важливо видалити тимчасовий файл у разі помилки
104
+ if 'composite_path' in locals() and os.path.exists(composite_path):
105
+ os.remove(composite_path)
106
  raise gr.Error(f"Error Getting {e}", duration=5)
107
 
108
+ # Gradio інтерфейс
 
109
  with gr.Blocks(css_paths="style.css",) as demo:
 
110
  gr.HTML(
111
  """
112
  <div class="header-container">
 
115
  </div>
116
  <div>
117
  <h1>Gemini for Image Editing</h1>
118
+ <p>Powered by <a href="https://gradio.app/">Gradio</a>⚡️|
119
+ <a href="https://huggingface.co/spaces/ameerazam08/Gemini-Image-Edit?duplicate=true">Duplicate</a> this Repo |
120
+ <a href="https://aistudio.google.com/apikey">Get an API Key</a> |
121
+ Follow me on Twitter: <a href="https://x.com/Ameerazam18">Ameerazam18</a></p>
122
  </div>
123
  </div>
124
  """
125
  )
126
+
127
+ # Прибираємо секцію API Configuration або змінюємо її опис, оскільки ключ більше не вводиться
128
  with gr.Accordion("⚠️ API Configuration ⚠️", open=False, elem_classes="config-accordion"):
129
  gr.Markdown("""
130
+ - **Ваш Gemini API ключ має бути збережений у змінній оточення `geminigoogle` в налаштуваннях Hugging Face Space.**
131
+ - Іноді модель повертає текст замість зображення.
 
 
 
 
132
  """)
133
 
134
  with gr.Accordion("📌 Usage Instructions", open=False, elem_classes="instructions-accordion"):
135
  gr.Markdown("""
136
+ ### 📌 Usage
137
+ - Upload an image and enter a prompt to generate outputs.
138
+ - If text is returned instead of an image, it will appear in the text output.
139
+ - Upload Only PNG Image
140
+ - ❌ **Do not use NSFW images!**
141
  """)
142
 
143
  with gr.Row(elem_classes="main-content"):
 
149
  elem_id="image-input",
150
  elem_classes="upload-box"
151
  )
152
+ # Прибираємо поле введення API ключа з інтерфейсу
153
+ # gemini_api_key = gr.Textbox(
154
+ # lines=1,
155
+ # placeholder="Enter Gemini API Key (optional)",
156
+ # label="Gemini API Key (optional)",
157
+ # elem_classes="api-key-input"
158
+ # )
159
  prompt_input = gr.Textbox(
160
  lines=2,
161
  placeholder="Enter prompt here...",
 
163
  elem_classes="prompt-input"
164
  )
165
  submit_btn = gr.Button("Generate", elem_classes="generate-btn")
166
+
167
  with gr.Column(elem_classes="output-column"):
168
  output_gallery = gr.Gallery(label="Generated Outputs", elem_classes="output-gallery")
169
  output_text = gr.Textbox(
170
+ label="Gemini Output",
171
  placeholder="Text response will appear here if no image is generated.",
172
  elem_classes="output-text"
173
  )
174
 
175
+ # Налаштовуємо взаємодію - прибираємо gemini_api_key з inputs
176
  submit_btn.click(
177
  fn=process_image_and_prompt,
178
+ inputs=[image_input, prompt_input], # Передаємо лише image_input та prompt_input
179
  outputs=[output_gallery, output_text],
180
  )
181
+
182
  gr.Markdown("## Try these examples", elem_classes="gr-examples-header")
183
+
184
+ # Приклади залишаємо без змін, API ключ в них не потрібен
185
  examples = [
186
+ ["data/1.webp", 'change text to "AMEER"'],
187
+ ["data/2.webp", "remove the spoon from hand only"],
188
+ ["data/3.webp", 'change text to "Make it "'],
189
+ ["data/1.jpg", "add joker style only on face"],
190
+ ["data/1777043.jpg", "add joker style only on face"],
191
+ ["data/2807615.jpg", "add lipstick on lip only"],
192
+ ["data/76860.jpg", "add lipstick on lip only"],
193
+ ["data/2807615.jpg", "make it happy looking face only"],
194
  ]
195
+
196
  gr.Examples(
197
  examples=examples,
198
+ inputs=[image_input, prompt_input], # Приклади також не потребують API ключа
199
  elem_id="examples-grid"
200
  )
201