Upload deepseek_python_20251027_9d7d49.py
Browse files
deepseek_python_20251027_9d7d49.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import random
|
| 2 |
+
import yaml
|
| 3 |
+
import os
|
| 4 |
+
from typing import Dict, List, Any
|
| 5 |
+
|
| 6 |
+
class MusicPromptGenerator:
|
| 7 |
+
"""
|
| 8 |
+
音樂 AI Prompt 生成器 - ComfyUI 節點版本
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
def __init__(self):
|
| 12 |
+
self.keyword_map = {
|
| 13 |
+
"love": {"mood": "romantic", "genre": "pop", "theme": "love"},
|
| 14 |
+
"rain": {"mood": "melancholic", "genre": "lofi", "theme": "rain"},
|
| 15 |
+
"battle": {"mood": "energetic", "genre": "orchestral", "theme": "journey"},
|
| 16 |
+
"dream": {"mood": "dreamy", "genre": "ambient", "theme": "fantasy"},
|
| 17 |
+
"night": {"mood": "serene", "genre": "jazz", "theme": "night"},
|
| 18 |
+
"space": {"mood": "mysterious", "genre": "electronic", "theme": "scifi"},
|
| 19 |
+
"road": {"mood": "nostalgic", "genre": "rock", "theme": "journey"},
|
| 20 |
+
"sunrise": {"mood": "happy", "genre": "ambient", "theme": "nature"},
|
| 21 |
+
"sad": {"mood": "melancholic", "genre": "piano", "theme": "memory"}
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
self.default_data = {
|
| 25 |
+
"moods": [
|
| 26 |
+
{"en": "happy", "zh": "快樂"}, {"en": "dark", "zh": "陰鬱"},
|
| 27 |
+
{"en": "nostalgic", "zh": "懷舊"}, {"en": "melancholic", "zh": "憂傷"},
|
| 28 |
+
{"en": "euphoric", "zh": "狂喜"}, {"en": "mysterious", "zh": "神秘"},
|
| 29 |
+
{"en": "serene", "zh": "寧靜"}, {"en": "tense", "zh": "緊張"},
|
| 30 |
+
{"en": "romantic", "zh": "浪漫"}, {"en": "energetic", "zh": "活力"}
|
| 31 |
+
],
|
| 32 |
+
"genres": [
|
| 33 |
+
{"en": "pop", "zh": "流行"}, {"en": "jazz", "zh": "爵士"},
|
| 34 |
+
{"en": "rock", "zh": "搖滾"}, {"en": "electronic", "zh": "電子"},
|
| 35 |
+
{"en": "classical", "zh": "古典"}, {"en": "folk", "zh": "民謠"},
|
| 36 |
+
{"en": "lofi", "zh": "低保真"}, {"en": "orchestral", "zh": "管弦樂"},
|
| 37 |
+
{"en": "ambient", "zh": "環境音樂"}, {"en": "synthwave", "zh": "合成器浪潮"}
|
| 38 |
+
],
|
| 39 |
+
"themes": [
|
| 40 |
+
{"en": "love", "zh": "愛情"}, {"en": "rain", "zh": "雨天"},
|
| 41 |
+
{"en": "city", "zh": "都市夜景"}, {"en": "ocean", "zh": "海洋"},
|
| 42 |
+
{"en": "fantasy", "zh": "奇幻"}, {"en": "scifi", "zh": "科幻"},
|
| 43 |
+
{"en": "journey", "zh": "旅程"}, {"en": "memory", "zh": "回憶"},
|
| 44 |
+
{"en": "nature", "zh": "自然"}, {"en": "night", "zh": "夜晚"}
|
| 45 |
+
],
|
| 46 |
+
"instruments": [
|
| 47 |
+
{"en": "piano", "zh": "鋼琴"}, {"en": "guitar", "zh": "吉他"},
|
| 48 |
+
{"en": "synth", "zh": "合成器"}, {"en": "strings", "zh": "弦樂"},
|
| 49 |
+
{"en": "drums", "zh": "鼓組"}, {"en": "bass", "zh": "貝斯"},
|
| 50 |
+
{"en": "violin", "zh": "小提琴"}, {"en": "saxophone", "zh": "薩克斯風"},
|
| 51 |
+
{"en": "flute", "zh": "長笛"}, {"en": "harp", "zh": "豎琴"}
|
| 52 |
+
],
|
| 53 |
+
"vocal_styles": [
|
| 54 |
+
{"en": "female vocals", "zh": "女聲"}, {"en": "male vocals", "zh": "男聲"},
|
| 55 |
+
{"en": "choir", "zh": "合唱"}, {"en": "layered vocals", "zh": "層疊人聲"},
|
| 56 |
+
{"en": "whisper", "zh": "氣音呢喃"}, {"en": "falsetto", "zh": "假音"},
|
| 57 |
+
{"en": "rap", "zh": "說唱"}, {"en": "spoken word", "zh": "念白"}
|
| 58 |
+
],
|
| 59 |
+
"descriptions": [
|
| 60 |
+
{"en": "cinematic", "zh": "電影感"}, {"en": "lofi", "zh": "輕鬆低保真"},
|
| 61 |
+
{"en": "acoustic", "zh": "純淨原聲"}, {"en": "orchestral", "zh": "管弦編制"},
|
| 62 |
+
{"en": "minimal", "zh": "極簡主義"}, {"en": "experimental", "zh": "實驗前衛"},
|
| 63 |
+
{"en": "vintage", "zh": "復古風"}, {"en": "futuristic", "zh": "未來感"}
|
| 64 |
+
],
|
| 65 |
+
"tempos": [
|
| 66 |
+
{"en": "slow", "zh": "慢板"}, {"en": "medium", "zh": "中板"},
|
| 67 |
+
{"en": "fast", "zh": "快板"}, {"en": "adagio", "zh": "柔板"},
|
| 68 |
+
{"en": "allegro", "zh": "快板"}, {"en": "andante", "zh": "行板"}
|
| 69 |
+
]
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
@classmethod
|
| 73 |
+
def INPUT_TYPES(cls):
|
| 74 |
+
return {
|
| 75 |
+
"required": {
|
| 76 |
+
"mode": (["random", "keyword"], {"default": "random"}),
|
| 77 |
+
"keyword": ("STRING", {"default": "love", "multiline": False}),
|
| 78 |
+
"num_prompts": ("INT", {"default": 1, "min": 1, "max": 10}),
|
| 79 |
+
"language": (["en", "zh", "both"], {"default": "en"}),
|
| 80 |
+
"template_type": (["default", "cinematic", "minimal", "custom"], {"default": "default"}),
|
| 81 |
+
"custom_template": ("STRING", {
|
| 82 |
+
"default": "A {mood} {genre} track about {theme}, featuring {instrument} and {vocal_style}, {description} style, {tempo} tempo.",
|
| 83 |
+
"multiline": True
|
| 84 |
+
}),
|
| 85 |
+
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
| 86 |
+
},
|
| 87 |
+
"optional": {
|
| 88 |
+
"yaml_file": ("STRING", {"default": ""}),
|
| 89 |
+
}
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
RETURN_TYPES = ("STRING",)
|
| 93 |
+
RETURN_NAMES = ("music_prompt",)
|
| 94 |
+
FUNCTION = "generate_prompt"
|
| 95 |
+
CATEGORY = "AI Music"
|
| 96 |
+
DESCRIPTION = "生成音樂 AI 提示詞"
|
| 97 |
+
|
| 98 |
+
def load_yaml_data(self, file_path):
|
| 99 |
+
"""載入 YAML 詞庫檔案"""
|
| 100 |
+
if not file_path or not os.path.exists(file_path):
|
| 101 |
+
return self.default_data
|
| 102 |
+
|
| 103 |
+
try:
|
| 104 |
+
with open(file_path, 'r', encoding='utf-8') as f:
|
| 105 |
+
return yaml.safe_load(f)
|
| 106 |
+
except Exception as e:
|
| 107 |
+
print(f"載入 YAML 檔案失敗: {e}")
|
| 108 |
+
return self.default_data
|
| 109 |
+
|
| 110 |
+
def fill_template(self, mood, genre, theme, instrument, vocal, desc, tempo, template, language):
|
| 111 |
+
"""填充模板"""
|
| 112 |
+
en_template = template
|
| 113 |
+
zh_template = "一首{mood}{genre}的音樂,主題是{theme},包含{instrument}與{vocal_style},風格{description},節奏{tempo}。"
|
| 114 |
+
|
| 115 |
+
# 確保所有參數都是字典格式
|
| 116 |
+
mood_dict = mood if isinstance(mood, dict) else {"en": mood, "zh": mood}
|
| 117 |
+
genre_dict = genre if isinstance(genre, dict) else {"en": genre, "zh": genre}
|
| 118 |
+
theme_dict = theme if isinstance(theme, dict) else {"en": theme, "zh": theme}
|
| 119 |
+
instrument_dict = instrument if isinstance(instrument, dict) else {"en": instrument, "zh": instrument}
|
| 120 |
+
vocal_dict = vocal if isinstance(vocal, dict) else {"en": vocal, "zh": vocal}
|
| 121 |
+
desc_dict = desc if isinstance(desc, dict) else {"en": desc, "zh": desc}
|
| 122 |
+
tempo_dict = tempo if isinstance(tempo, dict) else {"en": tempo, "zh": tempo}
|
| 123 |
+
|
| 124 |
+
en = en_template.format(
|
| 125 |
+
mood=mood_dict["en"], genre=genre_dict["en"], theme=theme_dict["en"],
|
| 126 |
+
instrument=instrument_dict["en"], vocal_style=vocal_dict["en"],
|
| 127 |
+
description=desc_dict["en"], tempo=tempo_dict["en"]
|
| 128 |
+
)
|
| 129 |
+
zh = zh_template.format(
|
| 130 |
+
mood=mood_dict["zh"], genre=genre_dict["zh"], theme=theme_dict["zh"],
|
| 131 |
+
instrument=instrument_dict["zh"], vocal_style=vocal_dict["zh"],
|
| 132 |
+
description=desc_dict["zh"], tempo=tempo_dict["zh"]
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
if language == "en":
|
| 136 |
+
return en
|
| 137 |
+
elif language == "zh":
|
| 138 |
+
return zh
|
| 139 |
+
else:
|
| 140 |
+
return f"{en}\n{zh}"
|
| 141 |
+
|
| 142 |
+
def get_template(self, template_type, custom_template):
|
| 143 |
+
"""取得模板"""
|
| 144 |
+
templates = {
|
| 145 |
+
"default": "A {mood} {genre} track about {theme}, featuring {instrument} and {vocal_style}, {description} style, {tempo} tempo.",
|
| 146 |
+
"cinematic": "Cinematic {genre} music with {mood} atmosphere, theme: {theme}, featuring {instrument} and {vocal_style}, {tempo} tempo.",
|
| 147 |
+
"minimal": "{mood} {genre} | {theme} | {instrument} | {vocal_style} | {description} | {tempo}",
|
| 148 |
+
}
|
| 149 |
+
return custom_template if template_type == "custom" else templates.get(template_type, templates["default"])
|
| 150 |
+
|
| 151 |
+
def generate_prompt(self, mode, keyword, num_prompts, language, template_type, custom_template, seed, yaml_file=""):
|
| 152 |
+
# 設定隨機種子
|
| 153 |
+
if seed > 0:
|
| 154 |
+
random.seed(seed)
|
| 155 |
+
|
| 156 |
+
# 載入資料
|
| 157 |
+
data = self.load_yaml_data(yaml_file) if yaml_file else self.default_data
|
| 158 |
+
|
| 159 |
+
# 取得模板
|
| 160 |
+
template = self.get_template(template_type, custom_template)
|
| 161 |
+
|
| 162 |
+
results = []
|
| 163 |
+
|
| 164 |
+
for _ in range(num_prompts):
|
| 165 |
+
if mode == "keyword":
|
| 166 |
+
# 關鍵字模式
|
| 167 |
+
match = self.keyword_map.get(keyword.lower(), {})
|
| 168 |
+
|
| 169 |
+
def find_item(category, default_value):
|
| 170 |
+
target = match.get(category, default_value)
|
| 171 |
+
for item in data[category + "s"]:
|
| 172 |
+
if isinstance(item, dict) and item.get("en") == target:
|
| 173 |
+
return item
|
| 174 |
+
return random.choice(data[category + "s"])
|
| 175 |
+
|
| 176 |
+
mood = find_item("mood", "melancholic")
|
| 177 |
+
genre = find_item("genre", "pop")
|
| 178 |
+
theme = find_item("theme", "memory")
|
| 179 |
+
instrument = random.choice(data["instruments"])
|
| 180 |
+
vocal = random.choice(data["vocal_styles"])
|
| 181 |
+
desc = random.choice(data["descriptions"])
|
| 182 |
+
tempo = random.choice(data["tempos"])
|
| 183 |
+
|
| 184 |
+
else:
|
| 185 |
+
# 隨機模式
|
| 186 |
+
mood = random.choice(data["moods"])
|
| 187 |
+
genre = random.choice(data["genres"])
|
| 188 |
+
theme = random.choice(data["themes"])
|
| 189 |
+
instrument = random.choice(data["instruments"])
|
| 190 |
+
vocal = random.choice(data["vocal_styles"])
|
| 191 |
+
desc = random.choice(data["descriptions"])
|
| 192 |
+
tempo = random.choice(data["tempos"])
|
| 193 |
+
|
| 194 |
+
prompt = self.fill_template(mood, genre, theme, instrument, vocal, desc, tempo, template, language)
|
| 195 |
+
results.append(prompt)
|
| 196 |
+
|
| 197 |
+
# 合併多個提示詞
|
| 198 |
+
final_prompt = "\n\n".join(results) if num_prompts > 1 else results[0]
|
| 199 |
+
|
| 200 |
+
return (final_prompt,)
|
| 201 |
+
|
| 202 |
+
# 節點註冊
|
| 203 |
+
NODE_CLASS_MAPPINGS = {
|
| 204 |
+
"MusicPromptGenerator": MusicPromptGenerator
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
NODE_DISPLAY_NAME_MAPPINGS = {
|
| 208 |
+
"MusicPromptGenerator": "🎵 Music AI Prompt Generator"
|
| 209 |
+
}
|