omarkashif's picture
Update app.py
b00ec0a verified
Raw History Blame Contribute Delete
3.23 kB
"""
AiGiS Safety Captioning — Hugging Face Space (Gradio UI).
Same pipeline as the FastAPI service in ../src/api.py, wrapped in a simple
Gradio interface for HF Spaces:
image in -> YOLO (detector.py) -> structured detections + compliance
-> Claude (vlm_caption.py) -> safety observation
-> annotated image + caption shown in the UI
The YOLO weights are pulled once at startup from the Hugging Face model repo
below, so no local .pt file is needed in this Space.
Every Gradio app also exposes an automatic API (see the "Use via API" link at
the bottom of the Space page), so this doubles as a callable endpoint too.
Requires the ANTHROPIC_API_KEY secret to be set in the Space settings.
"""
from __future__ import annotations
import os
import cv2
import gradio as gr
import numpy as np
import spaces
from huggingface_hub import hf_hub_download
import vlm_caption
from detector import SafetyDetector
HF_REPO_ID = os.environ.get("AIGIS_HF_REPO_ID", "omarkashif/hockey-yolo-models")
HF_FILENAME = os.environ.get("AIGIS_HF_FILENAME", "aigis/yolov8s.pt")
DATA_YAML = os.environ.get("AIGIS_DATA_YAML", "sh17.yaml")
CONF = float(os.environ.get("AIGIS_CONF", "0.25"))
# Load the model on CPU at startup. Actual GPU attachment (ZeroGPU) only
# happens inside the @spaces.GPU-decorated function below, at inference time.
weights_path = hf_hub_download(repo_id=HF_REPO_ID, filename=HF_FILENAME)
detector = SafetyDetector(weights_path, DATA_YAML, conf=CONF)
@spaces.GPU(duration=60)
def run(image: np.ndarray, skip_vlm: bool):
if image is None:
return None, "Upload an image first.", {}
# Gradio gives RGB; Ultralytics/OpenCV (and our detector) work in BGR.
frame_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
det_result, annotated_bgr = detector.detect_and_annotate(frame_bgr, name="upload.jpg")
annotated_rgb = cv2.cvtColor(annotated_bgr, cv2.COLOR_BGR2RGB)
det_dict = det_result.to_dict()
if skip_vlm:
return annotated_rgb, "_(VLM captioning skipped)_", det_dict
if "ANTHROPIC_API_KEY" not in os.environ:
return annotated_rgb, "**Error:** ANTHROPIC_API_KEY is not set for this Space.", det_dict
ok, buf = cv2.imencode(".jpg", frame_bgr)
vlm_result = vlm_caption.caption_bytes(buf.tobytes(), "image/jpeg", det_dict)
caption_md = (
f"**Caption:** {vlm_result.get('caption', '(parse error)')}\n\n"
f"**Safety observation:** {vlm_result.get('safety_observation', '')}\n\n"
f"**Severity:** {vlm_result.get('severity', 'n/a')}"
)
return annotated_rgb, caption_md, det_dict
demo = gr.Interface(
fn=run,
inputs=[
gr.Image(type="numpy", label="Upload image"),
gr.Checkbox(label="Skip VLM caption (detector only, no API cost)"),
],
outputs=[
gr.Image(label="Annotated detections"),
gr.Markdown(label="Safety caption"),
gr.JSON(label="Raw detections + compliance"),
],
title="AiGiS Safety Captioning",
description=(
"Upload a workplace image. YOLO detects PPE compliance deterministically; "
"Claude turns those findings into a grounded safety observation."
),
)
if __name__ == "__main__":
demo.launch()