Deadmon commited on
Commit
1a2d550
·
verified ·
1 Parent(s): 25b4ca5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -34
app.py CHANGED
@@ -1,9 +1,131 @@
1
- # Fallback: Use a gr.Gallery component for thumbnails
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  with gr.Blocks(title="Image Editing Chatbot") as demo:
3
  gr.Markdown("# Image Editing Chatbot")
4
  gr.Markdown("Upload an image and/or type a prompt to generate or edit an image using Google's Gemini model")
5
 
6
- # Chatbot display area for text messages
7
  chatbot = gr.Chatbot(
8
  label="Chat",
9
  height=300,
@@ -11,10 +133,7 @@ with gr.Blocks(title="Image Editing Chatbot") as demo:
11
  avatar_images=(None, None)
12
  )
13
 
14
- # Gallery for thumbnails
15
- thumbnail_gallery = gr.Gallery(label="Conversation Thumbnails", columns=4, height=150)
16
-
17
- # Separate image outputs (gallery)
18
  with gr.Row():
19
  uploaded_image_output = gr.Image(label="Uploaded Image")
20
  generated_image_output = gr.Image(label="Generated Image")
@@ -40,48 +159,65 @@ with gr.Blocks(title="Image Editing Chatbot") as demo:
40
  )
41
  generate_btn = gr.Button("Generate Image")
42
 
43
- # State to maintain chat history and thumbnail list
 
 
 
 
44
  chat_state = gr.State([])
45
- thumbnail_list = gr.State([])
46
 
47
- def chat_handler(prompt, user_image, chat_history, thumbnails, output_filename="generated_image"):
48
- # Add the prompt to the chat history
49
- if prompt:
50
- chat_history.append({"role": "user", "content": prompt})
 
 
 
51
 
52
- # Add the uploaded image to the thumbnail list
53
- if user_image:
54
- thumbnails.append(user_image)
55
 
56
- # If no input, return early
57
- if not prompt and not user_image:
58
- chat_history.append({"role": "assistant", "content": "Please provide a prompt or an image."})
59
- return chat_history, user_image, None, thumbnails, ""
 
60
 
61
- # Generate image based on user input
62
- img, status = generate_image(prompt or "Generate an image", user_image, output_filename)
63
-
64
- # Add the status message to the chat history
65
- chat_history.append({"role": "assistant", "content": status})
66
-
67
- # Add the generated image to the thumbnail list
68
- if img:
69
- thumbnails.append(img)
70
-
71
- return chat_history, user_image, img, thumbnails, ""
 
 
 
 
 
 
 
 
 
 
72
 
73
  # Connect the button to the chat handler
74
  generate_btn.click(
75
  fn=chat_handler,
76
- inputs=[prompt_input, image_input, chat_state, thumbnail_list, filename_input],
77
- outputs=[chatbot, uploaded_image_output, generated_image_output, thumbnail_gallery, prompt_input]
78
  )
79
 
80
  # Also allow Enter key to submit
81
  prompt_input.submit(
82
  fn=chat_handler,
83
- inputs=[prompt_input, image_input, chat_state, thumbnail_list, filename_input],
84
- outputs=[chatbot, uploaded_image_output, generated_image_output, thumbnail_gallery, prompt_input]
85
  )
86
 
87
  if __name__ == "__main__":
 
