| """ |
| Gradio demo for Hugging Face Spaces. |
| Upload a short Minecraft gameplay clip → top-3 action predictions. |
| |
| Deploy: create Space with sdk=gradio, app_file=app.py |
| Requires voxel_scripted.pt in the model repo (download on startup). |
| """ |
|
|
| import os |
| from pathlib import Path |
|
|
| import gradio as gr |
| import torch |
|
|
| from hf_inference import CLASS_NAMES, load_model, predict_video |
|
|
| MODEL_ID = os.environ.get("HF_MODEL_ID", "fotographer/VoxelMind-2M-Minecraft-Classifier") |
| MODEL_FILE = os.environ.get("VOXELMIND_WEIGHTS", "models/voxel_scripted.pt") |
| DEVICE = "cuda" if torch.cuda.is_available() else "cpu" |
|
|
| _model = None |
|
|
|
|
| def get_model(): |
| global _model |
| if _model is None: |
| path = Path(MODEL_FILE) |
| if not path.exists(): |
| from huggingface_hub import hf_hub_download |
|
|
| path = Path( |
| hf_hub_download( |
| repo_id=MODEL_ID, |
| filename=MODEL_FILE, |
| repo_type="model", |
| ) |
| ) |
| _model = load_model(path, DEVICE) |
| return _model |
|
|
|
|
| def run(video_path: str): |
| if not video_path: |
| return "Upload a video first." |
| preds = predict_video(get_model(), video_path, device=DEVICE, topk=3) |
| lines = [f"**{name}** — {prob * 100:.1f}%" for name, prob in preds] |
| return "\n\n".join(lines) |
|
|
|
|
| demo = gr.Interface( |
| fn=run, |
| inputs=gr.Video(label="Minecraft clip (≥22 frames recommended)"), |
| outputs=gr.Markdown(label="Top-3 predictions"), |
| title="VoxelMind action classifier", |
| description=( |
| "Classifies player actions from 22×64×64 grayscale frames. " |
| f"Classes: {', '.join(CLASS_NAMES)}. " |
| "Inference uses a TorchScript export — architecture source is not published." |
| ), |
| examples=[], |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|