import spaces import gradio as gr import numpy as np import torch import cv2 import requests import json from PIL import Image from router import resolve_tool, call_tool, list_tools # ── YOLO ────────────────────────────────────────────────────────────────────── from ultralytics import YOLO @spaces.GPU def run_yolo(image, model_id="yolo11n.pt", conf=0.25, iou=0.45): model = YOLO(model_id) results = model(image, conf=conf, iou=iou) annotated = results[0].plot() return Image.fromarray(annotated[..., ::-1]) # ── MediaPipe Face Detection ─────────────────────────────────────────────────── import mediapipe as mp mp_face = mp.solutions.face_detection mp_draw = mp.solutions.drawing_utils def run_face_detection(image: np.ndarray, model_sel=1, min_conf=0.5): with mp_face.FaceDetection(model_selection=model_sel, min_detection_confidence=min_conf) as det: results = det.process(image) out = image[:, :, ::-1].copy() if results.detections: for d in results.detections: mp_draw.draw_detection(out, d) return out[:, :, ::-1] # ── IP-Adapter FaceID SDXL ──────────────────────────────────────────────────── _pipe = None def _load_pipe(): global _pipe if _pipe is not None: return _pipe from diffusers import DDIMScheduler, StableDiffusionXLPipeline from huggingface_hub import hf_hub_download from insightface.app import FaceAnalysis import ipown scheduler = DDIMScheduler( num_train_timesteps=1000, beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear", clip_sample=False, set_alpha_to_one=False, steps_offset=1, ) pipe = StableDiffusionXLPipeline.from_pretrained( "frankjoshua/juggernautXL_v8Rundiffusion", torch_dtype=torch.float16, scheduler=scheduler, add_watermarker=False, ) ip_ckpt = hf_hub_download( repo_id="h94/IP-Adapter-FaceID", filename="ip-adapter-faceid_sdxl.bin", repo_type="model" ) ip_model = ipown.IPAdapterFaceIDXL(pipe, ip_ckpt, "cuda") _pipe = ip_model return _pipe @spaces.GPU def run_faceid(face_image, prompt, neg_prompt="monochrome, lowres, bad anatomy", scale=0.8, steps=30): ip_model = _load_pipe() face_app = FaceAnalysis(name="buffalo_l", providers=["CUDAExecutionProvider"]) face_app.prepare(ctx_id=0, det_size=(640, 640)) img = np.array(face_image) img_bgr = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) faces = face_app.get(img_bgr) if not faces: return None, "No face detected in input image" embeds = torch.from_numpy(faces[0].normed_embedding).unsqueeze(0) images = ip_model.generate( prompt=prompt, negative_prompt=neg_prompt, faceid_embeds=embeds, scale=scale, num_samples=1, width=1024, height=1024, num_inference_steps=steps, ) return images[0], "Done" # ── API endpoint ─────────────────────────────────────────────────────────────── # Dashboard can POST to /api/predict with: # {"tool": "yolo"|"face"|"faceid", "data": [...]} # Gradio exposes this automatically via its REST API at /api/predict # ── UI ──────────────────────────────────────────────────────────────────────── with gr.Blocks(title="AI Hub", theme=gr.themes.Soft()) as demo: gr.Markdown("# 🧠 AI Hub — bovi1") gr.Markdown("All tools in one place. Each tab exposes a `/api/predict` endpoint your dashboard can call.") with gr.Tab("🎯 YOLO Object Detection"): with gr.Row(): yolo_in = gr.Image(label="Input", type="pil") yolo_out = gr.Image(label="Detections") with gr.Row(): yolo_model = gr.Dropdown( ["yolo11n.pt","yolo11s.pt","yolo11m.pt","yolo11l.pt","yolo11x.pt"], value="yolo11n.pt", label="Model" ) yolo_conf = gr.Slider(0.1, 0.9, value=0.25, label="Confidence") yolo_iou = gr.Slider(0.1, 0.9, value=0.45, label="IoU") gr.Button("Run", variant="primary").click( run_yolo, [yolo_in, yolo_model, yolo_conf, yolo_iou], yolo_out ) gr.Markdown("`POST /api/predict` — fn_index 0") with gr.Tab("👤 Face Detection"): with gr.Row(): face_in = gr.Image(label="Input", type="numpy") face_out = gr.Image(label="Detections") with gr.Row(): face_model = gr.Radio([0, 1], value=1, label="Model (0=short, 1=full)") face_conf = gr.Slider(0.1, 1.0, value=0.5, label="Min Confidence") gr.Button("Run", variant="primary").click( run_face_detection, [face_in, face_model, face_conf], face_out ) gr.Markdown("`POST /api/predict` — fn_index 1") with gr.Tab("🎨 FaceID Image Gen (SDXL)"): with gr.Row(): faceid_in = gr.Image(label="Face Image", type="pil") faceid_out = gr.Image(label="Generated") faceid_prompt = gr.Textbox(label="Prompt", placeholder="portrait of a person in a cyberpunk city") faceid_neg = gr.Textbox(label="Negative Prompt", value="monochrome, lowres, bad anatomy") with gr.Row(): faceid_scale = gr.Slider(0.1, 1.0, value=0.8, label="FaceID Scale") faceid_steps = gr.Slider(10, 50, value=30, step=1, label="Steps") faceid_status = gr.Textbox(label="Status", interactive=False) gr.Button("Generate", variant="primary").click( run_faceid, [faceid_in, faceid_prompt, faceid_neg, faceid_scale, faceid_steps], [faceid_out, faceid_status] ) gr.Markdown("`POST /api/predict` — fn_index 2") with gr.Tab("🔍 GMI Promo Watcher"): gr.HTML('') with gr.Tab("🚦 Smart Router"): gr.Markdown("Describe what you want — the router picks the best tool and runs it.") with gr.Row(): with gr.Column(): router_task = gr.Textbox(label="Task", placeholder="remove background from image") router_prompt = gr.Textbox(label="Prompt (if needed)", placeholder="a cat sitting on a cloud") router_image = gr.Image(label="Input Image (if needed)", type="pil") router_text = gr.Textbox(label="Text (for TTS)", placeholder="Hello world") router_tool = gr.Dropdown( choices=["auto"] + [t["key"] for t in list_tools()], value="auto", label="Force Tool (optional)" ) router_btn = gr.Button("Run", variant="primary") with gr.Column(): router_out_img = gr.Image(label="Output Image/Video") router_out_json = gr.JSON(label="Full Result") router_status = gr.Textbox(label="Tool Used", interactive=False) def run_router(task, prompt, image, text, tool_override): override = None if tool_override == "auto" else tool_override tool = resolve_tool(task, override) if not tool: return None, {"error": "Could not match task to a tool"}, "No match" inputs = {"prompt": prompt or task, "image": image, "text": text} result = call_tool(tool["key"], inputs) # Extract image result if present out_img = None raw = result.get("result") if isinstance(raw, str) and (raw.endswith(".png") or raw.endswith(".jpg") or raw.endswith(".mp4")): out_img = raw elif isinstance(raw, list) and len(raw) > 0: out_img = raw[0] return out_img, result, f"{tool['key']} → {tool['space']}" router_btn.click( run_router, [router_task, router_prompt, router_image, router_text, router_tool], [router_out_img, router_out_json, router_status] ) gr.Markdown("### Available Tools") tools_md = "\n".join([f"| `{t['key']}` | {t['task']} | {t['desc']} | `{t['space']}` |" for t in list_tools()]) gr.Markdown(f"| Key | Task | Description | Space |\n|---|---|---|---|\n{tools_md}") with gr.Tab("📡 Dashboard API"): gr.Markdown(""" ## How to call from your dashboard Each tool is available at this Space's `/api/predict` endpoint. ### YOLO (fn_index=0) ```js const res = await fetch("https://bovi1-ai-hub.hf.space/api/predict", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({ fn_index: 0, data: [imageBase64, "yolo11n.pt", 0.25, 0.45] }) }); const { data } = await res.json(); // data[0] = annotated image ``` ### Face Detection (fn_index=1) ```js body: JSON.stringify({ fn_index: 1, data: [imageBase64, 1, 0.5] }) ``` ### FaceID Gen (fn_index=2) ```js body: JSON.stringify({ fn_index: 2, data: [faceImageBase64, "your prompt", "negative prompt", 0.8, 30] }) ``` ### GMI Promo Watcher API ```js const res = await fetch("https://bovi1-gmi-promo-watcher.hf.space/api/predict", { method: "POST", body: JSON.stringify({ fn_index: 0, data: [] }) // triggers manual check }); ``` """) demo.queue().launch(server_name="0.0.0.0", server_port=7860)