1
+ import base64
2
+ import os
3
+ import mimetypes
4
+ from google import genai
5
+ from google.genai import types
6
+ import gradio as gr # Correct import for Gradio
7
+ import io
8
+ from PIL import Image
9
+
10
+ def save_binary_file(file_name, data):
11
+ f = open(file_name, "wb")
12
+ f.write(data)
13
+ f.close()
14
+
15
+ def generate_image(prompt, image=None, output_filename="generated_image"):
16
+ # Initialize client with the API key
17
+ client = genai.Client(
18
+ api_key="AIzaSyAQcy3LfrkMy6DqS_8MqftAXu1Bx_ov_E8",
19
+ )
20
+
21
+ model = "gemini-2.0-flash-exp-image-generation"
22
+ parts = [types.Part.from_text(text=prompt)]
23
+
24
+ # If an image is provided, add it to the content
25
+ if image:
26
+ # Convert PIL Image to bytes
27
+ img_byte_arr = io.BytesIO()
28
+ image.save(img_byte_arr, format="PNG")
29
+ img_bytes = img_byte_arr.getvalue()
30
+ # Add the image as a Part with inline_data
31
+ parts.append({
32
+ "inline_data": {
33
+ "mime_type": "image/png",
34
+ "data": img_bytes
35
+ }
36
+ })
37
+
38
+ contents = [
39
+ types.Content(
40
+ role="user",
41
+ parts=parts,
42
+ ),
43
+ ]
44
+ generate_content_config = types.GenerateContentConfig(
45
+ temperature=1,
46
+ top_p=0.95,
47
+ top_k=40,
48
+ max_output_tokens=8192,
49
+ response_modalities=[
50
+ "image",
51
+ "text",
52
+ ],
53
+ safety_settings=[
54
+ types.SafetySetting(
55
+ category="HARM_CATEGORY_CIVIC_INTEGRITY",
56
+ threshold="OFF",
57
+ ),
58
+ ],
59
+ response_mime_type="text/plain",
60
+ )
61
+
62
+ # Generate the content
63
+ response = client.models.generate_content_stream(
64
+ model=model,
65
+ contents=contents,
66
+ config=generate_content_config,
67
+ )
68
+
69
+ # Process the response
70
+ for chunk in response:
71
+ if not chunk.candidates or not chunk.candidates[0].content or not chunk.candidates[0].content.parts:
72
+ continue
73
+ if chunk.candidates[0].content.parts[0].inline_data:
74
+ inline_data = chunk.candidates[0].content.parts[0].inline_data
75
+ file_extension = mimetypes.guess_extension(inline_data.mime_type)
76
+ filename = f"{output_filename}{file_extension}"
77
+ save_binary_file(filename, inline_data.data)
78
+
79
+ # Convert binary data to PIL Image for Gradio display
80
+ img = Image.open(io.BytesIO(inline_data.data))
81
+ return img, f"Image saved as {filename}"
82
+ else:
83
+ return None, chunk.text
84
+
85
+ return None, "No image generated"
86
+
87
+ # Function to handle chat interaction
88
+ def chat_handler(prompt, user_image, chat_history, output_filename="generated_image"):
89
+ # Add the prompt to the chat history
90
+ if prompt:
91
+ chat_history.append({"role": "user", "content": prompt})
92
+
93
+ # If no input, return early
94
+ if not prompt and not user_image:
95
+ chat_history.append({"role": "assistant", "content": "Please provide a prompt or an image."})
96
+ return chat_history, user_image, None, ""
97
+
98
+ # Generate image based on user input
99
+ img, status = generate_image(prompt or "Generate an image", user_image, output_filename)
100
+
101
+ # Add the status message to the chat history
102
+ chat_history.append({"role": "assistant", "content": status})
103
+
104
+ return chat_history, user_image, img, ""
105
+
106
+ # Function to update chat history with thumbnails
107
+ def update_chat_with_thumbnails(chat_history, uploaded_image_url, generated_image_url):
108
+ # Create a copy of the chat history to avoid modifying the input directly
109
+ updated_history = chat_history.copy()
110
+
111
+ # If there's an uploaded image, add its thumbnail to the chat history
112
+ if uploaded_image_url and uploaded_image_url.strip():
113
+ thumbnail_html = f'<img src="{uploaded_image_url}" width="100px" style="margin: 5px;" />'
114
+ updated_history.append({"role": "user", "content": thumbnail_html})
115
+
116
+ # If there's a generated image, add its thumbnail to the chat history
117
+ if generated_image_url and generated_image_url.strip():
118
+ thumbnail_html = f'<img src="{generated_image_url}" width="100px" style="margin: 5px;" />'
119
+ updated_history.append({"role": "assistant", "content": thumbnail_html})
120
+
121
+ return updated_history
122
+
123
+ # Create Gradio interface
124
  with gr.Blocks(title="Image Editing Chatbot") as demo:
