| 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, |
| } |
|
|
| |
| 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: |
| |
| 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": {} |
| } |
|
|
| |
| 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) |
|
|
| |
| 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() |
| |
| 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] |
| 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) |
|
|
|
|
| |
| 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, |
| ) |
|
|
| |
| 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_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() |
|
|