huzey commited on
Commit
77e98f5
·
1 Parent(s): 84b8851
Files changed (2) hide show
  1. app.py +132 -17
  2. requirements.txt +2 -0
app.py CHANGED
@@ -1,16 +1,38 @@
1
  import logging
2
  import os
3
- from typing import List, Union
 
 
 
 
4
 
5
  import gradio as gr
6
  from PIL import Image
7
  import numpy as np
 
8
 
9
  from vibe_blending import run_vibe_blend_safe, run_vibe_blend_not_safe
10
  from ipadapter_model import create_image_grid
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  USE_HUGGINGFACE_ZEROGPU = os.getenv("USE_HUGGINGFACE_ZEROGPU", "false").lower() == "false" #"true"
13
  DEFAULT_CONFIG_PATH = "./config.yaml"
 
 
 
 
14
 
15
  if USE_HUGGINGFACE_ZEROGPU:
16
  try:
@@ -61,17 +83,11 @@ def load_gradio_images_helper(pil_images: Union[List, Image.Image, str]) -> List
61
  return processed_images
62
 
63
 
64
- def create_gradio_interface():
65
- theme = gr.themes.Base(
66
- spacing_size='md',
67
- text_size='lg',
68
- primary_hue='blue',
69
- neutral_hue='slate',
70
- secondary_hue='pink'
71
- )
72
-
73
- demo = gr.Blocks(theme=theme)
74
- with demo:
75
  gr.Markdown("""
76
  ## Vibe Blending Demo
77
 
@@ -81,8 +97,6 @@ def create_gradio_interface():
81
 
82
  Given a pair of images, vibe blending will generate a set of images that creatively connect the input images.
83
 
84
- **[📝 Feedback Form](https://docs.google.com/forms/d/e/1FAIpQLSfS-2fdJ3eaG6JBUGNgHYD4zNRtoPUOc2OhF8J-uT-gyR3LyA/viewform?usp=dialog)** - Please submit your interesting images!
85
-
86
  """)
87
  with gr.Row():
88
  with gr.Column():
@@ -103,6 +117,12 @@ def create_gradio_interface():
103
  with gr.Row():
104
  extra_images = gr.Gallery(label="Extra Images (optional)", show_label=True, columns=3, rows=2, height=150)
105
  negative_images = gr.Gallery(label="Negative Images (optional)", show_label=True, columns=3, rows=2, height=150)
 
 
 
 
 
 
106
  with gr.Column():
107
  with gr.Group():
108
  # blending_results = gr.Gallery(label="Vibe Blending Results", columns=5, rows=4, height=600)
@@ -110,8 +130,7 @@ def create_gradio_interface():
110
  blending_results = gr.Image(label="Vibe Blending Results", show_label=True, height=400)
111
  blend_button = gr.Button("🔴 Run Vibe Blending", variant="primary")
112
 
113
- # Training wrapper function
114
- def blend_button_click(input1, input2, extra_images, negative_images, alpha_start, alpha_end, n_steps):
115
  input1 = load_gradio_images_helper(input1)
116
  input2 = load_gradio_images_helper(input2)
117
  extra_images = load_gradio_images_helper(extra_images)
@@ -127,6 +146,12 @@ def create_gradio_interface():
127
  elif isinstance(negative_images, Image.Image):
128
  negative_images = [negative_images]
129
 
 
 
 
 
 
 
130
  alpha_weights = np.linspace(alpha_start, alpha_end, n_steps+2)[1:-1].tolist()
131
  blended_images = run_vibe_blend_not_safe(input1, input2, extra_images, negative_images, DEFAULT_CONFIG_PATH, alpha_weights)
132
  blended_images = create_image_grid(blended_images, rows=np.ceil(len(blended_images)/4).astype(int), cols=4)
@@ -134,6 +159,65 @@ def create_gradio_interface():
134
 
135
  blend_button.click(blend_button_click, inputs=[input1, input2, extra_images, negative_images, alpha_start, alpha_end, n_steps], outputs=[blending_results])
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  example_cases = [
138
  [Image.open("./images/playviolin_hr.png"), Image.open("./images/playguitar_hr.png")],
139
  [Image.open("./images/input_cat.png"), Image.open("./images/input_bread.png")],
@@ -156,14 +240,45 @@ def create_gradio_interface():
156
  [Image.open("./images/pink_bear1.jpg"), Image.open("./images/black_bear2.jpg"), [Image.open("./images/pink_bear1.jpg"), Image.open("./images/black_bear1.jpg")]],
157
  ]
158
  gr.Examples(examples=negative_image_examples, label="Negative Image Examples", inputs=[input1, input2, negative_images], outputs=[blending_results])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
 
 
 
 
 
 
160
  return demo
161
 
162
 
163
  if __name__ == "__main__":
164
  logging.basicConfig(level=logging.INFO)
165
 
