ethansteininger's picture
Upload folder using huggingface_hub
cb4f7ee verified
Raw
History Blame Contribute Delete
8.04 kB
import gradio as gr
import requests
import json
from typing import Optional
import base64
API_BASE_URL = "https://api.mixpeek.com/v1"
def encode_file_to_base64(file_path: str) -> str:
"""Encode a file to base64 string."""
with open(file_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
def get_file_type(file_path: str) -> str:
"""Determine file type from extension."""
ext = file_path.lower().split(".")[-1]
video_exts = {"mp4", "mov", "avi", "mkv", "webm", "flv"}
if ext in video_exts:
return "video"
return "image"
def extract_features(
api_key: str,
namespace_id: str,
file: Optional[str],
text_input: str,
input_type: str,
model_choice: str,
) -> str:
"""Extract features from the input using Mixpeek API."""
if not api_key:
return json.dumps({"error": "Please provide your Mixpeek API key"}, indent=2)
if not namespace_id:
return json.dumps({"error": "Please provide your Namespace ID"}, indent=2)
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"X-Namespace": namespace_id,
}
# Map model choice to model name
model_map = {
"Google Multimodal (1408D)": "multimodalembedding",
"OpenAI text-embedding-3-large": "text-embedding-3-large",
"OpenAI text-embedding-3-small": "text-embedding-3-small",
}
model = model_map.get(model_choice, "multimodalembedding")
try:
# Handle text input
if input_type == "Text":
if not text_input.strip():
return json.dumps({"error": "Please provide text input"}, indent=2)
payload = {
"provider": "google" if "multimodal" in model else "openai",
"model": model,
"inputs": {"text": text_input},
"parameters": {}
}
# Handle file input
else:
if not file:
return json.dumps({"error": "Please upload a file"}, indent=2)
file_type = get_file_type(file)
base64_data = encode_file_to_base64(file)
# Only Google multimodal supports image/video embeddings
if "multimodal" not in model:
return json.dumps({
"error": f"OpenAI embedding models only support text. Use 'Google Multimodal (1408D)' for {file_type} embeddings."
}, indent=2)
payload = {
"provider": "google",
"model": model,
"inputs": {
f"{file_type}_base64": base64_data
},
"parameters": {}
}
response = requests.post(
f"{API_BASE_URL}/inference",
headers=headers,
json=payload,
timeout=180
)
if response.status_code == 200:
result = response.json()
# Format the output nicely
output = {
"status": "success",
"model": model,
"input_type": input_type.lower() if input_type == "Text" else get_file_type(file),
}
if "data" in result:
data = result["data"]
if "embeddings" in data:
embeddings = data["embeddings"]
if embeddings and len(embeddings) > 0:
output["embedding_dimensions"] = len(embeddings[0])
output["embedding_preview"] = embeddings[0][:10] # First 10 dims
output["embedding_full"] = embeddings[0]
else:
output["data"] = data
else:
output["raw_response"] = result
if "latency_ms" in result:
output["latency_ms"] = result["latency_ms"]
return json.dumps(output, indent=2)
else:
return json.dumps({
"error": f"API returned status {response.status_code}",
"details": response.text
}, indent=2)
except requests.exceptions.Timeout:
return json.dumps({"error": "Request timed out. Try a smaller file."}, indent=2)
except Exception as e:
return json.dumps({"error": str(e)}, indent=2)
# Build the Gradio interface
with gr.Blocks(
title="Mixpeek Multimodal Feature Extractor",
theme=gr.themes.Soft(),
) as demo:
gr.Markdown("""
# Mixpeek Multimodal Feature Extractor
Extract **1408-dimensional embeddings** from **videos**, **images**, and **text** using
[Mixpeek's](https://mixpeek.com) inference API powered by Google Vertex AI.
**Supported Inputs:**
- **Image**: JPG, PNG, WebP, BMP, GIF
- **Video**: MP4, MOV, AVI, MKV, WebM
- **Text**: Any text string
---
""")
with gr.Row():
with gr.Column(scale=1):
api_key = gr.Textbox(
label="Mixpeek API Key",
placeholder="Enter your API key from mixpeek.com",
type="password",
)
namespace_id = gr.Textbox(
label="Namespace ID",
placeholder="Enter your namespace ID (e.g., ns_abc123)",
info="Required for API access. Find this in your Mixpeek dashboard."
)
input_type = gr.Radio(
choices=["File Upload", "Text"],
value="File Upload",
label="Input Type",
)
file_input = gr.File(
label="Upload File",
file_types=[".mp4", ".mov", ".avi", ".mkv", ".webm", ".flv",
".jpg", ".jpeg", ".png", ".webp", ".bmp", ".gif"],
visible=True,
)
text_input = gr.Textbox(
label="Text Input",
placeholder="Enter text to embed...",
lines=3,
visible=False,
)
model_choice = gr.Dropdown(
choices=[
"Google Multimodal (1408D)",
"OpenAI text-embedding-3-large",
"OpenAI text-embedding-3-small",
],
value="Google Multimodal (1408D)",
label="Embedding Model",
info="Google Multimodal supports text, image, and video. OpenAI models support text only."
)
extract_btn = gr.Button("Extract Embedding", variant="primary", size="lg")
with gr.Column(scale=1):
output = gr.Code(
label="Results",
language="json",
lines=30,
)
# Toggle visibility based on input type
def toggle_input(choice):
if choice == "Text":
return gr.update(visible=False), gr.update(visible=True)
else:
return gr.update(visible=True), gr.update(visible=False)
input_type.change(
toggle_input,
inputs=[input_type],
outputs=[file_input, text_input]
)
# Extract button click handler
extract_btn.click(
extract_features,
inputs=[
api_key,
namespace_id,
file_input,
text_input,
input_type,
model_choice,
],
outputs=[output],
)
gr.Markdown("""
---
### API Usage
```bash
curl -X POST https://api.mixpeek.com/v1/inference \\
-H "Authorization: Bearer YOUR_API_KEY" \\
-H "X-Namespace: YOUR_NAMESPACE_ID" \\
-H "Content-Type: application/json" \\
-d '{
"provider": "google",
"model": "multimodalembedding",
"inputs": {"text": "your text here"},
"parameters": {}
}'
```
### Resources
- [Mixpeek Documentation](https://docs.mixpeek.com)
- [API Reference](https://docs.mixpeek.com/api-reference)
- [Get API Key](https://mixpeek.com)
""")
if __name__ == "__main__":
demo.launch()