libreyolo-upload-hf-model
DevelopmentPrepare and upload a LibreYOLO weight repo to the HuggingFace LibreYOLO org. Use when publishing new weights (new family, new size, or new task like -seg). Covers filename, README, LICENSE, NOTICE, and collection membership.
How to use this skill
Bring this guide into your coding agent with a prompt tailored to the tool you use.
- Open your project in Codex.
- Copy and paste the prompt below.
- Review files and risks before approving any action.
Inspect the Agent Skill at https://github.com/LibreYOLO/libreyolo/blob/HEAD/skills/libreyolo-upload-hf-model/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/libreyolo-upload-hf-model, but wait for my approval before writing files or running scripts.
Copying this prompt does not install or run the skill. Review third-party files before use.
Upload a LibreYOLO weight repo to HuggingFace
Use this skill when publishing model weights to https://huggingface.co/LibreYOLO/<repo>.
Scope: weight-only repos (one .pt, one canonical filename, matching a family defined in libreyolo/models/<family>/model.py). Not product repos (face-*, libreyolo-web) — those are bespoke and out of scope.
The 5-file contract
Every weight repo contains exactly these 5 files. No more, no less.
<repo>/
├── .gitattributes # LFS rules (copy from any existing LibreYOLO weight repo, 1519 bytes)
├── README.md # YAML frontmatter + Source / Modifications / License
├── LICENSE # upstream license text, verbatim
├── NOTICE # attribution block (required for Apache-2.0 upstreams)
└── Libre<Family><size>[-<task>].pt # the canonical weight file
Do not upload:
- Lowercase or legacy filenames (
libreyolo9s.pt,rf-detr-nano.pth). - Raw upstream checkpoints alongside the converted weight.
- Both
.ptand.pthof the same weights.
Canonical filename
Derived from code, not invented:
name = FILENAME_PREFIX + size + ("-" + task if task else "")
file = name + ".pt"
FILENAME_PREFIX per family — read from libreyolo/models/<family>/model.py:
| Family | Prefix | Example |
|---|---|---|
| YOLOX | LibreYOLOX | LibreYOLOXs.pt |
| YOLO2 | LibreYOLO2 | LibreYOLO2b.pt (public-domain Darknet) |
| YOLO3 | LibreYOLO3 | LibreYOLO3b.pt, LibreYOLO3spp.pt (public-domain Darknet) |
| YOLO4 | LibreYOLO4 | LibreYOLO4b.pt (public-domain Darknet) |
| YOLO7 | LibreYOLO7 | LibreYOLO7b.pt (MIT MultimediaTechLab/YOLO) |
| YOLO9 | LibreYOLO9 | LibreYOLO9m.pt |
| YOLO9-P2 | LibreYOLO9P2 | LibreYOLO9P2s.pt, LibreYOLO9P2s-visdrone.pt (dataset-variant suffix) |
| RFDETR | LibreRFDETR | LibreRFDETRn.pt, LibreRFDETRn-seg.pt, LibreRFDETRx-pose.pt |
| RTDETR | LibreRTDETR | LibreRTDETRr50.pt |
| RTDETRv2 | LibreRTDETRv2 | LibreRTDETRv2r50.pt |
| RTDETRv4 | LibreRTDETRv4 | LibreRTDETRv4s.pt |
| RTMDet | LibreRTMDet | LibreRTMDets.pt |
| YOLONAS | LibreYOLONAS | LibreYOLONASs.pt |
| MobileNetV4 | LibreMobileNetV4 | LibreMobileNetV4s-cls.pt |
| ConvNeXt | LibreConvNeXt | LibreConvNeXtt-cls.pt |
| EfficientNetV2 | LibreEfficientNetV2 | LibreEfficientNetV2b0-cls.pt |
| ResNet | LibreResNet | LibreResNet50-cls.pt |
| CLIP | LibreCLIP | LibreCLIPb32-cls.pt (zero-shot, open-vocab classify) |
| NAFNet | LibreNAFNet | LibreNAFNets-restore.pt (restore-only) |
| PIDNet | LibrePIDNet | LibrePIDNets-sem.pt (semantic-only) |
| EoMT | LibreEoMT | LibreEoMTl-sem.pt (semantic-only) |
| DINOv2 | LibreDINOv2 | LibreDINOv2n.pt (semantic default), LibreDINOv2n-cls.pt |
| DepthAnythingV2 | LibreDepthAnythingV2 | LibreDepthAnythingV2s-depth.pt (only s is Apache; b/l/g are CC-BY-NC, see below) |
| FOMO | LibreFOMO | LibreFOMOs-point.pt (no weights hosted yet; license-gate first) |
Never-upload families: L2CS (Gaze360 terms forbid redistribution) and any
weight whose upstream/training-data license fails the gate in
skills/libreyolo-license-audit. DepthAnythingV2 b/l/g weights are
CC-BY-NC; hosting them is a maintainer decision, not a default. The
open-vocabulary and SAM/VLM tiers ship HF snapshot directories
(LibreGroundingDINOt, LibreOWLv2b16, ...), not single .pt files; their
repos mirror upstream snapshot layout plus card, so the 5-file contract below
does not apply verbatim (follow the existing mirror repos).
Ask the user if: the size code isn't obvious, the family isn't one of the above, or the filename doesn't match what the loader at libreyolo/models/base/model.py:get_download_url builds. Do not guess.
Canonical filename whitelist
Before creating the HF repo or uploading, verify that the .pt filename you are about to ship appears verbatim in this list. If it doesn't, stop and ask the user — either a new family/size/task is being introduced (skill should be updated) or the name is wrong.
Authoritative list of all valid weight filenames (matches the schema enforced by BaseModel._filename_regex and the family table in docs/nomenclature.md):
LibreYOLOXn.pt, LibreYOLOXt.pt, LibreYOLOXs.pt, LibreYOLOXm.pt,
LibreYOLOXl.pt, LibreYOLOXx.pt,
LibreYOLO2t.pt, LibreYOLO2b.pt,
LibreYOLO3t.pt, LibreYOLO3b.pt, LibreYOLO3spp.pt,
LibreYOLO4t.pt, LibreYOLO4b.pt,
LibreYOLO7b.pt,
LibreYOLO9t.pt, LibreYOLO9s.pt, LibreYOLO9m.pt, LibreYOLO9c.pt,
LibreYOLO9E2Et.pt, LibreYOLO9E2Es.pt, LibreYOLO9E2Em.pt,
LibreYOLO9E2Ec.pt,
LibreYOLO9P2t.pt, LibreYOLO9P2s.pt,
LibreYOLO9P2t-visdrone.pt, LibreYOLO9P2s-visdrone.pt,
LibreYOLONASs.pt, LibreYOLONASm.pt, LibreYOLONASl.pt,
LibreYOLONASn-pose.pt, LibreYOLONASs-pose.pt,
LibreYOLONASm-pose.pt, LibreYOLONASl-pose.pt,
LibreDFINEn.pt, LibreDFINEs.pt, LibreDFINEm.pt, LibreDFINEl.pt,
LibreDFINEx.pt,
LibreDEIMn.pt, LibreDEIMs.pt, LibreDEIMm.pt, LibreDEIMl.pt,
LibreDEIMx.pt,
LibreDEIMv2atto.pt, LibreDEIMv2femto.pt, LibreDEIMv2pico.pt,
LibreDEIMv2n.pt, LibreDEIMv2s.pt, LibreDEIMv2m.pt,
LibreDEIMv2l.pt, LibreDEIMv2x.pt,
LibrePICODETs.pt, LibrePICODETm.pt, LibrePICODETl.pt,
LibreRTDETRr18.pt, LibreRTDETRr34.pt, LibreRTDETRr50.pt,
LibreRTDETRr50m.pt, LibreRTDETRr101.pt, LibreRTDETRl.pt,
LibreRTDETRx.pt,
LibreRTDETRv2r18.pt, LibreRTDETRv2r34.pt, LibreRTDETRv2r50.pt,
LibreRTDETRv2r50m.pt, LibreRTDETRv2r101.pt,
LibreRTDETRv4s.pt, LibreRTDETRv4m.pt, LibreRTDETRv4l.pt,
LibreRTDETRv4x.pt,
LibreRTMDett.pt, LibreRTMDets.pt, LibreRTMDetm.pt,
LibreRTMDetl.pt, LibreRTMDetx.pt,
LibreRFDETRn.pt, LibreRFDETRs.pt, LibreRFDETRm.pt,
LibreRFDETRl.pt, LibreRFDETRn-seg.pt, LibreRFDETRs-seg.pt,
LibreRFDETRm-seg.pt, LibreRFDETRl-seg.pt, LibreRFDETRx-pose.pt,
LibreRFDETRn-obb.pt, LibreRFDETRs-obb.pt, LibreRFDETRm-obb.pt,
LibreRFDETRl-obb.pt,
LibreECs.pt, LibreECm.pt, LibreECl.pt, LibreECx.pt,
LibreECs-pose.pt, LibreECm-pose.pt, LibreECl-pose.pt,
LibreECx-pose.pt, LibreECs-seg.pt, LibreECm-seg.pt,
LibreECl-seg.pt, LibreECx-seg.pt,
LibreMobileNetV4s-cls.pt, LibreMobileNetV4m-cls.pt,
LibreMobileNetV4l-cls.pt,
LibreConvNeXtt-cls.pt, LibreConvNeXts-cls.pt, LibreConvNeXtb-cls.pt,
LibreEfficientNetV2b0-cls.pt, LibreEfficientNetV2b1-cls.pt,
LibreEfficientNetV2b2-cls.pt, LibreEfficientNetV2b3-cls.pt,
LibreResNet18-cls.pt, LibreResNet34-cls.pt,
LibreResNet50-cls.pt, LibreResNet101-cls.pt,
LibreCLIPb32-cls.pt, LibreCLIPb16-cls.pt, LibreCLIPl14-cls.pt,
LibreNAFNets-restore.pt, LibreNAFNetl-restore.pt,
LibrePIDNets-sem.pt, LibrePIDNetm-sem.pt, LibrePIDNetl-sem.pt,
LibreEoMTl-sem.pt,
LibreDINOv2n.pt, LibreDINOv2s.pt, LibreDINOv2m.pt, LibreDINOv2l.pt,
LibreDINOv2n-cls.pt, LibreDINOv2s-cls.pt, LibreDINOv2m-cls.pt,
LibreDINOv2l-cls.pt,
LibreDepthAnythingV2s-depth.pt, LibreDepthAnythingV2b-depth.pt,
LibreDepthAnythingV2l-depth.pt, LibreDepthAnythingV2g-depth.pt,
LibreFOMOs-point.pt, LibreFOMOm-point.pt, LibreFOMOl-point.pt
License caveats inside the list: DepthAnythingV2 b/l/g are CC-BY-NC
(maintainer decision to host); -visdrone variants are a research preview
under VisDrone's CC BY-NC-SA (repo LibreYOLO/LibreYOLO9P2s-visdrone, with
the license stated loudly on the card); FOMO weights have no cleared hosting
license yet. A name being valid does not make it hostable; run the gate.
The -visdrone suffix is a WEIGHT_VARIANTS dataset variant (grammar in
docs/nomenclature.md): only families that declare WEIGHT_VARIANTS in
their model.py may carry one, and plain COCO-default weights never do.
Classification (-cls) repos use pipeline_tag: image-classification,
datasets: imagenet-1k, and omit the Benchmarks section (Vision Analysis
tracks detection only). The architecture is a native timm-derived port; weights
are Apache-2.0 ImageNet-1k and load bit-identically (max_abs_diff == 0).
LibreCLIP is the zero-shot, open-vocabulary classifier (CLIP). Its HF cards use
pipeline_tag: zero-shot-image-classification, must document the LAION-2B
data-provenance note (see libreyolo/models/clip/NOTICE.md), and omit the VA
Benchmarks section (zero-shot, not a trained-on-COCO detector).
Common rule violations to reject before upload:
- Wrong casing on the size —
LibreDEIMv2Atto.pt(PascalCase). Sizes are always lowercase. - Old class-name forms in the file —
LibreYOLORTDETR*.ptorLibreECDET*.pt. The library renamed those. - Detect carrying an explicit
-detsuffix —LibreECs-det.pt. Detect is implicit, no suffix. - Lowercase prefix —
librerfdetrn.pt(Hugging Face is case-insensitive on lookup but the file inside the repo must use the canonical case).
If a candidate filename isn't in the list and isn't a brand-new family being introduced now, stop and ask rather than uploading.
README template
---
license: <apache-2.0 | mit | ...>
library_name: libreyolo
tags:
- object-detection
- <family-tag> # yolox | yolov9 | rf-detr | rt-detr | yolo-nas
---
# <RepoName>
<One sentence: what architecture, what size, repackaged for LibreYOLO.>
## Source
Derived from [<upstream-org>/<upstream-repo>](https://github.com/<upstream-org>/<upstream-repo>)
at <tag-or-commit>.
Copyright (c) <years> <upstream-authors>. Licensed under the <License> License.
<If a backbone has its own upstream, add a second paragraph for it.>
## Modifications
State-dict key remapping only. Learned parameters are unchanged.
See `weights/convert_<family>_weights.py` in the
[LibreYOLO source repository](https://github.com/LibreYOLO/libreyolo).
## Benchmarks
Independent, verified accuracy and speed benchmarks for this model:
[visionanalysis.org/model/<va-slug>](https://www.visionanalysis.org/model/<va-slug>)
## License
<Apache License 2.0 | MIT License>. See the [`LICENSE`](./LICENSE)
and [`NOTICE`](./NOTICE) files in this repository.
Vision Analysis benchmark link (<va-slug>)
Detect weight repos link to the model's page on the benchmark site
visionanalysis.org. The URL is deterministic —
derive it from (FAMILY, size), never search for it or guess:
https://www.visionanalysis.org/model/<va-slug>
- Map the family id:
yolo9→yolov9. Every other family id is used as-is (yolox,rfdetr,rtdetr,rtdetrv2,rtdetrv4,dfine,deim,deimv2,picodet,yolonas,ec). - Map the size — YOLOX only:
n→nano,t→tiny. All other sizes are used as-is (includingr50-style RT-DETR codes and DEIMv2'satto/femto/pico). - Join:
yolov9concatenates with no separator; every other family joins with a hyphen.
| Weight file | <va-slug> |
|---|---|
LibreYOLOXn.pt | yolox-nano |
LibreYOLOXs.pt | yolox-s |
LibreYOLO9s.pt | yolov9s |
LibreDFINEm.pt | dfine-m |
LibreRTDETRr50.pt | rtdetr-r50 |
LibreDEIMv2atto.pt | deimv2-atto |
Rules:
- Detect repos only. Vision Analysis tracks detection; omit the Benchmarks
section from
-seg/-pose/-cls/-obband gaze repos. - No slug exists for
yolo9_e2e,yolo9_p2,l2cs, RTMDet, the VLM / SAM / open-vocab tiers, or the Darknet-lineage families (yolo2,yolo3,yolo4) andyolo7— omit the Benchmarks section and tell the user. Semantic / depth / restore / point repos also omit it (detection only). - The page may lag the upload. Model pages are generated from
website/src/data/metadata/models.jsonin LibreYOLO/vision-analysis; a page goes live on the next site deploy after the model is added there, with or without benchmark runs. The derived URL never changes, so include the link at upload time regardless — but check the slug exists inmodels.jsonand, if it doesn't, tell the user to add the model entry so the page resolves.
LICENSE + NOTICE
- LICENSE: copy the upstream
LICENSEfile verbatim. Do not synthesize, do not template. - NOTICE: required when upstream is Apache-2.0. Short attribution block:
Libre<Family> weights
---------------------
This product contains weights derived from <Upstream>
(https://github.com/<upstream-org>/<upstream-repo>).
Copyright (c) <years> <upstream-authors>.
Licensed under the Apache License, Version 2.0.
<Second paragraph if there's a separately-licensed backbone.>
For MIT upstreams (e.g. YOLOv9): NOTICE is not legally required. For consistency with existing YOLOX/RFDETR/RTDETR repos, include one anyway.
Collection membership
After the repo is uploaded, add it to a collection:
| Repo type | Collection |
|---|---|
| Detection weights | LibreYOLO/libreyolo-models-698875bf2b5f695708415169 |
| RF-DETR segmentation | LibreYOLO/rf-detr-instance-segmentation-69bde2744d6c285366a69603 |
| New seg family (e.g. YOLOX-seg) | Ask the user — create a new collection or extend existing |
| New detection family with no siblings yet | Add to LibreYOLO Models |
Add via HF UI or huggingface_hub.add_collection_item(collection_slug, item_id=<repo>, item_type="model").
Upload workflow
- Build the 5 files locally in a clean directory. For detect repos, derive
the Vision Analysis
<va-slug>(section above) and fill in the README Benchmarks link. - Verify canonical filename matches
BaseModel.get_download_url()output for this family + size. - Cross-check the filename against the whitelist above. If it isn't in the list, halt and ask the user — don't paper over it with a manual override.
- Validate the
.ptagainst the current LibreYOLO checkpoint metadata schema before upload. The source of truth isdocs/checkpoint_schema.mdand the helpers inlibreyolo/utils/serialization.py; do not duplicate the schema in this skill. A simple load smoke test is not enough. - Create the HF repo (skip if it exists):
huggingface-cli repo create LibreYOLO/<RepoName> --type model. - Upload:
huggingface-cli upload LibreYOLO/<RepoName> <local-dir> . --commit-message "Initial upload". - Smoke test:
YOLO.from_pretrained("LibreYOLO/<RepoName>")on a fresh machine / cleared cache. - Add to the matching collection.
One commit per file if iterating — easier to revert than a batch commit.
Ask the user when
- The upstream release / commit pin isn't known (reproducibility needs it in README).
- The family isn't in the code yet (the skill can't derive canonical filename).
- A file with the same name already exists on the target repo (overwrite is destructive).
- The repo is a new task type and no collection fits.
- The upstream has a non-standard license (neither Apache-2.0 nor MIT).
- The model's
<va-slug>is missing from vision-analysismodels.json(the benchmark link will 404 until the model entry is added and deployed).
Common traps
- Relying only on
YOLO.from_pretrained(...); it can pass even when required checkpoint metadata is missing or stale. - Uploading both
.ptand.pthof the same weights (wastes HF storage, no canonical filename). - Copying a lowercase filename from an old release — the loader only fetches the
FILENAME_PREFIX-cased.pt. - Writing
license: mitin README YAML for a repo whose weights derive from an Apache-2.0 upstream — MIT re-licensing is not legal without explicit permission. - Forgetting
.gitattributes— weights upload as raw blobs instead of LFS and the repo becomes huge. - Adding to the wrong collection (seg → detection collection).