Files
LocalAI/gallery/variant-exclusions.yaml
mudler's LocalAI [bot] 0cdd781c2d ci(gallery): propose variant groupings for review instead of letting them decay (#10992)
ci(gallery): propose variant groupings for review on a schedule

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>
Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
2026-07-20 23:08:00 +02:00

84 lines
5.5 KiB
YAML

# Rejection ledger for the gallery variant proposal job.
#
# `.github/ci/variantproposals` looks for gallery entries that are alternative
# builds of the same weights and proposes grouping them under one another with
# `variants:`. Grouping is a judgement call that has gone wrong in both
# directions, so the job only proposes. This file is where the answers live once
# a human has given them.
#
# The job reads this file and stays silent about everything it names. Without it
# a declined candidate comes back every night until reviewers stop reading the
# job's pull requests, at which point the job is worse than useless.
#
# To decline a proposal, add one line to `pairs` inside the proposal pull
# request itself and close the pull request:
#
# - {parent: some-model, variant: some-model-thing, reason: "different finetune"}
#
# Three kinds of entry:
#
# tokens a name segment that marks a distinct model rather than another build
# of the same one. Two candidates whose names differ by one of these
# are never proposed. Use this for a finetune or language suffix that
# will keep recurring across models.
# pairs one specific candidate, matched in either order.
# groups a set where no two members may ever be paired, for releases like a
# per-language family where listing every pair would be unreadable.
#
# Things the job refuses structurally, so they do NOT need to be listed here:
# different parameter sizes (8b vs 1.7b, a3b vs a22b, e2b vs e4b), entries with
# a byte-identical install payload, and any target that already has a parent.
tokens:
- {token: abliterated, reason: "safety-ablated finetune, not a re-quantization of the base weights"}
- {token: uncensored, reason: "finetune, not a re-quantization of the base weights"}
- {token: heretic, reason: "finetune, not a re-quantization of the base weights"}
- {token: horror, reason: "finetune, not a re-quantization of the base weights"}
- {token: glitter, reason: "finetune, not a re-quantization of the base weights"}
- {token: starshine, reason: "finetune, not a re-quantization of the base weights"}
- {token: deckard, reason: "finetune, not a re-quantization of the base weights"}
- {token: esper, reason: "finetune, not a re-quantization of the base weights"}
- {token: sft, reason: "supervised finetune, not a re-quantization of the base weights"}
- {token: distill, reason: "distilled model, different weights from the teacher"}
- {token: distilled, reason: "distilled model, different weights from the teacher"}
- {token: roleplay, reason: "finetune, not a re-quantization of the base weights"}
# `apex` and `qat` are quantization techniques and are deliberately NOT here:
# the job strips them like any other quantization marker. A model that uses
# "apex" as a finetune name instead belongs in `pairs` below.
pairs:
# Aliases. Byte-identical payloads are not alternative builds. whisper-1
# exists so OpenAI-compatible clients can send that name; grouping it under
# whisper-base would hide the name clients actually send.
- {parent: whisper-base, variant: whisper-1, reason: "alias: identical payload, whisper-1 is the name OpenAI-compatible clients send"}
# Different capability surface, not a different build. The multimodal entry
# adds a vision projector and a different config; installing one instead of
# the other silently changes what the model can do.
- {parent: mistralai_mistral-small-3.1-24b-instruct-2503, variant: mistralai_mistral-small-3.1-24b-instruct-2503-multimodal, reason: "different capability surface: the multimodal entry adds a vision projector"}
# Safety-ablated finetunes that share a base name with the model they were
# derived from. The token rule above already covers these; they are spelled
# out because each was considered individually during the manual sweeps.
- {parent: dolphin-2.9.2-phi-3-medium, variant: dolphin-2.9.2-phi-3-medium-abliterated, reason: "finetune, not a re-quantization"}
- {parent: falcon3-1b-instruct, variant: falcon3-1b-instruct-abliterated, reason: "finetune, not a re-quantization"}
- {parent: falcon3-3b-instruct, variant: falcon3-3b-instruct-abliterated, reason: "finetune, not a re-quantization"}
- {parent: falcon3-10b-instruct, variant: falcon3-10b-instruct-abliterated, reason: "finetune, not a re-quantization"}
- {parent: meta-llama-3.1-8b-instruct, variant: meta-llama-3.1-8b-instruct-abliterated, reason: "finetune, not a re-quantization"}
- {parent: qwen3-30b-a3b, variant: qwen3-30b-a3b-abliterated, reason: "finetune, not a re-quantization"}
# English-only and multilingual ASR are different models trained on different
# data. They share a repo and a filename shape, so the heuristics will keep
# finding them.
- {parent: whisper-tiny, variant: whisper-tiny-en, reason: "English-only versus multilingual ASR: different weights"}
- {parent: whisper-base, variant: whisper-base-en, reason: "English-only versus multilingual ASR: different weights"}
- {parent: whisper-small, variant: whisper-small-en, reason: "English-only versus multilingual ASR: different weights"}
# Different products that happen to share a prefix.
- {parent: vibevoice-cpp, variant: vibevoice-cpp-asr, reason: "different products: a TTS engine and an ASR engine, not two builds of one model"}
groups:
# One release per language. Every pair here is a different model.
- members: [kokoros, kokoros-de, kokoros-ja, kokoros-cmn]
reason: "different languages: one Kokoro release per language, not alternative builds of one model"