6 Commits
Author SHA1 Message Date
Cyan9977 00cdff5422 Add files via upload 2025-12-24 12:41:17 +08:00
Cyan9977 0b86452a6e Add files via upload 2025-12-23 19:39:38 +08:00
Cyan9977 fbbe3d2e60 Add files via upload 2025-12-10 09:45:27 +08:00
Cyan9977 28cb7cfec3 Add files via upload 2025-12-09 16:40:09 +08:00
Cyan9977 09c4f12d94 Add files via upload 2025-12-09 16:16:05 +08:00
Cyan9977 9780a9d720 Add files via upload 2025-12-09 15:22:13 +08:00
2 changed files with 150 additions and 42 deletions
+9 -3
View File
@@ -33,14 +33,19 @@
* **核心逻辑**: 每次运行只输出**一行**提示词。
* **容错机制**: 如果您的 KSampler 设置 `Batch Size > 1` (例如 4),该节点会输出 4 份**完全相同**的 conditioning。这意味着您将得到 4 张基于同一提示词的图片,方便优选,提高出图容错率。
* **参数详解**:
* **全局前缀**: 一个全局通用的提示词前缀(例如通用画质词、常用 LoRA 触发词等),**始终拼在最前面**。
* **使用规则**: 仅当你在“全局前缀”里填写内容时才会生效;留空则等同于旧版本逻辑(不添加任何全局前缀)。
* **画师风格提示词 (前缀)**: 输入风格、艺术家等前缀。
* **多行文本**: 核心主体提示词列表,每行一个。
* **提示词后缀**: 画面质量、细节描述等通用后缀。
* **使用文件**: 从文件读取提示词列表(每行一个)。
* **提示词文件夹 / 文件名**: 将文件路径拆分为“文件夹 + 文件名”,文件扩展名固定为 `.txt`。
* 示例:文件夹 `C:\Users\Administrator\Desktop\prompt` + 文件名 `21` -> 实际读取 `...\prompt\21.txt`
* **索引设置 (核心功能)**: 控制本次运行使用哪一行提示词。
* `-1` (或留空): **记忆模式**。接着上次的进度继续跑(适合长序列生成)。
* `0`: **重置模式**。强制本次任务从第 1 行开始(适合完成调试后想完整跑一遍)。
* `5`: **锁定模式**。强制本次任务只跑第 6 行(适合反复调试特定提示词)。
* `2,8,35`: **列表模式**。只在第 3、9、36 行之间循环生成(适合精选生成)。
* `0`: **顺序模式**。重置计数器,从第 1 行开始,并在每次生成后自动递增(适合想从头完整跑一遍队列)。
* `5` (数字 > 0): **指定模式**。强制只跑第 N 行 (如输入 5 则跑第 5 行),**不会**自动递增(适合反复调试特定提示词)。
* `2,8,35`: **列表模式**。只在第 2、8、35 行之间循环生成(适合精选生成)。
* **文本输出**: 提供 `prompt_text` 输出端口,可连接 ShowText 节点查看当前使用的完整提示词。
### 2. PQ (Batch) / 批量队列 🆕
@@ -51,6 +56,7 @@
* **预设支持**: 现已支持保存和加载预设模板。
* **⚠️ 注意**: 保存或删除预设后,请**刷新浏览器**以更新预设列表。
* **文本输出**: 提供 `prompt_text_list` 输出端口,输出当前批次的所有提示词文本。
* **提示词来源**: 同样支持“使用文件 + 提示词文件夹/文件名(固定 .txt)”。
### 3. PQ Simple / 简易版系列 🆕
包含 **增量简易** (`PQ Simple (Incr.)`) 和 **批量简易** (`PQ Simple (Batch)`) 两个节点。
+141 -39
View File
@@ -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,