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)