Spaces:
Running
Running
import gradio as gr | |
import requests | |
import random | |
import json | |
import os | |
from together import Together | |
import base64 | |
from PIL import Image | |
import io | |
# --- Environment Variable for Together API Key --- | |
TOGETHER_API_KEY = os.environ.get('TOGETHER_API_KEY') | |
# --- Together API Client Configuration --- | |
# Initialize the Together client only if the API key is available | |
client = Together(api_key=TOGETHER_API_KEY) if TOGETHER_API_KEY else None | |
# --- Pixabay API Configuration --- | |
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 | |
# --- Function to search Pixabay --- | |
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: | |
# This case should not be reachable with the Gradio Radio component | |
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 the image URL, None for video, and an empty status message | |
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 for image, the video URL, and an empty status message | |
return None, video_url, "" | |
else: | |
# Fallback to medium quality if large is not available | |
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: | |
# Catch any other unexpected errors | |
return None, None, f"An unexpected error occurred: {e}" | |
# --- Together AI Image Generation Functions --- | |
def together_text_to_image(prompt: str): | |
""" | |
Generates an image from text using the Together AI API. | |
Args: | |
prompt (str): The text prompt for image generation. | |
Returns: | |
str: The URL of the generated image, or an error message. | |
""" | |
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." | |
try: | |
image_completion = client.images.generate( | |
model="black-forest-labs/FLUX.1.1-pro", # Hardcoded model as requested | |
width=1024, | |
height=768, | |
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", # Hardcoded model as requested | |
steps=40, # Hardcoded steps as requested | |
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}" | |
# --- Gradio Blocks Interface Definition --- | |
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) | |
# Logic to toggle visibility of input columns and output components based on media type selection | |
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) | |
# Trigger the update_pixabay_inputs_blocks function when media_type_radio changes | |
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] | |
) | |
# Trigger the search_pixabay function when the search button is clicked | |
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_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, | |
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, | |
) | |
# --- Launch the Gradio app --- | |
if __name__ == "__main__": | |
demo.launch(mcp_server=True) |