fix(civitai): drop redundant variant and role suffixes from save names

A suffix only adds what the CivitAI name lacks: the variant is skipped
when the name already spells that token (ideogram4INT8_...UncondINT8
stays as is, x_fp8 still gains -fp8_e4m3fn once the header names the
exact dtype), header-derived expert roles obey the same file-name guard
as title-derived ones (ideogram4_fp8Uncond no longer ends in -uncond),
and companions never take a role, since the text encoder of a
high-noise version is the same file the low-noise version ships.
This commit is contained in:
CalamitousFelicitousness
2026-09-30 03:34:50 +01:00
parent f49595da0a
commit 803583c6f4
3 changed files with 39 additions and 18 deletions
+6 -6
View File
@@ -1072,10 +1072,10 @@
"2884783": "ideogram4_fp8Scaled-fp8_e4m3fn.safetensors"
},
"3005513": {
"2884823": "ideogram4_fp8Uncond-fp8_e4m3fn-uncond.safetensors"
"2884823": "ideogram4_fp8Uncond-fp8_e4m3fn.safetensors"
},
"3003586": {
"2949563": "ideogram4INT8_ideogram4UncondINT8-int8.safetensors"
"2949563": "ideogram4INT8_ideogram4UncondINT8.safetensors"
},
"3246186": {
"3128946": "ideogram4_txt_3128946-fp8.safetensors",
@@ -1125,10 +1125,10 @@
"90000001": {
"1": "synthWan_v10_1-fp8_e5m2-low-noise.safetensors",
"2": "synthWan_v10_2-bf16-high-noise.safetensors",
"3": "synthWan_v10_txt-bf16-high-noise.safetensors"
"3": "synthWan_v10_txt-bf16.safetensors"
},
"90000002": {
"11": "ideoUnofficial_fp8-fp8-uncond.safetensors"
"11": "ideoUnofficial_fp8-uncond.safetensors"
},
"90000003": {
"21": "collide-fp16-full.safetensors",
@@ -1160,7 +1160,7 @@
"2884783": "ideogram4_fp8Scaled.safetensors"
},
"3005513": {
"2884823": "ideogram4_fp8Uncond-uncond.safetensors"
"2884823": "ideogram4_fp8Uncond.safetensors"
},
"3003586": {
"2949563": "ideogram4INT8_ideogram4UncondINT8.safetensors"
@@ -1213,7 +1213,7 @@
"90000001": {
"1": "synthWan_v10_1-low-noise.safetensors",
"2": "synthWan_v10_2-high-noise.safetensors",
"3": "synthWan_v10_txt-high-noise.safetensors"
"3": "synthWan_v10_txt.safetensors"
},
"90000002": {
"11": "ideoUnofficial_fp8-uncond.safetensors"
+16 -2
View File
@@ -6,8 +6,8 @@ Covers:
- save names for recorded CivitAI versions with the precision suffix on, matching the reference names in the fixture
- the collision cascade with the suffix off: role first, then variant, size class and the file id
- variant tokens from metadata.fp, metadata.quantType and the quantType query parameter of the download url
- expert roles from the version title, the file name and the safetensors header metadata
- variant tokens from metadata.fp, metadata.quantType and the quantType query parameter of the download url, skipped when the name spells the token already
- expert roles from the version title or the safetensors header, never for companions or names that carry a role word
- header probes upgrading a generic fp8 claim to the exact dtype, and leaving it alone when the probe failed
- companion files routing to their own type folder
- a failed remote header read returning an error and never entering the probe cache
@@ -82,6 +82,15 @@ def test_suffix_and_variant():
check('variant gguf ignores fp', names.file_variant(make_file(1, 'a.gguf', fp='fp16')), None)
check('variant gguf format ignores fp', names.file_variant(CivitFile.parse_obj({'id': 1, 'name': 'a.bin', 'metadata': {'format': 'GGUF', 'fp': 'fp16', 'quantType': 'Q5_0'}})), 'Q5_0')
check('variant safetensors quant fallback', names.file_variant(make_file(1, 'a.safetensors', quant='Q8_0')), 'Q8_0')
check('carries fp8', names.name_carries('model_fp8.safetensors', 'fp8'), True)
check('carries exact only', names.name_carries('model_fp8.safetensors', 'fp8_e4m3fn'), False)
check('carries quant', names.name_carries('model-Q8_0.gguf', 'Q8_0'), True)
check('carries not q50', names.name_carries('wan_highQ50.gguf', 'Q5_0'), False)
check('carries camel', names.name_carries('ideogram4Nvfp4_nvfp4_nf4.safetensors', 'nf4'), True)
f = make_file(1, 'model_fp8.safetensors', fp='fp8')
check('name skips carried variant', names.save_name(f, [f]), 'model_fp8.safetensors')
context = names.apply_peeks(names.NameContext(), [f], {1: {'metadata': None, 'probe': {'ok': True, 'dominant_dtype': 'F8_E4M3'}}})
check('name keeps upgraded variant', names.save_name(f, [f], context), 'model_fp8-fp8_e4m3fn.safetensors')
check('variant bad url', names.file_variant(make_file(1, 'a.gguf', url='')), None)
@@ -96,6 +105,11 @@ def test_roles():
check('role metadata', names.role_from_metadata({'model_type': 'ideogram4_uncond'}, ideo), 'uncond')
check('role metadata cond', names.role_from_metadata({'model_type': 'ideogram4_cond', 'n': 3}, ideo), None)
check('role metadata none', names.role_from_metadata(None, ideo), None)
header = names.NameContext(name='v1.0', base_model='Ideogram 4.0', roles={1: 'uncond', 2: 'uncond', 3: 'uncond'})
check('role header', names.file_role(make_file(1, 'x.safetensors'), header), 'uncond')
check('role header gated by name', names.file_role(make_file(2, 'x_uncond.safetensors'), header), None)
check('role header not on companion', names.file_role(make_file(3, 'x_txt.safetensors', 'Text Encoder'), header), None)
check('role title not on companion', names.file_role(make_file(4, 'x.vae.safetensors', 'VAE'), wan), None)
def test_peek_upgrade():