OpenParable
Skip to content
← Back to skills

libreyolo-upload-hf-model

Development

Prepare 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.

View on GitHub ↗
QUICK START

How to use this skill

Bring this guide into your coding agent with a prompt tailored to the tool you use.

  1. Open your project in Codex.
  2. Copy and paste the prompt below.
  3. Review files and risks before approving any action.
Prompt to paste
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 .pt and .pth of 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:

FamilyPrefixExample
YOLOXLibreYOLOXLibreYOLOXs.pt
YOLO2LibreYOLO2LibreYOLO2b.pt (public-domain Darknet)
YOLO3LibreYOLO3LibreYOLO3b.pt, LibreYOLO3spp.pt (public-domain Darknet)
YOLO4LibreYOLO4LibreYOLO4b.pt (public-domain Darknet)
YOLO7LibreYOLO7LibreYOLO7b.pt (MIT MultimediaTechLab/YOLO)
YOLO9LibreYOLO9LibreYOLO9m.pt
YOLO9-P2LibreYOLO9P2LibreYOLO9P2s.pt, LibreYOLO9P2s-visdrone.pt (dataset-variant suffix)
RFDETRLibreRFDETRLibreRFDETRn.pt, LibreRFDETRn-seg.pt, LibreRFDETRx-pose.pt
RTDETRLibreRTDETRLibreRTDETRr50.pt
RTDETRv2LibreRTDETRv2LibreRTDETRv2r50.pt
RTDETRv4LibreRTDETRv4LibreRTDETRv4s.pt
RTMDetLibreRTMDetLibreRTMDets.pt
YOLONASLibreYOLONASLibreYOLONASs.pt
MobileNetV4LibreMobileNetV4LibreMobileNetV4s-cls.pt
ConvNeXtLibreConvNeXtLibreConvNeXtt-cls.pt
EfficientNetV2LibreEfficientNetV2LibreEfficientNetV2b0-cls.pt
ResNetLibreResNetLibreResNet50-cls.pt
CLIPLibreCLIPLibreCLIPb32-cls.pt (zero-shot, open-vocab classify)
NAFNetLibreNAFNetLibreNAFNets-restore.pt (restore-only)
PIDNetLibrePIDNetLibrePIDNets-sem.pt (semantic-only)
EoMTLibreEoMTLibreEoMTl-sem.pt (semantic-only)
DINOv2LibreDINOv2LibreDINOv2n.pt (semantic default), LibreDINOv2n-cls.pt
DepthAnythingV2LibreDepthAnythingV2LibreDepthAnythingV2s-depth.pt (only s is Apache; b/l/g are CC-BY-NC, see below)
FOMOLibreFOMOLibreFOMOs-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*.pt or LibreECDET*.pt. The library renamed those.
  • Detect carrying an explicit -det suffix — 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>
  1. 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).
  2. Map the size — YOLOX only: n → nano, t → tiny. All other sizes are used as-is (including r50-style RT-DETR codes and DEIMv2's atto/femto/pico).
  3. Join: yolov9 concatenates with no separator; every other family joins with a hyphen.
Weight file<va-slug>
LibreYOLOXn.ptyolox-nano
LibreYOLOXs.ptyolox-s
LibreYOLO9s.ptyolov9s
LibreDFINEm.ptdfine-m
LibreRTDETRr50.ptrtdetr-r50
LibreDEIMv2atto.ptdeimv2-atto

Rules:

  • Detect repos only. Vision Analysis tracks detection; omit the Benchmarks section from -seg / -pose / -cls / -obb and 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) and yolo7 — 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.json in 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 in models.json and, if it doesn't, tell the user to add the model entry so the page resolves.

LICENSE + NOTICE

  • LICENSE: copy the upstream LICENSE file 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 typeCollection
Detection weightsLibreYOLO/libreyolo-models-698875bf2b5f695708415169
RF-DETR segmentationLibreYOLO/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 yetAdd to LibreYOLO Models

Add via HF UI or huggingface_hub.add_collection_item(collection_slug, item_id=<repo>, item_type="model").

Upload workflow

  1. 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.
  2. Verify canonical filename matches BaseModel.get_download_url() output for this family + size.
  3. 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.
  4. Validate the .pt against the current LibreYOLO checkpoint metadata schema before upload. The source of truth is docs/checkpoint_schema.md and the helpers in libreyolo/utils/serialization.py; do not duplicate the schema in this skill. A simple load smoke test is not enough.
  5. Create the HF repo (skip if it exists): huggingface-cli repo create LibreYOLO/<RepoName> --type model.
  6. Upload: huggingface-cli upload LibreYOLO/<RepoName> <local-dir> . --commit-message "Initial upload".
  7. Smoke test: YOLO.from_pretrained("LibreYOLO/<RepoName>") on a fresh machine / cleared cache.
  8. 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-analysis models.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 .pt and .pth of 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: mit in 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).