|
|
|
@@ -20,19 +20,48 @@ NODE_DISPLAY_NAME_MAPPINGS = {}
|
|
|
|
|
PARAMETER_LABELS = {
|
|
|
|
|
"multiline_text": "多行文本",
|
|
|
|
|
"use_file": "使用文件",
|
|
|
|
|
"file_path": "文件路径",
|
|
|
|
|
"file_folder": "提示词文件夹",
|
|
|
|
|
"file_name": "文件名",
|
|
|
|
|
"mode": "运行模式",
|
|
|
|
|
"label": "队列标识",
|
|
|
|
|
"preset": "预设模板",
|
|
|
|
|
"template": "模板",
|
|
|
|
|
"save_preset": "保存预设",
|
|
|
|
|
"delete_preset": "删除预设",
|
|
|
|
|
"global_prefix": "全局前缀",
|
|
|
|
|
"artist_style_prompt": "画师风格提示词",
|
|
|
|
|
"prompt_suffix": "提示词后缀",
|
|
|
|
|
"preset_name_for_save": "保存预设名称",
|
|
|
|
|
"index_setting": "索引设置"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _pq_normalize_prompt_part(s: str) -> str:
|
|
|
|
|
"""清理提示词片段首尾空白与多余逗号,避免拼接后出现 ', ,' 或 ',,'。"""
|
|
|
|
|
if s is None:
|
|
|
|
|
return ""
|
|
|
|
|
s = str(s).strip()
|
|
|
|
|
# 仅处理首尾逗号(不改中间内容)
|
|
|
|
|
s = s.strip(",").strip()
|
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _pq_build_prompt_file_path(file_folder: str, file_name: str) -> str:
|
|
|
|
|
"""
|
|
|
|
|
将“提示词文件夹 + 文件名”组合成最终 .txt 路径。
|
|
|
|
|
- file_name 若已包含 .txt(忽略大小写),则不重复追加。
|
|
|
|
|
- file_folder 可为空;为空时返回 file_name(便于直接写完整路径)。
|
|
|
|
|
"""
|
|
|
|
|
folder = str(file_folder or "").strip()
|
|
|
|
|
name = str(file_name or "").strip()
|
|
|
|
|
if not name:
|
|
|
|
|
return ""
|
|
|
|
|
if not name.lower().endswith(".txt"):
|
|
|
|
|
name = name + ".txt"
|
|
|
|
|
if folder:
|
|
|
|
|
return os.path.join(folder, name)
|
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
|
def parse_frame_prompts(raw_text: str):
|
|
|
|
|
"""
|
|
|
|
|
解析输入为 {frame_index: prompt} 的升序字典。
|
|
|
|
@@ -328,7 +357,7 @@ class StylePromptQueue:
|
|
|
|
|
[增量模式] 风格化提示词队列节点。
|
|
|
|
|
- 每次运行仅输出一行提示词。
|
|
|
|
|
- 即使 Batch Size > 1,也全部使用这一行(用于提高容错率)。
|
|
|
|
|
- 索引设置:支持 "-1"(记忆), "0"(重置), "5"(指定行), "2,8,35"(列表)
|
|
|
|
|
- 索引设置:支持 "-1"(记忆/自动), "0"(从0开始), "5"(从5开始), "2,8,35"(列表循环)
|
|
|
|
|
"""
|
|
|
|
|
@classmethod
|
|
|
|
|
def INPUT_TYPES(cls):
|
|
|
|
@@ -339,11 +368,13 @@ class StylePromptQueue:
|
|
|
|
|
return {
|
|
|
|
|
"required": {
|
|
|
|
|
"clip": ("CLIP",),
|
|
|
|
|
"全局前缀": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"画师风格提示词": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"多行文本": ("STRING", {"multiline": True, "default": "A cat\nA dog"}),
|
|
|
|
|
"提示词后缀": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"使用文件": ("BOOLEAN", {"default": False}),
|
|
|
|
|
"文件路径": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"提示词文件夹": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"文件名": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"索引设置": ("STRING", {"multiline": False, "default": "-1"}),
|
|
|
|
|
"预设模板": (preset_list, {"default": "None"}),
|
|
|
|
|
"保存预设名称": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
@@ -357,7 +388,10 @@ class StylePromptQueue:
|
|
|
|
|
FUNCTION = "run"
|
|
|
|
|
CATEGORY = "PromptQueue"
|
|
|
|
|
|
|
|
|
|
def run(self, clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板, 保存预设名称, 保存预设, 删除预设):
|
|
|
|
|
def run(self, clip, 全局前缀, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 提示词文件夹, 文件名, 索引设置, 预设模板, 保存预设名称, 保存预设, 删除预设, unique_id=None):
|
|
|
|
|
# 全局前缀:仅当输入不为空时生效;留空则完全等同于旧逻辑
|
|
|
|
|
global_prefix = _pq_normalize_prompt_part(全局前缀)
|
|
|
|
|
|
|
|
|
|
prefix = 画师风格提示词
|
|
|
|
|
suffix = 提示词后缀
|
|
|
|
|
|
|
|
|
@@ -412,12 +446,18 @@ class StylePromptQueue:
|
|
|
|
|
suffix = ""
|
|
|
|
|
print(f"[Style Prompt Queue] 无法解析预设 '{预设模板}',已作为前缀处理")
|
|
|
|
|
|
|
|
|
|
lines = _read_lines_from_source(多行文本, 文件路径, 使用文件)
|
|
|
|
|
# 组合文件路径(优先“文件夹+文件名”,回退到“文件路径”以兼容旧工作流)
|
|
|
|
|
effective_file_path = _pq_build_prompt_file_path(提示词文件夹, 文件名)
|
|
|
|
|
lines = _read_lines_from_source(多行文本, effective_file_path, 使用文件)
|
|
|
|
|
|
|
|
|
|
# 应用前缀和后缀
|
|
|
|
|
final_lines = []
|
|
|
|
|
for line in lines:
|
|
|
|
|
parts = [p for p in [prefix, line, suffix] if p and p.strip()]
|
|
|
|
|
parts = []
|
|
|
|
|
for p in [global_prefix, prefix, line, suffix]:
|
|
|
|
|
pp = _pq_normalize_prompt_part(p)
|
|
|
|
|
if pp:
|
|
|
|
|
parts.append(pp)
|
|
|
|
|
final_lines.append(", ".join(parts))
|
|
|
|
|
|
|
|
|
|
if not final_lines:
|
|
|
|
@@ -430,31 +470,61 @@ class StylePromptQueue:
|
|
|
|
|
idx_mode = indices[0]
|
|
|
|
|
|
|
|
|
|
target_idx = 0
|
|
|
|
|
desc = _pq_source_descriptor(使用文件, effective_file_path, 多行文本)
|
|
|
|
|
|
|
|
|
|
# 扩展逻辑:支持 "Start From X" 且自动递增
|
|
|
|
|
# 检测 索引设置变更 或 源内容变更
|
|
|
|
|
|
|
|
|
|
queue_label = "Auto_Queue"
|
|
|
|
|
if unique_id:
|
|
|
|
|
queue_label = f"{unique_id}_Auto_Queue"
|
|
|
|
|
|
|
|
|
|
current_setting_str = str(索引设置).strip()
|
|
|
|
|
# 索引设置状态也需要隔离,否则不同节点使用相同文本但不同设置时会互相干扰
|
|
|
|
|
setting_key = f"{queue_label}_Settings_{desc}"
|
|
|
|
|
last_setting = _pq_store.get("Index Settings", setting_key, "")
|
|
|
|
|
|
|
|
|
|
setting_changed = (current_setting_str != last_setting)
|
|
|
|
|
if setting_changed:
|
|
|
|
|
_pq_store.put("Index Settings", setting_key, current_setting_str)
|
|
|
|
|
|
|
|
|
|
# 获取 Auto_Queue 的最后一次源,用于判断是否发生源变更
|
|
|
|
|
last_source = _pq_store.get("PromptQueue Sources", queue_label, None)
|
|
|
|
|
source_changed = (last_source != desc)
|
|
|
|
|
|
|
|
|
|
should_reset_counter = setting_changed or source_changed
|
|
|
|
|
|
|
|
|
|
if idx_mode == -1:
|
|
|
|
|
# 记忆模式 (Auto/Resume)
|
|
|
|
|
# 使用原有的 _pq_get_next_index 逻辑,自动递增
|
|
|
|
|
# 队列标识这里隐式使用 "Index Setting - Auto" 或者是文件名哈希,
|
|
|
|
|
# 为了简单起见,我们还是需要一个 Key。
|
|
|
|
|
# 这里我们用 "Auto_Queue" + 文件描述符 作为 key
|
|
|
|
|
desc = _pq_source_descriptor(使用文件, 文件路径, 多行文本)
|
|
|
|
|
target_idx = _pq_get_next_index("Auto_Queue", len(final_lines), desc)
|
|
|
|
|
target_idx = _pq_get_next_index(queue_label, len(final_lines), desc)
|
|
|
|
|
|
|
|
|
|
elif idx_mode == 0:
|
|
|
|
|
# 重置/顺序模式 (Reset to 0)
|
|
|
|
|
target_idx = 0
|
|
|
|
|
elif len(indices) == 1 and idx_mode >= 0:
|
|
|
|
|
# 0: Auto from beginning (Start from 0 + Auto Increment)
|
|
|
|
|
# N > 0: Fixed single line N (1-based index) -> Index N-1
|
|
|
|
|
|
|
|
|
|
if idx_mode == 0:
|
|
|
|
|
# Auto Mode (0)
|
|
|
|
|
if should_reset_counter:
|
|
|
|
|
_pq_store.put("PromptQueue Counters", queue_label, 0)
|
|
|
|
|
_pq_store.put("PromptQueue Sources", queue_label, desc)
|
|
|
|
|
|
|
|
|
|
target_idx = _pq_get_next_index(queue_label, len(final_lines), desc)
|
|
|
|
|
else:
|
|
|
|
|
# Fixed Line Mode (e.g. 1 -> 1st line -> index 0)
|
|
|
|
|
# Non-incremental
|
|
|
|
|
target_idx = idx_mode - 1
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
# 指定模式 / 列表模式
|
|
|
|
|
if len(indices) == 1:
|
|
|
|
|
target_idx = indices[0]
|
|
|
|
|
else:
|
|
|
|
|
# 列表循环
|
|
|
|
|
# 使用一个基于列表内容的特殊 key
|
|
|
|
|
list_key = f"List_{索引设置}"
|
|
|
|
|
# 这里的 total 是列表长度
|
|
|
|
|
list_idx = _pq_get_next_index(list_key, len(indices), list_key)
|
|
|
|
|
target_idx = indices[list_idx]
|
|
|
|
|
# 列表模式 (2,8,35) -> 视为 1-based index
|
|
|
|
|
# 使用一个基于列表内容的特殊 key
|
|
|
|
|
list_key = f"List_{索引设置}"
|
|
|
|
|
# 这里的 total 是列表长度
|
|
|
|
|
list_idx = _pq_get_next_index(list_key, len(indices), list_key)
|
|
|
|
|
val = indices[list_idx]
|
|
|
|
|
# 转换为 0-based
|
|
|
|
|
target_idx = val - 1
|
|
|
|
|
if target_idx < 0:
|
|
|
|
|
target_idx = 0
|
|
|
|
|
|
|
|
|
|
# 越界保护
|
|
|
|
|
if target_idx >= len(final_lines):
|
|
|
|
@@ -462,6 +532,9 @@ class StylePromptQueue:
|
|
|
|
|
if target_idx < 0:
|
|
|
|
|
target_idx = 0
|
|
|
|
|
|
|
|
|
|
# Debug print
|
|
|
|
|
print(f"[PromptQueue] Index Setting: '{索引设置}' -> Mode: {idx_mode} -> Target Line: {target_idx + 1}")
|
|
|
|
|
|
|
|
|
|
line_to_process = final_lines[target_idx]
|
|
|
|
|
|
|
|
|
|
ordered = [(0, line_to_process)]
|
|
|
|
@@ -470,7 +543,7 @@ class StylePromptQueue:
|
|
|
|
|
return ([[cond, meta]], line_to_process)
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def IS_CHANGED(cls, clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板, 保存预设名称, 保存预设, 删除预设):
|
|
|
|
|
def IS_CHANGED(cls, clip, 全局前缀, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 提示词文件夹, 文件名, 索引设置, 预设模板, 保存预设名称, 保存预设, 删除预设):
|
|
|
|
|
# 始终返回时间戳以强制重新执行
|
|
|
|
|
return str(time.time())
|
|
|
|
|
|
|
|
|
@@ -487,22 +560,39 @@ class SimpleStylePromptQueue(StylePromptQueue):
|
|
|
|
|
return {
|
|
|
|
|
"required": {
|
|
|
|
|
"clip": ("CLIP",),
|
|
|
|
|
"全局前缀": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"画师风格提示词": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"多行文本": ("STRING", {"multiline": True, "default": "A cat\nA dog"}),
|
|
|
|
|
"提示词后缀": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"使用文件": ("BOOLEAN", {"default": False}),
|
|
|
|
|
"文件路径": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"提示词文件夹": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"文件名": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"索引设置": ("STRING", {"multiline": False, "default": "-1"}),
|
|
|
|
|
"预设模板": (preset_list, {"default": "None"}),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def run(self, clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板):
|
|
|
|
|
def run(self, clip, 全局前缀, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 提示词文件夹, 文件名, 索引设置, 预设模板, unique_id=None):
|
|
|
|
|
# 调用父类的 run,传入 None/False 作为预设参数
|
|
|
|
|
return super().run(clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板, "", False, False)
|
|
|
|
|
return super().run(
|
|
|
|
|
clip,
|
|
|
|
|
全局前缀,
|
|
|
|
|
画师风格提示词,
|
|
|
|
|
多行文本,
|
|
|
|
|
提示词后缀,
|
|
|
|
|
使用文件,
|
|
|
|
|
提示词文件夹,
|
|
|
|
|
文件名,
|
|
|
|
|
索引设置,
|
|
|
|
|
预设模板,
|
|
|
|
|
"",
|
|
|
|
|
False,
|
|
|
|
|
False,
|
|
|
|
|
unique_id=unique_id
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def IS_CHANGED(cls, clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板):
|
|
|
|
|
def IS_CHANGED(cls, clip, 全局前缀, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 提示词文件夹, 文件名, 索引设置, 预设模板):
|
|
|
|
|
return str(time.time())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -520,11 +610,13 @@ class StylePromptQueueBatch:
|
|
|
|
|
return {
|
|
|
|
|
"required": {
|
|
|
|
|
"clip": ("CLIP",),
|
|
|
|
|
"全局前缀": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"画师风格提示词": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"多行文本": ("STRING", {"multiline": True, "default": "A cat\nA dog"}),
|
|
|
|
|
"提示词后缀": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"使用文件": ("BOOLEAN", {"default": False}),
|
|
|
|
|
"文件路径": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"提示词文件夹": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"文件名": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"索引设置": ("STRING", {"multiline": False, "default": "0"}),
|
|
|
|
|
"预设模板": (preset_list, {"default": "None"}),
|
|
|
|
|
"保存预设名称": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
@@ -538,7 +630,10 @@ class StylePromptQueueBatch:
|
|
|
|
|
FUNCTION = "run"
|
|
|
|
|
CATEGORY = "PromptQueue"
|
|
|
|
|
|
|
|
|
|
def run(self, clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板, 保存预设名称, 保存预设, 删除预设):
|
|
|
|
|
def run(self, clip, 全局前缀, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 提示词文件夹, 文件名, 索引设置, 预设模板, 保存预设名称, 保存预设, 删除预设):
|
|
|
|
|
# 全局前缀:仅当输入不为空时生效;留空则完全等同于旧逻辑
|
|
|
|
|
global_prefix = _pq_normalize_prompt_part(全局前缀)
|
|
|
|
|
|
|
|
|
|
prefix = 画师风格提示词
|
|
|
|
|
suffix = 提示词后缀
|
|
|
|
|
|
|
|
|
@@ -579,11 +674,16 @@ class StylePromptQueueBatch:
|
|
|
|
|
prefix = preset_content
|
|
|
|
|
suffix = ""
|
|
|
|
|
|
|
|
|
|
lines = _read_lines_from_source(多行文本, 文件路径, 使用文件)
|
|
|
|
|
effective_file_path = _pq_build_prompt_file_path(提示词文件夹, 文件名)
|
|
|
|
|
lines = _read_lines_from_source(多行文本, effective_file_path, 使用文件)
|
|
|
|
|
|
|
|
|
|
final_lines = []
|
|
|
|
|
for line in lines:
|
|
|
|
|
parts = [p for p in [prefix, line, suffix] if p and p.strip()]
|
|
|
|
|
parts = []
|
|
|
|
|
for p in [global_prefix, prefix, line, suffix]:
|
|
|
|
|
pp = _pq_normalize_prompt_part(p)
|
|
|
|
|
if pp:
|
|
|
|
|
parts.append(pp)
|
|
|
|
|
final_lines.append(", ".join(parts))
|
|
|
|
|
|
|
|
|
|
if not final_lines:
|
|
|
|
@@ -651,22 +751,24 @@ class SimpleStylePromptQueueBatch(StylePromptQueueBatch):
|
|
|
|
|
return {
|
|
|
|
|
"required": {
|
|
|
|
|
"clip": ("CLIP",),
|
|
|
|
|
"全局前缀": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"画师风格提示词": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"多行文本": ("STRING", {"multiline": True, "default": "A cat\nA dog"}),
|
|
|
|
|
"提示词后缀": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"使用文件": ("BOOLEAN", {"default": False}),
|
|
|
|
|
"文件路径": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"提示词文件夹": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"文件名": ("STRING", {"multiline": False, "default": ""}),
|
|
|
|
|
"索引设置": ("STRING", {"multiline": False, "default": "0"}),
|
|
|
|
|
"预设模板": (preset_list, {"default": "None"}),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def run(self, clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板):
|
|
|
|
|
def run(self, clip, 全局前缀, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 提示词文件夹, 文件名, 索引设置, 预设模板):
|
|
|
|
|
# 调用父类的 run,传入 None 作为预设参数
|
|
|
|
|
return super().run(clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板, "", False, False)
|
|
|
|
|
return super().run(clip, 全局前缀, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 提示词文件夹, 文件名, 索引设置, 预设模板, "", False, False)
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def IS_CHANGED(cls, clip, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 文件路径, 索引设置, 预设模板):
|
|
|
|
|
def IS_CHANGED(cls, clip, 全局前缀, 画师风格提示词, 多行文本, 提示词后缀, 使用文件, 提示词文件夹, 文件名, 索引设置, 预设模板):
|
|
|
|
|
return float("nan")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -797,7 +899,7 @@ def _pq_delete_negative_template_preset(name: str) -> None:
|
|
|
|
|
# 注册新节点
|
|
|
|
|
NODE_CLASS_MAPPINGS.update({
|
|
|
|
|
"NegativePromptQueue": NegativePromptQueue,
|
|
|
|
|
"StylePromptQueue": "PromptQueue 增量",
|
|
|
|
|
"StylePromptQueue": StylePromptQueue,
|
|
|
|
|
"SimpleStylePromptQueue": SimpleStylePromptQueue,
|
|
|
|
|
"StylePromptQueueBatch": StylePromptQueueBatch,
|
|
|
|
|
"SimpleStylePromptQueueBatch": SimpleStylePromptQueueBatch,
|
|
|
|
|