fix(other-models): default downloads to a flat path, not {base_model}/{first_tag}

get_download_path_template() fell back to "{base_model}/{first_tag}" for any
unconfigured model type, so other-model downloads were silently nested under an
arbitrary CivitAI tag even though the settings UI exposes no template row for
"other" and priority_tags has no "other" entry (making {first_tag} resolve to
tags[0]).

Add DEFAULT_DOWNLOAD_PATH_TEMPLATES with other -> "" so unconfigured and
unknown types resolve to a flat layout under the already sub_type-scoped
default_other_roots; explicit settings.json values still win. Mirror the flat
default in the frontend DEFAULT_PATH_TEMPLATES and stop the download/move
default-path previews from rendering "/undefined" or a dangling slash.
This commit is contained in:
Will Miao
2026-09-13 11:30:57 +08:00
parent 931dfbe1d3
commit 6fe0543d2e
9 changed files with 269 additions and 25 deletions
+12 -15
View File
@@ -25,6 +25,7 @@ from typing import (
from platformdirs import user_config_dir
from ..utils.constants import (
DEFAULT_DOWNLOAD_PATH_TEMPLATES,
DEFAULT_ENABLED_OTHER_SUB_TYPES,
DEFAULT_HASH_CHUNK_SIZE_MB,
DEFAULT_PRIORITY_TAG_CONFIG,
@@ -2335,10 +2336,14 @@ class SettingsManager:
"""Get download path template for specific model type
Args:
model_type: The type of model ('lora', 'checkpoint', 'embedding')
model_type: The type of model ('lora', 'checkpoint', 'embedding',
'other')
Returns:
Template string for the model type, defaults to '{base_model}/{first_tag}'
Template string for the model type. Falls back to the per-type
default in ``DEFAULT_DOWNLOAD_PATH_TEMPLATES``; unknown model types
resolve to an empty string (flat layout) rather than silently
nesting downloads under an unconfigured subfolder.
"""
templates = self.settings.get("download_path_templates", {})
@@ -2362,27 +2367,19 @@ class SettingsManager:
logger.warning(
f"Failed to parse download_path_templates JSON string: {e}. Setting default values."
)
default_template = "{base_model}/{first_tag}"
templates = {
"lora": default_template,
"checkpoint": default_template,
"embedding": default_template,
}
templates = dict(DEFAULT_DOWNLOAD_PATH_TEMPLATES)
self.settings["download_path_templates"] = templates
self._save_settings()
# Ensure templates is a dictionary
if not isinstance(templates, dict):
default_template = "{base_model}/{first_tag}"
templates = {
"lora": default_template,
"checkpoint": default_template,
"embedding": default_template,
}
templates = dict(DEFAULT_DOWNLOAD_PATH_TEMPLATES)
self.settings["download_path_templates"] = templates
self._save_settings()
return templates.get(model_type, "{base_model}/{first_tag}")
return templates.get(
model_type, DEFAULT_DOWNLOAD_PATH_TEMPLATES.get(model_type, "")
)
_SETTINGS_MANAGER: Optional["SettingsManager"] = None
+13
View File
@@ -251,6 +251,19 @@ DEFAULT_PRIORITY_TAG_CONFIG = {
"embedding": ", ".join(CIVITAI_MODEL_TAGS),
}
# Default download path template for each model type. "other" defaults to a
# flat layout (empty template) on purpose: other-model downloads are already
# separated by sub_type roots (default_other_roots), and priority_tags has no
# "other" entry, so {first_tag} would resolve to an arbitrary CivitAI tag and
# scatter files into unstable folders. Users can still opt in to a template by
# writing "other" into download_path_templates in settings.json.
DEFAULT_DOWNLOAD_PATH_TEMPLATES: Dict[str, str] = {
"lora": "{base_model}/{first_tag}",
"checkpoint": "{base_model}/{first_tag}",
"embedding": "{base_model}/{first_tag}",
"other": "",
}
# baseModel values from CivitAI that should be treated as diffusion models (unet)
# These model types are incorrectly labeled as "checkpoint" by CivitAI but are actually diffusion models
DIFFUSION_MODEL_BASE_MODELS = frozenset(