Spaces:
Running
Running
| from copy import deepcopy | |
| from src.prompt_parser import ParsedPrompt | |
| from src.tag_warehouse import TagWarehouse | |
| from src.synonym_data import _load_groups, _find_synonym_group | |
| def get_synonym_conflicts(tag: str, other_tags: list[str]) -> list[str]: | |
| if not other_tags: | |
| return [] | |
| tag_group = _find_synonym_group(tag) | |
| if tag_group is None: | |
| return [] | |
| other_lower = {o.lower().strip() for o in other_tags} | |
| return [o for o in other_tags if o.lower().strip() in tag_group and o.lower().strip() != tag.lower().strip()] | |
| def has_synonym_conflict(tag: str, existing: list[str]) -> bool: | |
| group = _find_synonym_group(tag) | |
| if group is None: | |
| return False | |
| tag_lower = tag.lower().strip() | |
| existing_lower = {e.lower().strip() for e in existing} | |
| for member in group: | |
| if member != tag_lower and member in existing_lower: | |
| return True | |
| return False | |
| def filter_synonym_duplicates(tags: list[str]) -> list[str]: | |
| if not tags: | |
| return [] | |
| result = [] | |
| for t in tags: | |
| if not has_synonym_conflict(t, result): | |
| result.append(t) | |
| return result | |
| def filter_user_against_category_tags( | |
| user_tags: list[str], | |
| category_tags: list[str], | |
| ) -> list[str]: | |
| """Preserve the user's explicit tags. | |
| Previously this stripped any user tag that shared a synonym group with the | |
| selected category pools, which silently erased the user's stated intent | |
| (e.g. "blue hair" vanished because "blue hair" also lives in the hair pool). | |
| Generation now keeps the user's tags and only drops internal synonym | |
| duplicates, relying on the engine's protected-set / head-noun guard to avoid | |
| re-adding redundant tags. | |
| """ | |
| if not user_tags: | |
| return [] | |
| return filter_synonym_duplicates(user_tags) | |
| def apply_synonym_filter( | |
| parsed: ParsedPrompt, | |
| selected_categories: list[str], | |
| warehouse: TagWarehouse, | |
| model: str = "anima", | |
| rating: str = "pg", | |
| ) -> ParsedPrompt: | |
| """Drop internal synonym duplicates from the user's own tags. | |
| Category pool membership is intentionally NOT consulted here: the previous | |
| behavior of stripping user tags that collide with a pool erased explicit | |
| user intent. `warehouse`/`rating` stay in the signature for API compat. | |
| """ | |
| if parsed is None: | |
| return parsed | |
| result = deepcopy(parsed) | |
| if result.general_tags is None: | |
| result.general_tags = [] | |
| result.general_tags = filter_synonym_duplicates(result.general_tags) | |
| return result | |
| def reload_groups(): | |
| from src.synonym_data import reload_synonym_groups | |
| reload_synonym_groups() | |
| _load_groups() | |