mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-24 22:52:12 -03:00
chore(priority-tags): add newline terminator
This commit is contained in:
@@ -64,4 +64,11 @@ CIVITAI_MODEL_TAGS = [
|
||||
'realistic', 'anime', 'toon', 'furry', 'style',
|
||||
'poses', 'background', 'tool', 'vehicle', 'buildings',
|
||||
'objects', 'assets', 'animal', 'action'
|
||||
]
|
||||
]
|
||||
|
||||
# Default priority tag configuration strings for each model type
|
||||
DEFAULT_PRIORITY_TAG_CONFIG = {
|
||||
'lora': ', '.join(CIVITAI_MODEL_TAGS),
|
||||
'checkpoint': ', '.join(CIVITAI_MODEL_TAGS),
|
||||
'embedding': ', '.join(CIVITAI_MODEL_TAGS),
|
||||
}
|
||||
|
||||
104
py/utils/tag_priorities.py
Normal file
104
py/utils/tag_priorities.py
Normal file
@@ -0,0 +1,104 @@
|
||||
"""Helpers for parsing and resolving priority tag configurations."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, Iterable, List, Optional, Sequence, Set
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PriorityTagEntry:
|
||||
"""A parsed priority tag configuration entry."""
|
||||
|
||||
canonical: str
|
||||
aliases: Set[str]
|
||||
|
||||
@property
|
||||
def normalized_aliases(self) -> Set[str]:
|
||||
return {alias.lower() for alias in self.aliases}
|
||||
|
||||
|
||||
def _normalize_alias(alias: str) -> str:
|
||||
return alias.strip()
|
||||
|
||||
|
||||
def parse_priority_tag_string(config: str | None) -> List[PriorityTagEntry]:
|
||||
"""Parse the user-facing priority tag string into structured entries."""
|
||||
|
||||
if not config:
|
||||
return []
|
||||
|
||||
entries: List[PriorityTagEntry] = []
|
||||
seen_canonicals: Set[str] = set()
|
||||
|
||||
for raw_entry in _split_priority_entries(config):
|
||||
canonical, aliases = _parse_priority_entry(raw_entry)
|
||||
if not canonical:
|
||||
continue
|
||||
|
||||
normalized_canonical = canonical.lower()
|
||||
if normalized_canonical in seen_canonicals:
|
||||
# Skip duplicate canonicals while preserving first occurrence priority
|
||||
continue
|
||||
seen_canonicals.add(normalized_canonical)
|
||||
|
||||
alias_set = {canonical, *aliases}
|
||||
cleaned_aliases = {_normalize_alias(alias) for alias in alias_set if _normalize_alias(alias)}
|
||||
if not cleaned_aliases:
|
||||
continue
|
||||
|
||||
entries.append(PriorityTagEntry(canonical=canonical, aliases=cleaned_aliases))
|
||||
|
||||
return entries
|
||||
|
||||
|
||||
def _split_priority_entries(config: str) -> List[str]:
|
||||
# Split on commas while respecting that users may add new lines for readability
|
||||
parts = []
|
||||
for chunk in config.split('\n'):
|
||||
parts.extend(chunk.split(','))
|
||||
return [part.strip() for part in parts if part.strip()]
|
||||
|
||||
|
||||
def _parse_priority_entry(entry: str) -> tuple[str, Set[str]]:
|
||||
if '(' in entry and entry.endswith(')'):
|
||||
canonical, raw_aliases = entry.split('(', 1)
|
||||
canonical = canonical.strip()
|
||||
alias_section = raw_aliases[:-1] # drop trailing ')'
|
||||
aliases = {alias.strip() for alias in alias_section.split('|') if alias.strip()}
|
||||
return canonical, aliases
|
||||
|
||||
if '(' in entry and not entry.endswith(')'):
|
||||
# Malformed entry; treat as literal canonical to avoid surprises
|
||||
entry = entry.replace('(', '').replace(')', '')
|
||||
|
||||
canonical = entry.strip()
|
||||
return canonical, set()
|
||||
|
||||
|
||||
def resolve_priority_tag(
|
||||
tags: Sequence[str] | Iterable[str],
|
||||
entries: Sequence[PriorityTagEntry],
|
||||
) -> Optional[str]:
|
||||
"""Resolve the first matching canonical priority tag for the provided tags."""
|
||||
|
||||
tag_lookup: Dict[str, str] = {}
|
||||
for tag in tags:
|
||||
if not isinstance(tag, str):
|
||||
continue
|
||||
normalized = tag.lower()
|
||||
if normalized not in tag_lookup:
|
||||
tag_lookup[normalized] = tag
|
||||
|
||||
for entry in entries:
|
||||
for alias in entry.normalized_aliases:
|
||||
if alias in tag_lookup:
|
||||
return entry.canonical
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def collect_canonical_tags(entries: Iterable[PriorityTagEntry]) -> List[str]:
|
||||
"""Return the ordered list of canonical tags from the parsed entries."""
|
||||
|
||||
return [entry.canonical for entry in entries]
|
||||
@@ -4,7 +4,6 @@ from typing import Dict
|
||||
from ..services.service_registry import ServiceRegistry
|
||||
from ..config import config
|
||||
from ..services.settings_manager import get_settings_manager
|
||||
from .constants import CIVITAI_MODEL_TAGS
|
||||
import asyncio
|
||||
|
||||
def get_lora_info(lora_name):
|
||||
@@ -170,16 +169,7 @@ def calculate_relative_path_for_model(model_data: Dict, model_type: str = 'lora'
|
||||
base_model_mappings = settings_manager.get('base_model_path_mappings', {})
|
||||
mapped_base_model = base_model_mappings.get(base_model, base_model)
|
||||
|
||||
# Find the first Civitai model tag that exists in model_tags
|
||||
first_tag = ''
|
||||
for civitai_tag in CIVITAI_MODEL_TAGS:
|
||||
if civitai_tag in model_tags:
|
||||
first_tag = civitai_tag
|
||||
break
|
||||
|
||||
# If no Civitai model tag found, fallback to first tag
|
||||
if not first_tag and model_tags:
|
||||
first_tag = model_tags[0]
|
||||
first_tag = settings_manager.resolve_priority_tag_for_model(model_tags, model_type)
|
||||
|
||||
if not first_tag:
|
||||
first_tag = 'no tags' # Default if no tags available
|
||||
|
||||
Reference in New Issue
Block a user