internal/autogen/identity_test.go
Rama main · réplica de lectura del repositorio original.
package autogen
import "testing"
// Every case here is a REAL header off a real gguf. The rules exist to survive
// what publishers actually write, so invented inputs would prove nothing.
func TestIdentityFrom(t *testing.T) {
cases := []struct {
name string
meta Metadata
wantRow, wantFam string
}{
{
// The bug this replaced regexes for: three unrelated spellings of one
// model, all landing on one row. Only the header knows.
"unsloth Qwen3.8",
Metadata{BaseName: "Qwen3.8-27B", SizeLabel: "27B"},
"qwen3.8-27b", "qwen3.8-27b",
}, {
// Qwen's own conversion writes the size OUT of the basename, and calls
// the finetune "source". Same model, same row.
"Qwen3.8 from source",
Metadata{BaseName: "Qwen3.8", SizeLabel: "27B", FineTune: "source", GeneralName: "Qwen3.8 27B Source"},
"qwen3.8-27b", "qwen3.8-27b",
}, {
// Finetunes must NOT collapse: Instruct and Thinking share a basename
// and a size and are different models - one row each, one family.
"Qwen3-4B Instruct",
Metadata{BaseName: "Qwen3", SizeLabel: "4B", FineTune: "Instruct"},
"qwen3-4b-instruct", "qwen3-4b",
}, {
"Qwen3-4B Thinking",
Metadata{BaseName: "Qwen3", SizeLabel: "4B", FineTune: "Thinking"},
"qwen3-4b-thinking", "qwen3-4b",
}, {
// An abliterated finetune keeps the base's family, so it groups under it.
"a finetune of Qwen3.8",
Metadata{BaseName: "Qwen3.8-27B", SizeLabel: "27B", FineTune: "Aggressive"},
"qwen3.8-27b-aggressive", "qwen3.8-27b",
}, {
// Case and separators are noise: one model, however it is punctuated.
"punctuation",
Metadata{BaseName: "Qwen2.5_VL_7B_Instruct", SizeLabel: "7B", FineTune: "Instruct"},
"qwen2.5-vl-instruct-7b-instruct", "qwen2.5-vl-instruct-7b",
}, {
// LFM2.5 ships its git commit as the finetune; left in, it would split
// the model's quants across a row each.
"a commit hash for a finetune",
Metadata{BaseName: "LFM2.5", SizeLabel: "2.7B", FineTune: "799e37a4e60bdaae12c03b982cd0b0a531d87047"},
"lfm2.5-2.7b", "lfm2.5-2.7b",
}, {
// Only general.name survives some conversions.
"name only",
Metadata{GeneralName: "Gemma 4 E2B", SizeLabel: "4.6B"},
"gemma-4-e2b", "gemma-4-e2b",
}, {
// Nanbeige's general.name is a hex blob, and a size label alone names
// nothing - so the file identifies nothing and the caller falls back.
"junk name, size only",
Metadata{GeneralName: "F56Ec5A9650268Aa098496734743C25Ea778Bd2D", SizeLabel: "4.2B"},
"", "",
}, {
// Most diffusion ggufs and every hand conversion look like this.
"no identity at all",
Metadata{},
"", "",
},
}
for _, c := range cases {
got := identityFrom(c.meta)
if got.ModelKey != c.wantRow || got.FamilyKey != c.wantFam {
t.Errorf("%s: identityFrom = (%q, %q), want (%q, %q)", c.name, got.ModelKey, got.FamilyKey, c.wantRow, c.wantFam)
}
}
}
// The quant label rides along untouched - identityFrom judges names, not weights.
func TestIdentityFrom_CarriesQuantLabel(t *testing.T) {
if got := identityFrom(Metadata{QuantLabel: "IQ4_XS mix"}).QuantLabel; got != "IQ4_XS mix" {
t.Errorf("QuantLabel = %q", got)
}
}