Update app.py
Browse files
app.py
CHANGED
@@ -9,8 +9,7 @@ from together import Together
|
|
9 |
TOGETHER_API_KEY = os.environ.get('TOGETHER_API_KEY')
|
10 |
|
11 |
# --- Together API Client Configuration ---
|
12 |
-
|
13 |
-
client = Together(api_key=TOGETHER_API_KEY) if TOGETHER_API_KEY else None
|
14 |
|
15 |
# --- Pixabay API Configuration ---
|
16 |
PIXABAY_API_KEY = os.environ.get('PIXABAY_API_KEY')
|
@@ -18,21 +17,50 @@ IMAGE_API_URL = 'https://pixabay.com/api/'
|
|
18 |
VIDEO_API_URL = 'https://pixabay.com/api/videos/'
|
19 |
PER_PAGE = 5
|
20 |
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
"""
|
24 |
-
Searches the Pixabay API for royalty-free stock images or videos based on user query and filters.
|
25 |
|
26 |
Args:
|
27 |
-
query (str): The search term for finding media.
|
28 |
media_type (str): Specifies the type of media to search for.
|
29 |
-
Accepted values are "Image" or "Video".
|
30 |
image_type (str): Filter results by image type (used only if media_type is "Image").
|
31 |
-
Accepted values: "all", "photo", "illustration", "vector".
|
32 |
orientation (str): Filter results by image orientation (used only if media_type is "Image").
|
33 |
-
Accepted values: "all", "horizontal", "vertical".
|
34 |
video_type (str): Filter results by video type (used only if media_type is "Video").
|
35 |
-
Accepted values: "all", "film", "animation".
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
"""
|
37 |
if not query:
|
38 |
return None, None, "Please enter a search query."
|
@@ -56,7 +84,6 @@ def search_pixabay(query: str, media_type: str, image_type: str, orientation: st
|
|
56 |
api_url = VIDEO_API_URL
|
57 |
params['video_type'] = video_type
|
58 |
else:
|
59 |
-
# This case should not be reachable with the Gradio Radio component
|
60 |
return None, None, "Invalid media type selected."
|
61 |
|
62 |
try:
|
@@ -76,7 +103,6 @@ def search_pixabay(query: str, media_type: str, image_type: str, orientation: st
|
|
76 |
if media_type == "Image":
|
77 |
image_url = selected_hit.get('largeImageURL')
|
78 |
if image_url:
|
79 |
-
# Return the image URL, None for video, and an empty status message
|
80 |
return image_url, None, ""
|
81 |
else:
|
82 |
return None, None, "Could not retrieve large image URL."
|
@@ -87,10 +113,8 @@ def search_pixabay(query: str, media_type: str, image_type: str, orientation: st
|
|
87 |
video_url = large_video.get('url')
|
88 |
|
89 |
if video_url:
|
90 |
-
# Return None for image, the video URL, and an empty status message
|
91 |
return None, video_url, ""
|
92 |
else:
|
93 |
-
# Fallback to medium quality if large is not available
|
94 |
medium_video = video_urls.get('medium', {})
|
95 |
video_url = medium_video.get('url')
|
96 |
if video_url:
|
@@ -103,20 +127,18 @@ def search_pixabay(query: str, media_type: str, image_type: str, orientation: st
|
|
103 |
except json.JSONDecodeError:
|
104 |
return None, None, "Error decoding API response."
|
105 |
except Exception as e:
|
106 |
-
# Catch any other unexpected errors
|
107 |
return None, None, f"An unexpected error occurred: {e}"
|
108 |
|
109 |
-
# --- Together AI Image Generation Functions ---
|
110 |
def together_text_to_image(prompt: str = "", width: int = 1024, height: int = 1024):
|
111 |
"""
|
112 |
Generates an image from a text prompt using the Together AI API and the FLUX.1.1-pro model.
|
113 |
|
114 |
Args:
|
115 |
-
prompt (str): The text prompt to generate the image from.
|
116 |
-
width (int
|
117 |
-
Must be between 512 and 1440.
|
118 |
-
height (int
|
119 |
-
Must be between 512 and 1440.
|
120 |
|
121 |
Returns:
|
122 |
str: The URL of the generated image if successful, or an error message if not.
|
@@ -131,7 +153,6 @@ def together_text_to_image(prompt: str = "", width: int = 1024, height: int = 10
|
|
131 |
if width < min_size or width > max_size or height < min_size or height > max_size:
|
132 |
aspect_ratio = width / height
|
133 |
|
134 |
-
# Adjust based on which dimension is more out of bounds
|
135 |
if width < min_size or height < min_size:
|
136 |
if width < height:
|
137 |
width = min_size
|
@@ -147,13 +168,12 @@ def together_text_to_image(prompt: str = "", width: int = 1024, height: int = 10
|
|
147 |
height = max_size
|
148 |
width = int(round(height * aspect_ratio))
|
149 |
|
150 |
-
# Re-clamp just in case rounding pushed a value out of range
|
151 |
width = max(min_size, min(width, max_size))
|
152 |
height = max(min_size, min(height, max_size))
|
153 |
|
154 |
try:
|
155 |
image_completion = client.images.generate(
|
156 |
-
model="black-forest-labs/FLUX.1.1-pro",
|
157 |
width=width,
|
158 |
height=height,
|
159 |
steps=40,
|
@@ -163,27 +183,12 @@ def together_text_to_image(prompt: str = "", width: int = 1024, height: int = 10
|
|
163 |
except Exception as e:
|
164 |
return f"Error generating image from text: {e}"
|
165 |
|
166 |
-
|
167 |
-
def image_to_url(image_path):
|
168 |
-
try:
|
169 |
-
url = 'https://uguu.se/upload'
|
170 |
-
|
171 |
-
with open(image_path, 'rb') as f:
|
172 |
-
files = {'files[]': (image_path, f)}
|
173 |
-
response = requests.post(url, files=files)
|
174 |
-
response_json = response.json()
|
175 |
-
return response_json['files'][0]['url']
|
176 |
-
except FileNotFoundError:
|
177 |
-
return "Error: File not found. Please check the image path."
|
178 |
-
except Exception as e:
|
179 |
-
return f"An error occurred: {e}"
|
180 |
-
|
181 |
-
def together_image_to_image(image_numpy, prompt: str):
|
182 |
"""
|
183 |
Transforms an image based on a text prompt using the Together AI API.
|
184 |
|
185 |
Args:
|
186 |
-
|
187 |
prompt (str): The text prompt for image transformation.
|
188 |
|
189 |
Returns:
|
@@ -191,26 +196,26 @@ def together_image_to_image(image_numpy, prompt: str):
|
|
191 |
"""
|
192 |
if not client:
|
193 |
return "Together AI client not initialized. Please set the TOGETHER_API_KEY environment variable."
|
194 |
-
if
|
195 |
return "Please upload or paste an image for image-to-image transformation."
|
196 |
if not prompt:
|
197 |
return "Please enter a prompt for image transformation."
|
198 |
|
199 |
try:
|
200 |
-
|
201 |
-
|
|
|
202 |
|
203 |
image_completion = client.images.generate(
|
204 |
-
model="black-forest-labs/FLUX.1-kontext-max",
|
205 |
-
steps=40,
|
206 |
prompt=prompt,
|
207 |
-
image_url=
|
208 |
)
|
209 |
return image_completion.data[0].url
|
210 |
except Exception as e:
|
211 |
return f"Error transforming image: {e}"
|
212 |
|
213 |
-
|
214 |
# --- Gradio Blocks Interface Definition ---
|
215 |
with gr.Blocks(title="Media Generation and Search Explorer") as demo:
|
216 |
gr.Markdown("## Media Generation and Search Explorer")
|
@@ -237,25 +242,27 @@ with gr.Blocks(title="Media Generation and Search Explorer") as demo:
|
|
237 |
pixabay_image_output = gr.Image(label="Result Image (URL)", interactive=False)
|
238 |
pixabay_video_output = gr.Video(label="Result Video (URL)", interactive=False)
|
239 |
|
240 |
-
# Logic to toggle visibility of input columns and output components based on media type selection
|
241 |
def update_pixabay_inputs_blocks(media_type):
|
|
|
242 |
if media_type == "Image":
|
243 |
-
return gr.update(visible=True), gr.update(visible=False),
|
|
|
244 |
elif media_type == "Video":
|
245 |
-
return gr.update(visible=False), gr.update(visible=True),
|
|
|
246 |
else:
|
247 |
-
return gr.update(visible=True), gr.update(visible=False),
|
|
|
248 |
|
249 |
-
# Trigger the update_pixabay_inputs_blocks function when media_type_radio changes
|
250 |
pixabay_media_type_radio.change(
|
251 |
fn=update_pixabay_inputs_blocks,
|
252 |
inputs=pixabay_media_type_radio,
|
253 |
-
outputs=[pixabay_image_options_col, pixabay_video_options_col,
|
|
|
254 |
api_name=False,
|
255 |
show_api=False
|
256 |
)
|
257 |
|
258 |
-
# Trigger the search_pixabay function when the search button is clicked
|
259 |
pixabay_search_button.click(
|
260 |
fn=search_pixabay,
|
261 |
inputs=[
|
|
|
9 |
TOGETHER_API_KEY = os.environ.get('TOGETHER_API_KEY')
|
10 |
|
11 |
# --- Together API Client Configuration ---
|
12 |
+
client = Together(api_key=TOGETHER_API_KEY)
|
|
|
13 |
|
14 |
# --- Pixabay API Configuration ---
|
15 |
PIXABAY_API_KEY = os.environ.get('PIXABAY_API_KEY')
|
|
|
17 |
VIDEO_API_URL = 'https://pixabay.com/api/videos/'
|
18 |
PER_PAGE = 5
|
19 |
|
20 |
+
def image_to_url(image_path):
|
21 |
+
"""
|
22 |
+
Uploads an image to a temporary hosting service and returns its URL.
|
23 |
+
|
24 |
+
Args:
|
25 |
+
image_path (str): The path to the image file to be uploaded.
|
26 |
+
|
27 |
+
Returns:
|
28 |
+
str: The URL of the uploaded image, or an error message if the upload fails.
|
29 |
+
"""
|
30 |
+
try:
|
31 |
+
url = 'https://uguu.se/upload'
|
32 |
+
|
33 |
+
with open(image_path, 'rb') as f:
|
34 |
+
files = {'files[]': (image_path, f)}
|
35 |
+
response = requests.post(url, files=files)
|
36 |
+
response_json = response.json()
|
37 |
+
return response_json['files'][0]['url']
|
38 |
+
except FileNotFoundError:
|
39 |
+
return "Error: File not found. Please check the image path."
|
40 |
+
except Exception as e:
|
41 |
+
return f"An error occurred: {e}"
|
42 |
+
|
43 |
+
def search_pixabay(query: str = "", media_type: str = "Image", image_type: str = "all",
|
44 |
+
orientation: str = "all", video_type: str = "all"):
|
45 |
"""
|
46 |
+
Searches the Pixabay API for royalty-free stock images or videos based on user's query and filters.
|
47 |
|
48 |
Args:
|
49 |
+
query (str): The search term for finding stock media.
|
50 |
media_type (str): Specifies the type of media to search for.
|
51 |
+
Accepted values are "Image" or "Video". Defaults to "Image".
|
52 |
image_type (str): Filter results by image type (used only if media_type is "Image").
|
53 |
+
Accepted values: "all", "photo", "illustration", "vector". Defaults to "all".
|
54 |
orientation (str): Filter results by image orientation (used only if media_type is "Image").
|
55 |
+
Accepted values: "all", "horizontal", "vertical". Defaults to "all".
|
56 |
video_type (str): Filter results by video type (used only if media_type is "Video").
|
57 |
+
Accepted values: "all", "film", "animation". Defaults to "all".
|
58 |
+
|
59 |
+
Returns:
|
60 |
+
tuple: Contains three elements:
|
61 |
+
- str: URL of the found image (or None if not found or media_type is "Video")
|
62 |
+
- str: URL of the found video (or None if not found or media_type is "Image")
|
63 |
+
- str: Status message or error message
|
64 |
"""
|
65 |
if not query:
|
66 |
return None, None, "Please enter a search query."
|
|
|
84 |
api_url = VIDEO_API_URL
|
85 |
params['video_type'] = video_type
|
86 |
else:
|
|
|
87 |
return None, None, "Invalid media type selected."
|
88 |
|
89 |
try:
|
|
|
103 |
if media_type == "Image":
|
104 |
image_url = selected_hit.get('largeImageURL')
|
105 |
if image_url:
|
|
|
106 |
return image_url, None, ""
|
107 |
else:
|
108 |
return None, None, "Could not retrieve large image URL."
|
|
|
113 |
video_url = large_video.get('url')
|
114 |
|
115 |
if video_url:
|
|
|
116 |
return None, video_url, ""
|
117 |
else:
|
|
|
118 |
medium_video = video_urls.get('medium', {})
|
119 |
video_url = medium_video.get('url')
|
120 |
if video_url:
|
|
|
127 |
except json.JSONDecodeError:
|
128 |
return None, None, "Error decoding API response."
|
129 |
except Exception as e:
|
|
|
130 |
return None, None, f"An unexpected error occurred: {e}"
|
131 |
|
|
|
132 |
def together_text_to_image(prompt: str = "", width: int = 1024, height: int = 1024):
|
133 |
"""
|
134 |
Generates an image from a text prompt using the Together AI API and the FLUX.1.1-pro model.
|
135 |
|
136 |
Args:
|
137 |
+
prompt (str): The text prompt to generate the image from.
|
138 |
+
width (int): The width of the generated image in pixels.
|
139 |
+
Must be between 512 and 1440. Defaults to 1024.
|
140 |
+
height (int): The height of the generated image in pixels.
|
141 |
+
Must be between 512 and 1440. Defaults to 1024.
|
142 |
|
143 |
Returns:
|
144 |
str: The URL of the generated image if successful, or an error message if not.
|
|
|
153 |
if width < min_size or width > max_size or height < min_size or height > max_size:
|
154 |
aspect_ratio = width / height
|
155 |
|
|
|
156 |
if width < min_size or height < min_size:
|
157 |
if width < height:
|
158 |
width = min_size
|
|
|
168 |
height = max_size
|
169 |
width = int(round(height * aspect_ratio))
|
170 |
|
|
|
171 |
width = max(min_size, min(width, max_size))
|
172 |
height = max(min_size, min(height, max_size))
|
173 |
|
174 |
try:
|
175 |
image_completion = client.images.generate(
|
176 |
+
model="black-forest-labs/FLUX.1.1-pro",
|
177 |
width=width,
|
178 |
height=height,
|
179 |
steps=40,
|
|
|
183 |
except Exception as e:
|
184 |
return f"Error generating image from text: {e}"
|
185 |
|
186 |
+
def together_image_to_image(image_path: str = None, prompt: str = ""):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
"""
|
188 |
Transforms an image based on a text prompt using the Together AI API.
|
189 |
|
190 |
Args:
|
191 |
+
image_path (str): The path to the input image file.
|
192 |
prompt (str): The text prompt for image transformation.
|
193 |
|
194 |
Returns:
|
|
|
196 |
"""
|
197 |
if not client:
|
198 |
return "Together AI client not initialized. Please set the TOGETHER_API_KEY environment variable."
|
199 |
+
if image_path is None:
|
200 |
return "Please upload or paste an image for image-to-image transformation."
|
201 |
if not prompt:
|
202 |
return "Please enter a prompt for image transformation."
|
203 |
|
204 |
try:
|
205 |
+
image_url = image_to_url(image_path)
|
206 |
+
if isinstance(image_url, str) and image_url.startswith("Error"):
|
207 |
+
return image_url
|
208 |
|
209 |
image_completion = client.images.generate(
|
210 |
+
model="black-forest-labs/FLUX.1-kontext-max",
|
211 |
+
steps=40,
|
212 |
prompt=prompt,
|
213 |
+
image_url=image_url
|
214 |
)
|
215 |
return image_completion.data[0].url
|
216 |
except Exception as e:
|
217 |
return f"Error transforming image: {e}"
|
218 |
|
|
|
219 |
# --- Gradio Blocks Interface Definition ---
|
220 |
with gr.Blocks(title="Media Generation and Search Explorer") as demo:
|
221 |
gr.Markdown("## Media Generation and Search Explorer")
|
|
|
242 |
pixabay_image_output = gr.Image(label="Result Image (URL)", interactive=False)
|
243 |
pixabay_video_output = gr.Video(label="Result Video (URL)", interactive=False)
|
244 |
|
|
|
245 |
def update_pixabay_inputs_blocks(media_type):
|
246 |
+
"""Updates the visibility of input columns based on selected media type."""
|
247 |
if media_type == "Image":
|
248 |
+
return (gr.update(visible=True), gr.update(visible=False),
|
249 |
+
gr.update(visible=True), gr.update(visible=False))
|
250 |
elif media_type == "Video":
|
251 |
+
return (gr.update(visible=False), gr.update(visible=True),
|
252 |
+
gr.update(visible=False), gr.update(visible=True))
|
253 |
else:
|
254 |
+
return (gr.update(visible=True), gr.update(visible=False),
|
255 |
+
gr.update(visible=True), gr.update(visible=False))
|
256 |
|
|
|
257 |
pixabay_media_type_radio.change(
|
258 |
fn=update_pixabay_inputs_blocks,
|
259 |
inputs=pixabay_media_type_radio,
|
260 |
+
outputs=[pixabay_image_options_col, pixabay_video_options_col,
|
261 |
+
pixabay_image_output, pixabay_video_output],
|
262 |
api_name=False,
|
263 |
show_api=False
|
264 |
)
|
265 |
|
|
|
266 |
pixabay_search_button.click(
|
267 |
fn=search_pixabay,
|
268 |
inputs=[
|