166
- demo = create_gradio_interface()
167
  demo.launch(
168
  share=True,
169
  server_name="0.0.0.0" if USE_HUGGINGFACE_ZEROGPU else None,
 
1
  import logging
2
  import os
3
+ import tempfile
4
+ import uuid
5
+ from typing import List, Union, Optional
6
+ from datetime import datetime
7
+ from pathlib import Path
8
 
9
  import gradio as gr
10
  from PIL import Image
11
  import numpy as np
12
+ import pandas as pd
13
 
14
  from vibe_blending import run_vibe_blend_safe, run_vibe_blend_not_safe
15
  from ipadapter_model import create_image_grid
16
+ from feedback_viewer import create_feedback_viewer_tab, store_feedback_to_hf_dataset
17
+
18
+ # Hugging Face Datasets for feedback storage
19
+ try:
20
+ from datasets import Dataset, load_dataset # type: ignore
21
+ from huggingface_hub import login # type: ignore
22
+ HF_DATASETS_AVAILABLE = True
23
+ except ImportError:
24
+ Dataset = None # type: ignore
25
+ load_dataset = None # type: ignore
26
+ login = None # type: ignore
27
+ HF_DATASETS_AVAILABLE = False
28
+ logging.warning("Hugging Face datasets not available. Feedback will not be stored.")
29
 
30
  USE_HUGGINGFACE_ZEROGPU = os.getenv("USE_HUGGINGFACE_ZEROGPU", "false").lower() == "false" #"true"
31
  DEFAULT_CONFIG_PATH = "./config.yaml"
32
+ # Hugging Face Dataset repository for storing feedback
33
+ # Set this to your Hugging Face username/dataset-name, e.g., "your-username/vibe-blending-feedback"
34
+ HF_FEEDBACK_DATASET_REPO = os.getenv("HF_FEEDBACK_DATASET_REPO", None)
35
+ HF_TOKEN = os.getenv("HF_TOKEN", None)
36
 
37
  if USE_HUGGINGFACE_ZEROGPU:
38
  try:
 
83
  return processed_images
84
 
85
 
86
+
87
+
88
+ def create_vibe_blending_tab():
89
+ """Create the vibe blending tab interface."""
90
+ with gr.Tab("Vibe Blending"):
 
 
 
 
 
 
91
  gr.Markdown("""
92
  ## Vibe Blending Demo
93
 
 
97
 
98
  Given a pair of images, vibe blending will generate a set of images that creatively connect the input images.
99
 
 
 
100
  """)
101
  with gr.Row():
102
  with gr.Column():
 
117
  with gr.Row():
118
  extra_images = gr.Gallery(label="Extra Images (optional)", show_label=True, columns=3, rows=2, height=150)
119
  negative_images = gr.Gallery(label="Negative Images (optional)", show_label=True, columns=3, rows=2, height=150)
120
+ with gr.Group():
121
+ gr.Markdown("**Step 3:** Submit your feedback")
122
+ rating = gr.Radio(label="How do you like the results?", choices=["1", "2", "3", "4", "5"])
123
+ feedback_form = gr.TextArea(label="Feedback", show_label=False, lines=1)
124
+ feedback_button = gr.Button("Submit Feedback", variant="secondary", size="sm")
125
+
126
  with gr.Column():
127
  with gr.Group():
128
  # blending_results = gr.Gallery(label="Vibe Blending Results", columns=5, rows=4, height=600)
 
130
  blending_results = gr.Image(label="Vibe Blending Results", show_label=True, height=400)
131
  blend_button = gr.Button("🔴 Run Vibe Blending", variant="primary")
132
 
133
+ def _process_input_images(input1, input2, extra_images, negative_images):
 
134
  input1 = load_gradio_images_helper(input1)
135
  input2 = load_gradio_images_helper(input2)
136
  extra_images = load_gradio_images_helper(extra_images)
 
146
  elif isinstance(negative_images, Image.Image):
147
  negative_images = [negative_images]
148
 
149
+ return input1, input2, extra_images, negative_images
150
+
151
+ # Training wrapper function
152
+ def blend_button_click(input1, input2, extra_images, negative_images, alpha_start, alpha_end, n_steps):
153
+ input1, input2, extra_images, negative_images = _process_input_images(input1, input2, extra_images, negative_images)
154
+
155
  alpha_weights = np.linspace(alpha_start, alpha_end, n_steps+2)[1:-1].tolist()
156
  blended_images = run_vibe_blend_not_safe(input1, input2, extra_images, negative_images, DEFAULT_CONFIG_PATH, alpha_weights)
157
  blended_images = create_image_grid(blended_images, rows=np.ceil(len(blended_images)/4).astype(int), cols=4)
 
159
 
160
  blend_button.click(blend_button_click, inputs=[input1, input2, extra_images, negative_images, alpha_start, alpha_end, n_steps], outputs=[blending_results])
161
 
162
+ def feedback_button_click(rating, feedback_form, input1, input2, extra_images, negative_images, alpha_start, alpha_end, n_steps, blending_results):
163
+ """Handle feedback submission and store to Hugging Face Dataset."""
164
+ if not rating:
165
+ gr.Warning("Please select a rating before submitting feedback.")
166
+ return gr.update(value=None), gr.update(value="")
167
+
168
+ # Validate that required images exist
169
+ if input1 is None:
170
+ gr.Warning("Please upload Input 1 image before submitting feedback.")
171
+ return gr.update(value=rating), gr.update(value=feedback_form)
172
+
173
+ if input2 is None:
174
+ gr.Warning("Please upload Input 2 image before submitting feedback.")
175
+ return gr.update(value=rating), gr.update(value=feedback_form)
176
+
177
+ if blending_results is None:
178
+ gr.Warning("Please run vibe blending first to generate results before submitting feedback.")
179
+ return gr.update(value=rating), gr.update(value=feedback_form)
180
+
181
+ # Process images to check if they exist
182
+ input1_img, input2_img, extra_images_processed, negative_images_processed = _process_input_images(
183
+ input1, input2, extra_images, negative_images
184
+ )
185
+
186
+ # Process blending results
187
+ blended_images = load_gradio_images_helper(blending_results)
188
+
189
+ # Store feedback and images to Hugging Face Dataset
190
+ success = store_feedback_to_hf_dataset(
191
+ rating=rating,
192
+ feedback_text=feedback_form or "",
193
+ alpha_start=alpha_start,
194
+ alpha_end=alpha_end,
195
+ n_steps=n_steps,
196
+ input1_image=input1_img,
197
+ input2_image=input2_img,
198
+ extra_images=extra_images_processed if extra_images_processed else None,
199
+ negative_images=negative_images_processed if negative_images_processed else None,
200
+ blending_result_image=blended_images,
201
+ )
202
+
203
+ if success:
204
+ gr.Info("Thank you! Your feedback has been submitted successfully.")
205
+ return gr.update(value=None), gr.update(value="") # Reset rating and feedback form
206
+ else:
207
+ error_msg = "Feedback could not be stored. "
208
+ if not HF_FEEDBACK_DATASET_REPO:
209
+ error_msg += "Please configure `HF_FEEDBACK_DATASET_REPO` environment variable (e.g., 'your-username/vibe-blending-feedback')."
210
+ else:
211
+ error_msg += "Please check the logs for details."
212
+ gr.Warning(error_msg)
213
+ return gr.update(value=rating), gr.update(value=feedback_form) # Keep rating and feedback form
214
+
215
+ feedback_button.click(
216
+ feedback_button_click,
217
+ inputs=[rating, feedback_form, input1, input2, extra_images, negative_images, alpha_start, alpha_end, n_steps, blending_results],
218
+ outputs=[rating, feedback_form] # Reset rating and feedback form
219
+ )
220
+
221
  example_cases = [
222
  [Image.open("./images/playviolin_hr.png"), Image.open("./images/playguitar_hr.png")],
223
  [Image.open("./images/input_cat.png"), Image.open("./images/input_bread.png")],
 
240
  [Image.open("./images/pink_bear1.jpg"), Image.open("./images/black_bear2.jpg"), [Image.open("./images/pink_bear1.jpg"), Image.open("./images/black_bear1.jpg")]],
241
  ]
242
  gr.Examples(examples=negative_image_examples, label="Negative Image Examples", inputs=[input1, input2, negative_images], outputs=[blending_results])
243
+
244
+
245
+ # Feedback viewer functions moved to feedback_viewer.py
246
+
247
+
248
+ def create_merged_interface():
249
+ """Create merged interface with both tabs."""
250
+ theme = gr.themes.Base(
251
+ spacing_size='md',
252
+ text_size='lg',
253
+ primary_hue='blue',
254
+ neutral_hue='slate',
255
+ secondary_hue='pink'
256
+ )
257
+
258
+ demo = gr.Blocks(theme=theme)
259
+ with demo:
260
+ gr.Markdown("""
261
+ ## Vibe Blending Demo
262
+
263
+ This is the demo for the paper "*Vibe Spaces for Creatively Connecting and Expressing Visual Concepts*".
264
+
265
+ [Paper]() | [Code]() | [Website]()
266
+
267
+ Given a pair of images, vibe blending will generate a set of images that creatively connect the input images.
268
 
269
+ """)
270
+
271
+ # Create both tabs
272
+ create_vibe_blending_tab()
273
+ create_feedback_viewer_tab()
274
+
275
  return demo
276
 
277
 
278
  if __name__ == "__main__":
279
  logging.basicConfig(level=logging.INFO)
280
 
281
+ demo = create_merged_interface()
282
  demo.launch(
283
  share=True,
284
  server_name="0.0.0.0" if USE_HUGGINGFACE_ZEROGPU else None,
requirements.txt CHANGED
@@ -12,3 +12,5 @@ diffusers==0.33.1
12
  transformers==4.47.0
13
  triton==3.0.0
14
  ncut_pytorch==2.3.0
 
 
 
12
  transformers==4.47.0
13
  triton==3.0.0
14
  ncut_pytorch==2.3.0
15
+ datasets
16
+ huggingface_hub