125
  gr.Markdown("# Image Editing Chatbot")
126
  gr.Markdown("Upload an image and/or type a prompt to generate or edit an image using Google's Gemini model")
127
 
128
+ # Chatbot display area for text messages and thumbnails
129
  chatbot = gr.Chatbot(
130
  label="Chat",
131
  height=300,
 
133
  avatar_images=(None, None)
134
  )
135
 
136
+ # Separate image outputs
 
 
 
137
  with gr.Row():
138
  uploaded_image_output = gr.Image(label="Uploaded Image")
139
  generated_image_output = gr.Image(label="Generated Image")
 
159
  )
160
  generate_btn = gr.Button("Generate Image")
161
 
162
+ # Hidden components to store image URLs
163
+ uploaded_image_url = gr.State("")
164
+ generated_image_url = gr.State("")
165
+
166
+ # State to maintain chat history
167
  chat_state = gr.State([])
 
168
 
169
+ # JavaScript to extract image URLs and update the chat history
170
+ gr.HTML("""
171
+ <script>
172
+ async function updateImageURLs() {
173
+ // Get the image elements from the gr.Image components
174
+ const uploadedImage = document.querySelector('#component-3 img'); // Uploaded Image component
175
+ const generatedImage = document.querySelector('#component-4 img'); // Generated Image component
176
 
177
+ // Extract the src attributes (URLs)
178
+ const uploadedImageURL = uploadedImage && uploadedImage.src ? uploadedImage.src : "";
179
+ const generatedImageURL = generatedImage && generatedImage.src ? generatedImage.src : "";
180
 
181
+ // Call the Python function to update the chat history with the URLs
182
+ const chatHistory = await gradioApp().querySelector('#component-2').value; // Chat state component
183
+ const result = await gradioApp().querySelector('#component-0').callFunction('update_chat_with_thumbnails', [chatHistory, uploadedImageURL, generatedImageURL]);
184
+ return result;
185
+ }
186
 
187
+ // Run the function when the Generate Image button is clicked
188
+ document.querySelector('#component-8').addEventListener('click', async () => { // Generate Image button
189
+ // Wait for the images to update
190
+ setTimeout(async () => {
191
+ const updatedChat = await updateImageURLs();
192
+ // Update the chatbot component with the new history
193
+ document.querySelector('#component-1').value = updatedChat; // Chatbot component
194
+ }, 1000); // Delay to ensure images are loaded
195
+ });
196
+
197
+ // Also run the function when the Enter key is pressed in the prompt input
198
+ document.querySelector('#component-6').addEventListener('keypress', async (e) => { // Prompt input
199
+ if (e.key === 'Enter') {
200
+ setTimeout(async () => {
201
+ const updatedChat = await updateImageURLs();
202
+ document.querySelector('#component-1').value = updatedChat;
203
+ }, 1000);
204
+ }
205
+ });
206
+ </script>
207
+ """)
208
 
209
  # Connect the button to the chat handler
210
  generate_btn.click(
211
  fn=chat_handler,
212
+ inputs=[prompt_input, image_input, chat_state, filename_input],
213
+ outputs=[chatbot, uploaded_image_output, generated_image_output, prompt_input]
214
  )
215
 
216
  # Also allow Enter key to submit
217
  prompt_input.submit(
218
  fn=chat_handler,
219
+ inputs=[prompt_input, image_input, chat_state, filename_input],
220
+ outputs=[chatbot, uploaded_image_output, generated_image_output, prompt_input]
221
  )
222
 
223
  if __name__ == "__main__":