Views
No views yet
facebook/bart-large-mnli used strictly for zero-shot text classification into a closed label set (92 actions × 10 emotions × 78 scenes). Rendering is pure procedural PIL code — we draw every bone, every joint, every backdrop ourselves.1from skeleton_gif_model import SkeletonGif
2
3model = SkeletonGif.from_pretrained("ocmannazirbriet/skeleton-gif") # or local dir
4out = model("a sad man reading a book in a bedroom")
5
6print(out.action, out.emotion, out.scene) # 'reading' 'sad' 'bedroom'
7out.save("result.gif")pip install -r requirements.txtpillow, transformers, torch, huggingface_hub.facebook/bart-large-mnli is downloaded (~1.6 GB) and cached. Prompts that match built-in keyword rules skip the classifier entirely.prompt ──(keyword match / BART zero-shot)──▶ (action, emotion, scene)
──(procedural PIL render, 24 frames)──▶ .gifSkeletonGif.__call__ routes the prompt through a deterministic keyword matcher; if nothing unambiguous hits, it falls back to zero-shot classification over the closed label set. Confidence thresholds on each channel (action ≥ 0.35, emotion ≥ 0.55, scene ≥ 0.55) send low-confidence calls to safe defaults (standing_idle / neutral / none).action_X(t ∈ [0, 1)) -> {joint_id: (x, y)} computing joint positions at frame t. 15-joint OpenPose-style rig.SkeletonGifOutput dataclass:| field | type | description |
|---|---|---|
prompt | str | original input |
action | str | one of 92 closed-set labels |
emotion | str | one of 10 closed-set labels |
scene | str | one of 78 closed-set labels (or "none") |
gif_bytes | bytes | GIF payload — write directly or .save(path) |
config.json for the full canonical label lists. A few highlights:none).gif — PIL writes the bytes directly.(prompt, engine version) the output is bit-identical.@software{skeleton_gif,
title = {skeleton-gif: deterministic text-to-GIF with zero hallucination},
year = {2026},
url = {https://huggingface.co/ocmannazirbriet/skeleton-gif}
}