api-mcp / app.py
KingNish's picture
Update app.py
a028328 verified
raw
history blame
13.3 kB
import gradio as gr
import requests
import random
import json
import os
from together import Together
# --- 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 = "", 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."
# Clamp dimensions while preserving aspect ratio
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
# Adjust based on which dimension is more out of bounds
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))
# Re-clamp just in case rounding pushed a value out of range
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", # Hardcoded model
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", # 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_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,
)
# --- Launch the Gradio app ---
if __name__ == "__main__":
demo.launch(mcp_server=True)