Skip to content

ci(gallery): propose variant groupings for review instead of letting them decay#10992

Merged
mudler merged 1 commit into
masterfrom
gallery-variant-proposals
Jul 20, 2026
Merged

ci(gallery): propose variant groupings for review instead of letting them decay#10992
mudler merged 1 commit into
masterfrom
gallery-variant-proposals

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

Why

Gallery entries can declare variants:, and auto-selection then installs the best build for the host (#10943). Every family in the gallery today exists because a human curated it, across two manual sweeps (#10983 and its predecessor).

.github/gallery-agent/ adds entries on a schedule. It dedupes on the HuggingFace repo URL and picks exactly one quantization per model, so it never adds a second build of a repo it already has. The consequence is that it never creates a family and never joins one: a model published across two repos lands as two unrelated standalone entries, and the grouping decays as the gallery grows with nothing noticing.

What this adds

A weekly job that applies the grouping heuristics from those two sweeps and opens a PR proposing families for review. It never edits the gallery unattended.

That restraint is deliberate. Grouping is a judgement call that went wrong repeatedly by hand: earlier sweeps mis-grouped different parameter sizes, different languages and different finetunes, and had QAT and APEX backwards in both directions. The value here is catching drift and surfacing candidates, not automating the decision.

Modelled on checksum_checker, which already does compute-offline-and-propose.

Validation against human judgement

The useful question is whether the heuristics agree with what people actually decided. Running it against the gallery as it stood before #10983:

12 families proposed. 12 of 12 are groupings #10983 also made. Zero false positives.

Eight of #10983's groupings are not reached, and each is reported rather than silently dropped:

  • Four gemma-4 families are refused because the -qat entry already declares its own variants. gallery: group QAT, APEX and cross-backend builds under their base entry #10983 restructured those first; this job only adds. The refusal names the blocker.
  • Three cross-repo families are missed because the weight-filename signal requires the same upstream repo. Dropping that requirement was tried: against the real gallery it proposed ultravox-v0_5-llama-3_2-1b as a parent of the llama-3.2 instruct entries and linked in bert-embeddings. Those are primary files, so excluding auxiliary files does not prevent it. Three silent misses are better than three confident wrong families.
  • qwen3-tts-cpp + -0.6b-base-q4 is a genuine tension: the parameter-size exclusion forbids it, gallery: group QAT, APEX and cross-backend builds under their base entry #10983 made it anyway. Flagged with the specific rule change that would allow it, rather than resolved silently.

Against master as it stands now, with #10983 merged, it proposes nothing and opens no PR.

The rejection ledger

gallery/variant-exclusions.yaml. A proposal job that re-proposes declined candidates forever becomes noise and gets ignored, so declining is recorded and honoured.

tokens: [{token: abliterated, reason: "..."}]
pairs:  [{parent: whisper-base, variant: whisper-1, reason: "..."}]
groups: [{members: [kokoros, kokoros-de, ...], reason: "..."}]

Flow mappings throughout, so declining a proposal is a one-line edit a reviewer can make inside the proposal PR itself.

Seeded with the decisions already taken: the six -abliterated pairs, the mistral-small multimodal pair, the whisper-1 alias, the kokoros language set, and the recurring finetune tokens. qat and apex are deliberately absent, since those were ruled to be quantization techniques. Confirmed load-bearing: removing the ledger takes the pre-#10983 count from 12 to 14, and the two extras are exactly the kokoros set and the mistral pair.

Parameter-size and identical-payload exclusions are structural rules rather than ledger rows, since they generalise.

Safety rules

A proposal is refused, with the reason reported, when it would nest variants, claim a target another parent already claims, target an entry that is not independently installable, or touch a YAML merge anchor. The anchor case matters: a variants: key added to an anchor is inherited by every merging child, which silently mis-groups them. Verified against the real gallery, the refusal names &qwenttscpp_gallery and all nine merging children and states that each needs variants: [], which is what #10983 hand-edited.

On VariantParents in core/gallery/collapse_variants.go: its comment says taking the first parent in gallery order keeps the listing deterministic "for a gallery the linter would reject", but the linter does not currently reject a doubly-claimed target. This job will not create one. Adding that lint rule is worth doing separately.

Three gallery problems surfaced, none fixed here

  • whisper-large-q5_0 and whisper-small-q5_1 each appear twice in gallery/index.yaml. The job refuses to propose against them, since a variant reference to a duplicated name is ambiguous.
  • bert-embeddings declares overrides.parameters.model: llama-3.2-1b-instruct-q4_k_m.gguf, which looks like a stale copy-paste.

Verification

77 specs, 0 failures, no network. core/gallery green. make lint 0 issues, plus golangci-lint run explicitly on the new package since .github/ci/ sits outside ./.... Build, vet and gofmt clean. Confirmed the index is unmodified on a report-only run.

Assisted-by: Claude:claude-opus-4-8 [Claude Code]

A gallery entry may declare `variants:`, references to other entries that
are alternative builds of the same weights, and auto-selection then installs
the best build for the host. Those families exist only because humans curated
them in two manual sweeps.

The gallery agent dedupes on the HuggingFace repo URL and picks one
quantization per model, so it never adds a second build of a repo it already
has, and consequently never creates a family and never joins one. A model
published across two repos lands as two unrelated standalone entries. The
grouping decays as the gallery grows and nothing notices.

Add a scheduled job, in the same shape as the checksum checker: compute
offline, edit the index textually, open a pull request against ci-forks. It
proposes and never decides. Grouping is a judgement call that has gone wrong
in both directions, so the value is catching drift and surfacing candidates
with their evidence.

Three grouping signals, taken from the manual sweeps: same name once
quantization markers are stripped, the `:` config-suffix convention, and the
same primary weight filename once quantization markers are stripped. The
third requires the same upstream repository. Excluding auxiliary files is not
enough on its own: bert-embeddings, an ultravox audio model and a roleplay
finetune all declare a primary file called llama-3.2-1b-instruct-q4_k_m.gguf,
and grouping on that is the same error that linked four wan-2.1 entries and
Z-Image-Turbo to qwen3-4b.

Add gallery/variant-exclusions.yaml, a checked-in rejection ledger. A job
that re-proposes declined candidates every night becomes noise and gets
ignored. Declining a proposal is one flow-mapping line a reviewer adds inside
the proposal pull request itself. Seeded with the six -abliterated pairs whose
base is also in the gallery, the mistral-small multimodal pair, the whisper-1
alias, the kokoros language set, and the recurring finetune tokens. qat and
apex are deliberately not on it: they are quantization techniques.

Proposals refuse to nest, to let two parents claim one target, to target an
entry that installs nothing, and to touch a merge anchor, since a variants key
added to an anchor is inherited by every merging child. The anchor refusal
names every entry that would inherit, which is the worklist a human needs.

Run against the pre-sweep gallery, the job rediscovers 12 of the 19 groupings
the second manual sweep made, with no false positives. The rest it reports as
refusals or ledger declines rather than missing silently.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
@mudler
mudler merged commit 0cdd781 into master Jul 20, 2026
21 of 22 checks passed
@mudler
mudler deleted the gallery-variant-proposals branch July 20, 2026 21:08
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.

2 participants