|
import gradio as gr |
|
import requests |
|
import random |
|
import json |
|
import os |
|
from together import Together |
|
|
|
|
|
TOGETHER_API_KEY = os.environ.get('TOGETHER_API_KEY') |
|
|
|
|
|
|
|
client = Together(api_key=TOGETHER_API_KEY) if TOGETHER_API_KEY else None |
|
|
|
|
|
PIXABAY_API_KEY = os.environ.get('PIXABAY_API_KEY') |
|
IMAGE_API_URL = 'https://pixabay.com/api/' |
|
VIDEO_API_URL = 'https://pixabay.com/api/videos/' |
|
PER_PAGE = 5 |
|
|
|
|
|
def search_pixabay(query: str, media_type: str, image_type: str, orientation: str, video_type: str): |
|
""" |
|
Searches the Pixabay API for royalty-free stock images or videos based on user query and filters. |
|
|
|
Args: |
|
query (str): The search term for finding media. If empty, an error is returned. |
|
media_type (str): Specifies the type of media to search for. |
|
Accepted values are "Image" or "Video". |
|
image_type (str): Filter results by image type (used only if media_type is "Image"). |
|
Accepted values: "all", "photo", "illustration", "vector". |
|
orientation (str): Filter results by image orientation (used only if media_type is "Image"). |
|
Accepted values: "all", "horizontal", "vertical". |
|
video_type (str): Filter results by video type (used only if media_type is "Video"). |
|
Accepted values: "all", "film", "animation". |
|
""" |
|
if not query: |
|
return None, None, "Please enter a search query." |
|
|
|
if not PIXABAY_API_KEY: |
|
return None, None, "Pixabay API Key not found. Please set the PIXABAY_API_KEY environment variable." |
|
|
|
params = { |
|
'key': PIXABAY_API_KEY, |
|
'q': query, |
|
'per_page': PER_PAGE, |
|
'page': 1, |
|
'safesearch': 'true' |
|
} |
|
|
|
if media_type == "Image": |
|
api_url = IMAGE_API_URL |
|
params['image_type'] = image_type |
|
params['orientation'] = orientation |
|
elif media_type == "Video": |
|
api_url = VIDEO_API_URL |
|
params['video_type'] = video_type |
|
else: |
|
|
|
return None, None, "Invalid media type selected." |
|
|
|
try: |
|
response = requests.get(api_url, params=params) |
|
response.raise_for_status() |
|
data = response.json() |
|
|
|
if data.get('totalHits', 0) == 0: |
|
return None, None, f"No results found for '{query}'." |
|
|
|
hits = data.get('hits', []) |
|
if not hits: |
|
return None, None, f"No results found for '{query}'." |
|
|
|
selected_hit = random.choice(hits) |
|
|
|
if media_type == "Image": |
|
image_url = selected_hit.get('largeImageURL') |
|
if image_url: |
|
|
|
return image_url, None, "" |
|
else: |
|
return None, None, "Could not retrieve large image URL." |
|
|
|
elif media_type == "Video": |
|
video_urls = selected_hit.get('videos', {}) |
|
large_video = video_urls.get('large', {}) |
|
video_url = large_video.get('url') |
|
|
|
if video_url: |
|
|
|
return None, video_url, "" |
|
else: |
|
|
|
medium_video = video_urls.get('medium', {}) |
|
video_url = medium_video.get('url') |
|
if video_url: |
|
return None, video_url, "Using medium quality video." |
|
else: |
|
return None, None, "Could not retrieve video URL." |
|
|
|
except requests.exceptions.RequestException as e: |
|
return None, None, f"API request error: {e}" |
|
except json.JSONDecodeError: |
|
return None, None, "Error decoding API response." |
|
except Exception as e: |
|
|
|
return None, None, f"An unexpected error occurred: {e}" |
|
|
|
|
|
def together_text_to_image(prompt: str = "", width: int = 1024, height: int = 1024): |
|
""" |
|
Generates an image from a text prompt using the Together AI API and the FLUX.1.1-pro model. |
|
|
|
Args: |
|
prompt (str): The text prompt to generate the image from. This must be a non-empty string. |
|
width (int, optional): The width of the generated image in pixels. |
|
Must be between 512 and 1440. Will auto-adjust if out of bounds. Default is 1024. |
|
height (int, optional): The height of the generated image in pixels. |
|
Must be between 512 and 1440. Will auto-adjust if out of bounds. Default is 1024. |
|
|
|
Returns: |
|
str: The URL of the generated image if successful, or an error message if not. |
|
""" |
|
if not client: |
|
return "Together AI client not initialized. Please set the TOGETHER_API_KEY environment variable." |
|
if not prompt: |
|
return "Please enter a prompt for text-to-image generation." |
|
|
|
|
|
min_size, max_size = 512, 1440 |
|
if width < min_size or width > max_size or height < min_size or height > max_size: |
|
aspect_ratio = width / height |
|
|
|
|
|
if width < min_size or height < min_size: |
|
if width < height: |
|
width = min_size |
|
height = int(round(width / aspect_ratio)) |
|
else: |
|
height = min_size |
|
width = int(round(height * aspect_ratio)) |
|
elif width > max_size or height > max_size: |
|
if width > height: |
|
width = max_size |
|
height = int(round(width / aspect_ratio)) |
|
else: |
|
height = max_size |
|
width = int(round(height * aspect_ratio)) |
|
|
|
|
|
width = max(min_size, min(width, max_size)) |
|
height = max(min_size, min(height, max_size)) |
|
|
|
try: |
|
image_completion = client.images.generate( |
|
model="black-forest-labs/FLUX.1.1-pro", |
|
width=width, |
|
height=height, |
|
steps=40, |
|
prompt=prompt, |
|
) |
|
return image_completion.data[0].url |
|
except Exception as e: |
|
return f"Error generating image from text: {e}" |
|
|
|
|
|
def image_to_url(image_path): |
|
try: |
|
url = 'https://uguu.se/upload' |
|
|
|
with open(image_path, 'rb') as f: |
|
files = {'files[]': (image_path, f)} |
|
response = requests.post(url, files=files) |
|
response_json = response.json() |
|
return response_json['files'][0]['url'] |
|
except FileNotFoundError: |
|
return "Error: File not found. Please check the image path." |
|
except Exception as e: |
|
return f"An error occurred: {e}" |
|
|
|
def together_image_to_image(image_numpy, prompt: str): |
|
""" |
|
Transforms an image based on a text prompt using the Together AI API. |
|
|
|
Args: |
|
image_numpy (numpy.ndarray): The input image as a NumPy array (provided by Gradio). |
|
prompt (str): The text prompt for image transformation. |
|
|
|
Returns: |
|
str: The URL of the transformed image, or an error message. |
|
""" |
|
if not client: |
|
return "Together AI client not initialized. Please set the TOGETHER_API_KEY environment variable." |
|
if image_numpy is None: |
|
return "Please upload or paste an image for image-to-image transformation." |
|
if not prompt: |
|
return "Please enter a prompt for image transformation." |
|
|
|
try: |
|
|
|
print(image_numpy) |
|
|
|
image_completion = client.images.generate( |
|
model="black-forest-labs/FLUX.1-kontext-max", |
|
steps=40, |
|
prompt=prompt, |
|
image_url=image_to_url(image_numpy) |
|
) |
|
return image_completion.data[0].url |
|
except Exception as e: |
|
return f"Error transforming image: {e}" |
|
|
|
|
|
|
|
with gr.Blocks(title="Media Generation and Search Explorer") as demo: |
|
gr.Markdown("## Media Generation and Search Explorer") |
|
gr.Markdown("Explore royalty-free media from Pixabay and generate/transform images using Together AI.") |
|
|
|
with gr.Tab("Pixabay Search"): |
|
gr.Markdown("Search for royalty-free images and videos on Pixabay.") |
|
gr.Warning("This requires setting the PIXABAY_API_KEY environment variable.") |
|
with gr.Row(): |
|
pixabay_query_input = gr.Textbox(label="Search Query", placeholder="e.g., yellow flowers", scale=2) |
|
pixabay_media_type_radio = gr.Radio(["Image", "Video"], label="Media Type", value="Image", scale=1) |
|
pixabay_search_button = gr.Button("Search") |
|
|
|
with gr.Column(visible=True) as pixabay_image_options_col: |
|
pixabay_image_type_input = gr.Radio(["all", "photo", "illustration", "vector"], label="Image Type", value="all") |
|
pixabay_orientation_input = gr.Radio(["all", "horizontal", "vertical"], label="Orientation", value="all") |
|
|
|
with gr.Column(visible=False) as pixabay_video_options_col: |
|
pixabay_video_type_input = gr.Radio(["all", "film", "animation"], label="Video Type", value="all") |
|
|
|
pixabay_status_output = gr.Textbox(label="Status", interactive=False) |
|
|
|
with gr.Row(): |
|
pixabay_image_output = gr.Image(label="Result Image (URL)", interactive=False) |
|
pixabay_video_output = gr.Video(label="Result Video (URL)", interactive=False) |
|
|
|
|
|
def update_pixabay_inputs_blocks(media_type): |
|
if media_type == "Image": |
|
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(visible=False) |
|
elif media_type == "Video": |
|
return gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), gr.update(visible=True) |
|
else: |
|
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(visible=False) |
|
|
|
|
|
pixabay_media_type_radio.change( |
|
fn=update_pixabay_inputs_blocks, |
|
inputs=pixabay_media_type_radio, |
|
outputs=[pixabay_image_options_col, pixabay_video_options_col, pixabay_image_output, pixabay_video_output] |
|
) |
|
|
|
|
|
pixabay_search_button.click( |
|
fn=search_pixabay, |
|
inputs=[ |
|
pixabay_query_input, |
|
pixabay_media_type_radio, |
|
pixabay_image_type_input, |
|
pixabay_orientation_input, |
|
pixabay_video_type_input |
|
], |
|
outputs=[pixabay_image_output, pixabay_video_output, pixabay_status_output] |
|
) |
|
|
|
with gr.Tab("Together AI - Text to Image"): |
|
gr.Markdown("Generate an image from a text prompt using Together AI.") |
|
gr.Warning("This requires setting the TOGETHER_API_KEY environment variable.") |
|
with gr.Row(): |
|
together_text_to_image_prompt = gr.Textbox(label="Enter your prompt", scale=2) |
|
together_text_to_image_width = gr.Slider(label="Width", value=1024, minimum=512, maximum=1440) |
|
together_text_to_image_height = gr.Slider(label="Height", value=1024, minimum=512, maximum=1440) |
|
together_text_to_image_button = gr.Button("Generate Image", scale=1) |
|
together_text_to_image_output = gr.Image(label="Generated Image (URL)", type="filepath", interactive=False) |
|
|
|
together_text_to_image_button.click( |
|
fn=[together_text_to_image, together_text_to_image_width, together_text_to_image_height], |
|
inputs=together_text_to_image_prompt, |
|
outputs=together_text_to_image_output, |
|
) |
|
|
|
with gr.Tab("Together AI - Image to Image"): |
|
gr.Markdown("Transform an uploaded image based on a text prompt using Together AI.") |
|
gr.Warning("This requires setting the TOGETHER_API_KEY environment variable.") |
|
with gr.Row(): |
|
together_image_input = gr.Image(label="Upload or paste an image", type="filepath", scale=2) |
|
together_image_to_image_prompt = gr.Textbox(label="Enter your transformation prompt", scale=2) |
|
together_image_to_image_button = gr.Button("Transform Image", scale=1) |
|
together_image_to_image_output = gr.Image(label="Transformed Image (URL)", type="filepath", interactive=False) |
|
|
|
together_image_to_image_button.click( |
|
fn=together_image_to_image, |
|
inputs=[together_image_input, together_image_to_image_prompt], |
|
outputs=together_image_to_image_output, |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
demo.launch(mcp_server=True) |