diff --git a/locales/de.json b/locales/de.json index ebbc260d..030d92e7 100644 --- a/locales/de.json +++ b/locales/de.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "Trigger Words in LoRA-Syntax einschließen", - "includeTriggerWordsHelp": "Trainierte Trigger Words beim Kopieren der LoRA-Syntax in die Zwischenablage einschließen" + "includeTriggerWordsHelp": "Trainierte Trigger Words beim Kopieren der LoRA-Syntax in die Zwischenablage einschließen", + "loraSyntaxFormat": "[TODO: Translate] LoRA Syntax Format", + "loraSyntaxFormatHelp": "[TODO: Translate] LoRA syntax format. Full includes subfolder path () for lossless model resolution. Legacy uses filename only () — A1111 convention, may be ambiguous with duplicate filenames across folders.", + "loraSyntaxFormatOptions": { + "full": "[TODO: Translate] Full path (subfolder/name)", + "legacy": "[TODO: Translate] Legacy A1111 (name only)" + } }, "metadataArchive": { "enableArchiveDb": "Metadaten-Archiv-Datenbank aktivieren", diff --git a/locales/en.json b/locales/en.json index b025b9e5..df07ed78 100644 --- a/locales/en.json +++ b/locales/en.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "Include Trigger Words in LoRA Syntax", - "includeTriggerWordsHelp": "Include trained trigger words when copying LoRA syntax to clipboard" + "includeTriggerWordsHelp": "Include trained trigger words when copying LoRA syntax to clipboard", + "loraSyntaxFormat": "LoRA Syntax Format", + "loraSyntaxFormatHelp": "LoRA syntax format. Full includes subfolder path () for lossless model resolution. Legacy uses filename only () — A1111 convention, may be ambiguous with duplicate filenames across folders.", + "loraSyntaxFormatOptions": { + "full": "Full path (subfolder/name)", + "legacy": "Legacy A1111 (name only)" + } }, "metadataArchive": { "enableArchiveDb": "Enable Metadata Archive Database", diff --git a/locales/es.json b/locales/es.json index 36825d67..4ec1c110 100644 --- a/locales/es.json +++ b/locales/es.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "Incluir palabras clave en la sintaxis de LoRA", - "includeTriggerWordsHelp": "Incluir palabras clave entrenadas al copiar la sintaxis de LoRA al portapapeles" + "includeTriggerWordsHelp": "Incluir palabras clave entrenadas al copiar la sintaxis de LoRA al portapapeles", + "loraSyntaxFormat": "[TODO: Translate] LoRA Syntax Format", + "loraSyntaxFormatHelp": "[TODO: Translate] LoRA syntax format. Full includes subfolder path () for lossless model resolution. Legacy uses filename only () — A1111 convention, may be ambiguous with duplicate filenames across folders.", + "loraSyntaxFormatOptions": { + "full": "[TODO: Translate] Full path (subfolder/name)", + "legacy": "[TODO: Translate] Legacy A1111 (name only)" + } }, "metadataArchive": { "enableArchiveDb": "Habilitar base de datos de archivo de metadatos", diff --git a/locales/fr.json b/locales/fr.json index 7a02ffd3..72ce096c 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "Inclure les mots-clés dans la syntaxe LoRA", - "includeTriggerWordsHelp": "Inclure les mots-clés d'entraînement lors de la copie de la syntaxe LoRA dans le presse-papiers" + "includeTriggerWordsHelp": "Inclure les mots-clés d'entraînement lors de la copie de la syntaxe LoRA dans le presse-papiers", + "loraSyntaxFormat": "[TODO: Translate] LoRA Syntax Format", + "loraSyntaxFormatHelp": "[TODO: Translate] LoRA syntax format. Full includes subfolder path () for lossless model resolution. Legacy uses filename only () — A1111 convention, may be ambiguous with duplicate filenames across folders.", + "loraSyntaxFormatOptions": { + "full": "[TODO: Translate] Full path (subfolder/name)", + "legacy": "[TODO: Translate] Legacy A1111 (name only)" + } }, "metadataArchive": { "enableArchiveDb": "Activer la base de données d'archive des métadonnées", diff --git a/locales/he.json b/locales/he.json index 8e7c2a1f..a4206f75 100644 --- a/locales/he.json +++ b/locales/he.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "כלול מילות טריגר בתחביר LoRA", - "includeTriggerWordsHelp": "כלול מילות טריגר מאומנות בעת העתקת תחביר LoRA ללוח" + "includeTriggerWordsHelp": "כלול מילות טריגר מאומנות בעת העתקת תחביר LoRA ללוח", + "loraSyntaxFormat": "[TODO: Translate] LoRA Syntax Format", + "loraSyntaxFormatHelp": "[TODO: Translate] LoRA syntax format. Full includes subfolder path () for lossless model resolution. Legacy uses filename only () — A1111 convention, may be ambiguous with duplicate filenames across folders.", + "loraSyntaxFormatOptions": { + "full": "[TODO: Translate] Full path (subfolder/name)", + "legacy": "[TODO: Translate] Legacy A1111 (name only)" + } }, "metadataArchive": { "enableArchiveDb": "הפעל מסד נתונים של ארכיון מטא-דאטה", diff --git a/locales/ja.json b/locales/ja.json index 45113b29..4c76216f 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "LoRA構文にトリガーワードを含める", - "includeTriggerWordsHelp": "LoRA構文をクリップボードにコピーする際、学習済みトリガーワードを含めます" + "includeTriggerWordsHelp": "LoRA構文をクリップボードにコピーする際、学習済みトリガーワードを含めます", + "loraSyntaxFormat": "[TODO: Translate] LoRA Syntax Format", + "loraSyntaxFormatHelp": "[TODO: Translate] LoRA syntax format. Full includes subfolder path () for lossless model resolution. Legacy uses filename only () — A1111 convention, may be ambiguous with duplicate filenames across folders.", + "loraSyntaxFormatOptions": { + "full": "[TODO: Translate] Full path (subfolder/name)", + "legacy": "[TODO: Translate] Legacy A1111 (name only)" + } }, "metadataArchive": { "enableArchiveDb": "メタデータアーカイブデータベースを有効化", diff --git a/locales/ko.json b/locales/ko.json index ef4db6da..903ea104 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "LoRA 문법에 트리거 단어 포함", - "includeTriggerWordsHelp": "LoRA 문법을 클립보드에 복사할 때 학습된 트리거 단어를 포함합니다" + "includeTriggerWordsHelp": "LoRA 문법을 클립보드에 복사할 때 학습된 트리거 단어를 포함합니다", + "loraSyntaxFormat": "[TODO: Translate] LoRA Syntax Format", + "loraSyntaxFormatHelp": "[TODO: Translate] LoRA syntax format. Full includes subfolder path () for lossless model resolution. Legacy uses filename only () — A1111 convention, may be ambiguous with duplicate filenames across folders.", + "loraSyntaxFormatOptions": { + "full": "[TODO: Translate] Full path (subfolder/name)", + "legacy": "[TODO: Translate] Legacy A1111 (name only)" + } }, "metadataArchive": { "enableArchiveDb": "메타데이터 아카이브 데이터베이스 활성화", diff --git a/locales/ru.json b/locales/ru.json index dfbd4b08..bddeca81 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "Включать триггерные слова в синтаксис LoRA", - "includeTriggerWordsHelp": "Включать обученные триггерные слова при копировании синтаксиса LoRA в буфер обмена" + "includeTriggerWordsHelp": "Включать обученные триггерные слова при копировании синтаксиса LoRA в буфер обмена", + "loraSyntaxFormat": "[TODO: Translate] LoRA Syntax Format", + "loraSyntaxFormatHelp": "[TODO: Translate] LoRA syntax format. Full includes subfolder path () for lossless model resolution. Legacy uses filename only () — A1111 convention, may be ambiguous with duplicate filenames across folders.", + "loraSyntaxFormatOptions": { + "full": "[TODO: Translate] Full path (subfolder/name)", + "legacy": "[TODO: Translate] Legacy A1111 (name only)" + } }, "metadataArchive": { "enableArchiveDb": "Включить архив метаданных", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index e60aadb9..11143c17 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "复制 LoRA 语法时包含触发词", - "includeTriggerWordsHelp": "复制 LoRA 语法到剪贴板时包含训练触发词" + "includeTriggerWordsHelp": "复制 LoRA 语法到剪贴板时包含训练触发词", + "loraSyntaxFormat": "LoRA 语法格式", + "loraSyntaxFormatHelp": "LoRA 语法格式。完整路径(Full)包含子文件夹路径 (),解析精确无歧义。旧版(Legacy)仅使用文件名 ()——A1111 原始约定,同名文件跨文件夹时可能产生歧义。", + "loraSyntaxFormatOptions": { + "full": "完整路径(子文件夹/名称)", + "legacy": "旧版 A1111(仅名称)" + } }, "metadataArchive": { "enableArchiveDb": "启用元数据归档数据库", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index cbe87428..68c1cfbd 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -577,7 +577,13 @@ }, "misc": { "includeTriggerWords": "在 LoRA 語法中包含觸發詞", - "includeTriggerWordsHelp": "複製 LoRA 語法到剪貼簿時包含訓練觸發詞" + "includeTriggerWordsHelp": "複製 LoRA 語法到剪貼簿時包含訓練觸發詞", + "loraSyntaxFormat": "LoRA 語法格式", + "loraSyntaxFormatHelp": "LoRA 語法格式。完整路徑(Full)包含子資料夾路徑 (),解析精確無歧義。舊版(Legacy)僅使用檔名 ()——A1111 原始約定,同名檔案跨資料夾時可能產生歧義。", + "loraSyntaxFormatOptions": { + "full": "完整路徑(子資料夾/名稱)", + "legacy": "舊版 A1111(僅名稱)" + } }, "metadataArchive": { "enableArchiveDb": "啟用中繼資料封存資料庫", diff --git a/py/nodes/lora_loader.py b/py/nodes/lora_loader.py index e97a5893..f91d8090 100644 --- a/py/nodes/lora_loader.py +++ b/py/nodes/lora_loader.py @@ -9,6 +9,7 @@ from ..utils.utils import get_lora_info_absolute from .utils import ( FlexibleOptionalInputType, any_type, + apply_lora_syntax_format, detect_nunchaku_model_kind, extract_lora_name, get_loras_list, @@ -52,7 +53,7 @@ def _collect_widget_entries(kwargs): for lora in get_loras_list(kwargs): if not lora.get("active", False): continue - lora_name = lora["name"] + lora_name = apply_lora_syntax_format(lora["name"]) model_strength = float(lora["strength"]) clip_strength = float(lora.get("clipStrength", model_strength)) lora_path, trigger_words = get_lora_info_absolute(lora_name) diff --git a/py/nodes/lora_stacker.py b/py/nodes/lora_stacker.py index 49a57cac..2b3549a1 100644 --- a/py/nodes/lora_stacker.py +++ b/py/nodes/lora_stacker.py @@ -1,6 +1,6 @@ import os from ..utils.utils import get_lora_info -from .utils import FlexibleOptionalInputType, any_type, extract_lora_name, get_loras_list +from .utils import FlexibleOptionalInputType, any_type, apply_lora_syntax_format, extract_lora_name, get_loras_list import logging @@ -48,7 +48,7 @@ class LoraStackerLM: if not lora.get('active', False): continue - lora_name = lora['name'] + lora_name = apply_lora_syntax_format(lora['name']) model_strength = float(lora['strength']) # Get clip strength - use model strength as default if not specified clip_strength = float(lora.get('clipStrength', model_strength)) diff --git a/py/nodes/utils.py b/py/nodes/utils.py index a78a3ff3..6c6f15eb 100644 --- a/py/nodes/utils.py +++ b/py/nodes/utils.py @@ -44,14 +44,29 @@ import folder_paths # type: ignore logger = logging.getLogger(__name__) +def get_lora_syntax_format(): + try: + from ..services.settings_manager import get_settings_manager + return get_settings_manager().get("lora_syntax_format", "legacy") + except Exception: + return "legacy" + + +def apply_lora_syntax_format(name): + fmt = get_lora_syntax_format() + if fmt == "legacy": + return name.replace("\\", "/").rstrip("/").split("/")[-1] + return name + + def extract_lora_name(lora_path): normalized = lora_path.replace("\\", "/") basename = os.path.basename(normalized) name_no_ext = os.path.splitext(basename)[0] dirname = os.path.dirname(normalized) if dirname and dirname not in (".", "/") and not normalized.startswith("/"): - return f"{dirname}/{name_no_ext}" - return name_no_ext + return apply_lora_syntax_format(f"{dirname}/{name_no_ext}") + return apply_lora_syntax_format(name_no_ext) def get_loras_list(kwargs): diff --git a/py/services/settings_manager.py b/py/services/settings_manager.py index e4fb102d..af7bc764 100644 --- a/py/services/settings_manager.py +++ b/py/services/settings_manager.py @@ -96,6 +96,7 @@ DEFAULT_SETTINGS: Dict[str, Any] = { "compact_mode": False, "priority_tags": DEFAULT_PRIORITY_TAG_CONFIG.copy(), "model_name_display": "model_name", + "lora_syntax_format": "legacy", "model_card_footer_action": "replace_preview", "show_version_on_card": True, "update_flag_strategy": "same_base", diff --git a/static/js/state/index.js b/static/js/state/index.js index 15ead32f..c44b8f80 100644 --- a/static/js/state/index.js +++ b/static/js/state/index.js @@ -37,6 +37,7 @@ const DEFAULT_SETTINGS_BASE = Object.freeze({ card_info_display: 'always', show_folder_sidebar: true, model_name_display: 'model_name', + lora_syntax_format: 'legacy', model_card_footer_action: 'example_images', show_version_on_card: true, include_trigger_words: false, diff --git a/static/js/utils/uiHelpers.js b/static/js/utils/uiHelpers.js index 11f0e8c4..db4c5ea7 100644 --- a/static/js/utils/uiHelpers.js +++ b/static/js/utils/uiHelpers.js @@ -420,12 +420,16 @@ export function getLoraStrengthsFromUsageTips(usageTips = {}) { export function buildLoraSyntax(fileName, usageTips = {}) { const { strength, hasStrength, clipStrength, hasClipStrength } = getLoraStrengthsFromUsageTips(usageTips); + const effectiveName = state.global.settings?.lora_syntax_format === 'legacy' + ? fileName.split('/').pop() + : fileName; + if (hasClipStrength) { const modelStrength = hasStrength ? strength : 1; - return ``; + return ``; } - return ``; + return ``; } export function copyLoraSyntax(card) { diff --git a/templates/components/modals/settings_modal.html b/templates/components/modals/settings_modal.html index cafd7d95..f6bbf73b 100644 --- a/templates/components/modals/settings_modal.html +++ b/templates/components/modals/settings_modal.html @@ -536,7 +536,7 @@ - +
@@ -595,6 +595,22 @@

{{ t('settings.sections.misc') }}

+
+
+
+ +
+
+ +
+
+
diff --git a/web/comfyui/autocomplete.js b/web/comfyui/autocomplete.js index 4f29f2c9..8be8e1b3 100644 --- a/web/comfyui/autocomplete.js +++ b/web/comfyui/autocomplete.js @@ -104,6 +104,30 @@ function removeLoraExtension(fileName = '') { return fileName.replace(/\.(safetensors|ckpt|pt|bin)$/i, ''); } +let _loraSyntaxFormatCache = null; + +function _getLoraSyntaxFormat() { + if (typeof _loraSyntaxFormatCache !== 'undefined' && _loraSyntaxFormatCache !== null) { + return _loraSyntaxFormatCache; + } + return 'legacy'; +} +async function _initLoraSyntaxFormat() { + try { + const response = await api.fetchApi('/lm/settings'); + if (response.ok) { + const data = await response.json(); + if (data.success && data.settings) { + _loraSyntaxFormatCache = data.settings.lora_syntax_format || 'legacy'; + return; + } + } + } catch (e) { + } + _loraSyntaxFormatCache = 'legacy'; +} +_initLoraSyntaxFormat(); + function parseSearchTokens(term = '') { const include = []; const exclude = []; @@ -231,6 +255,10 @@ const MODEL_BEHAVIORS = { const folder = directories.length ? directories.join('/') + '/' : ''; const loraName = folder + baseName; + const resultName = _getLoraSyntaxFormat() === 'legacy' + ? baseName + : loraName; + let strength = 1.0; let hasStrength = false; let clipStrength = null; @@ -265,9 +293,9 @@ const MODEL_BEHAVIORS = { } if (clipStrength !== null) { - return formatAutocompleteInsertion(``); + return formatAutocompleteInsertion(``); } - return formatAutocompleteInsertion(``); + return formatAutocompleteInsertion(``); } }, embeddings: {