import re
import json
from typing import Tuple, List
class PromptValidator:
""" Stable Diffusion 提示词基础语法校验器 """
CONFLICT_PAIRS = [
(["masterpiece", "best quality", "highres"], ["worst quality", "lowres", "bad quality"]),
(["detailed", "intricate"], ["blurry", "simple"]),
(["photorealistic", "realistic"], ["anime", "cartoon", "painting"]),
]
OBSOLETE_TAGS = ["ng_deepnegative_v1_75t", "easynegative"]
def __init__(self):
self.errors = []
self.warnings = []
self.suggestions = []
def validate(self, prompt: str) -> dict:
"""主校验函数"""
self.errors.clear()
self.warnings.clear()
self.suggestions.clear()
if not prompt or prompt.strip() == "":
self.errors.append("提示词不能为空")
return self._generate_report()
prompt_lower = prompt.lower()
self._check_conflicts(prompt_lower)
self._check_obsolete_tags(prompt_lower)
self._check_weight_syntax(prompt)
self._check_semantic_contradictions(prompt_lower)
if not self.errors:
self._generate_suggestions(prompt)
return self._generate_report()
def _check_conflicts(self, prompt: str):
for positive_group, negative_group in self.CONFLICT_PAIRS:
has_positive = any(word in prompt for word in positive_group)
has_negative = any(word in prompt for word in negative_group)
if has_positive and has_negative:
self.warnings.append(f"提示词中可能包含冲突描述:{positive_group} 与 {negative_group} 同时存在,可能导致模型困惑。")
def _check_obsolete_tags(self, prompt: str):
for tag in self.OBSOLETE_TAGS:
if tag in prompt:
self.warnings.append(f"检测到可能对 SD3.5 无效或效果不佳的旧版标签:'{tag}',建议移除或替换。")
def _check_weight_syntax(self, prompt: str):
stack = []
for i, char in enumerate(prompt):
if char == '(':
stack.append(i)
elif char == ')':
if not stack:
self.errors.append(f"括号不匹配:在位置 {i} 发现多余的 ')' ")
else:
stack.pop()
if stack:
self.errors.append(f"括号不匹配:{len(stack)} 个 '(' 没有闭合")
def _check_semantic_contradictions(self, prompt: str):
contradictions = [
(["red", "blue"], "同时描述红色和蓝色可能矛盾"),
(["day", "night"], "同时描述白天和夜晚可能矛盾"),
(["indoor", "outdoor"], "同时描述室内和室外可能矛盾"),
]
for words, message in contradictions:
if all(word in prompt for word in words):
self.warnings.append(f"语义警告:{message}")
def _generate_suggestions(self, prompt: str):
if len(prompt) < 20:
self.suggestions.append("提示词较短,可以尝试添加更多细节描述(如环境、光线、材质、视角)来获得更精确的图像。")
if "4k" in prompt or "8k" in prompt:
self.suggestions.append("SD3.5 已具备高细节生成能力,'4k'、'8k'等标签可能非必需,可尝试移除以简化提示词。")
def _generate_report(self) -> dict:
return {
"is_valid": len(self.errors) == 0,
"errors": self.errors.copy(),
"warnings": self.warnings.copy(),
"suggestions": self.suggestions.copy()
}
import nodes
import folder_paths
class PromptValidatorNode:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"prompt": ("STRING", {"multiline": True, "default": "masterpiece, best quality, 1girl, beautiful detailed eyes"}),
},
}
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("validated_prompt", "validation_report")
FUNCTION = "validate"
CATEGORY = "utils"
def validate(self, prompt):
validator = PromptValidator()
report = validator.validate(prompt)
report_str = "=== 提示词校验报告 ===\n"
if report['errors']:
report_str += "❌ 错误:\n" + "\n".join(f" - {e}" for e in report['errors']) + "\n"
if report['warnings']:
report_str += "⚠️ 警告:\n" + "\n".join(f" - {w}" for w in report['warnings']) + "\n"
if report['suggestions']:
report_str += "💡 建议:\n" + "\n".join(f" - {s}" for s in report['suggestions']) + "\n"
if report['is_valid'] and not report['warnings']:
report_str += "✅ 提示词语法检查通过,可以尝试生成。\n"
validated_prompt = prompt
return (validated_prompt, report_str)
NODE_CLASS_MAPPINGS = {
"PromptValidatorNode": PromptValidatorNode
}
NODE_DISPLAY_NAME_MAPPINGS = {
"PromptValidatorNode": "SD 提示词语法校验器"
}
=== 提示词校验报告 ===
⚠️ 警告:
- 提示词中可能包含冲突描述:['masterpiece', 'best quality', 'highres'] 与 ['worst quality', 'lowres', 'bad quality'] 同时存在,可能导致模型困惑。
✅ 提示词语法检查通过,可以尝试生成。
CONFLICT_PAIRS = [
(["underwater", "ocean floor"], ["on fire", "burning", "flames"]),
]
BEST_PRACTICES = {
"anime": ["建议添加 'anime style', 'official art' 等标签来强化风格。", "避免与 'photorealistic' 同时使用。"],
"portrait": ["建议添加焦距描述,如 'sharp focus', 'portrait photography'。", "可考虑添加灯光描述,如 'studio lighting', 'rim light'。"],
}