Skip to content

feat(modelcard): give local model files the modelCard of the Hugging Face repo they came from - #114

Open
lab700xdev wants to merge 1 commit into
mainfrom
local-hf-modelcard
Open

lab700xdev wants to merge 1 commit into
mainfrom
local-hf-modelcard

Conversation

@lab700xdev

Copy link
Copy Markdown
Contributor

What

A local copy of a Hugging Face model now gets the same modelCard an hf:// scan of its repo produces, when the link can be proven.

  1. Candidate repo from local evidence. Either the HF cache layout (models--<org>--<name>/snapshots/<commit>/…, which gives the repo and revision), or a config.json next to the weights whose _name_or_path is an org/name repo id. File names are never used.
  2. Proof by content. The file's SHA-256 must equal an lfs.oid in the repo's file listing, or, for small files stored in git, its git blob id must equal an oid. A renamed file still matches. A fine-tune whose config still names its base model does not.
  3. No card when nothing proves out, when two repos both prove out, or on any network failure, following the same best-effort contract as the hf:// card fetch.

A matched card carries aisbom:hf:match (hf-cache or config-name-or-path), so an inferred link can be told apart from an hf:// scan.

Privacy and opt-out

  • Only the repo id and commit are sent to huggingface.co. The hash comparison happens locally, so paths, file names and hashes are never sent.
  • A _name_or_path that is a single name, looks like a path, or names a directory that exists is never requested.
  • A tree with no HF evidence makes no request and prints nothing.
  • On by default for CycloneDX 1.7, SPDX 3.0 and score on a directory. --no-hf-lookup, AISBOM_NO_HF_LOOKUP=1 or --offline turn it off.
  • The README's Telemetry & Privacy section, the Action README and the air-gapped guide document this.

Other changes

  • SPDX 3.0 links each model only to the datasets its own card declares (unchanged for hf:// scans, where every model shares one card).
  • score's model-card and dataset fix hints mention that a local copy in the HF cache also works.

Verification

  • poetry run pytest --cov=aisbom --cov-fail-under=85: 1452 passed, 93.73% coverage. aisbom bypass-scorecard --check passes.
  • New tests cover candidate rules, hash proof (LFS and git blob), fine-tune rejection, ambiguity, pagination, host-pinned pagination, malformed ids, every opt-out making zero requests, outputs that skip the lookup, per-file cards in CycloneDX and SPDX 3.0, and strict 1.7 schema validation.
  • Live on hf-internal-testing/tiny-random-bert, comparing main against this branch:
    • HF cache copy: matched 2 of 2 (model.safetensors via git blob id, pytorch_model.bin via LFS SHA-256). No field regressions; the only added component key is modelCard, and it equals the hf:// scan's card apart from aisbom:hf:match.
    • The same weights with no HF evidence: output identical to main apart from serial number and timestamp.
    • config.json naming the repo: matched. Fine-tune with a config naming the base model: no card.
    • All outputs pass strict CycloneDX 1.7 validation.
    • aisbom score on the cache copy: 50.0 (D) with --no-hf-lookup, 65.0 (C) without.

Release note

Local scans of HF-cached models now contact huggingface.co by default, including in the GitHub Action when the scanned directory has that evidence.

…Face repo they came from

A local copy of a Hugging Face model used to get no modelCard, while an
hf:// scan of the same repo did. Local scans now look for evidence of the
repo (the HF cache layout, or a config.json whose _name_or_path is an
org/name repo id), prove it by finding the file's SHA-256 or git blob id in
that repo's file listing, and only then attach the repo's card.

- No proof, a lookup failure, or more than one repo proving out: no card.
- A matched card records aisbom:hf:match (hf-cache or config-name-or-path).
- Only the repo id and commit are sent; paths, names and hashes stay local.
  Path-like or single-name _name_or_path values are never requested.
- On by default for CycloneDX 1.7, SPDX 3.0 and score on a directory;
  --no-hf-lookup, AISBOM_NO_HF_LOOKUP=1 or --offline turn it off.
- SPDX 3.0 now links each model only to its own card's datasets.
- README privacy section, Action README and air-gapped guide updated.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c519ec516d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread aisbom/spdx3_gen.py
for dep in results.get("dependencies", [])
],
"datasets": _card_datasets(results.get("hf_model_card")),
"datasets": _all_card_datasets(results),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include per-model dataset assignments in the namespace

When the same artifacts and dependencies have different per-model dataset assignments but the same first-seen dataset union—for example, model A changes from [x, y] to [x] while model B changes from [z] to [y, z]—this fingerprint remains identical even though the generated trainedOn relationships differ. Both SPDX documents consequently reuse the same document, package, and relationship IRIs, so importing them into one SPDX/RDF store can conflate distinct relationship versions. Fingerprint each artifact's own _card_datasets(_card_for(...)) list rather than only the union.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant