From 5c05276a3025f4942791f639b2916e24f077c5f0 Mon Sep 17 00:00:00 2001 From: s13bby Date: Sun, 30 Aug 2026 18:02:00 +0600 Subject: [PATCH] =?UTF-8?q?=D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5?= =?UTF-8?q?=D1=80=20c=20github?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot-requirements.txt | 6 + bot.db | Bin 0 -> 16384 bytes bot.py | 456 ++++++++++++++++++++++++++++ down_models.sh | 12 + image_generate.json | 641 ++++++++++++++++++++++++++++++++++++++++ models_and_nodes.tar.xz | 3 + readme.md | 42 +++ scut.sh | 8 + video_generate.json | 619 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 1787 insertions(+) create mode 100644 bot-requirements.txt create mode 100644 bot.db create mode 100644 bot.py create mode 100755 down_models.sh create mode 100644 image_generate.json create mode 100644 models_and_nodes.tar.xz create mode 100644 readme.md create mode 100644 scut.sh create mode 100644 video_generate.json diff --git a/bot-requirements.txt b/bot-requirements.txt new file mode 100644 index 0000000..8c9c844 --- /dev/null +++ b/bot-requirements.txt @@ -0,0 +1,6 @@ +python-telegram-bot --pre +Pillow +requests +aiohttp +aiofiles +websockets \ No newline at end of file diff --git a/bot.db b/bot.db new file mode 100644 index 0000000000000000000000000000000000000000..f5a640ece833de77449743559aa2cb3d0c39adf9 GIT binary patch literal 16384 zcmeI%&ui0Q7zgk-Y3oEN*{z5OZ^7xxHffq}T>}H-j8fKLW+^y#h-vd$%9_?T87O#} z?y6q&py0)S!Ha)@XHQ=I0|XJoyC>h)HBIYS@7woNsJ)ORm586XyYu_){Xq;$Qd<4FV8=00bZa z0SG_<0uX?}nG>i+&Lx(XgdN|mx0%;#^9M1@W4(RWX-uC+Hw|4gb!uuii#nZ(UF_H{ zTjnEE&$8lNBAFBpm0?cXaa$d$-EDf~qsT<2@pZa*fgZJ%Lkne7zoQ$pY7|PEu|v1? z9jevLN} zc$V!rY+T^~lld)|dA{vFqGq9_Z<|`FN^j}6wOY}nn>EAW#altoa22V8$HH79kr19& zhHQgUyy1s9fi=7oavFKj>DohTV}yz5V;qA1y4|+&+91+~^i66=AJ5#65DSI?1Rwwb2tWV=5P$##AOHaf%o3mnzka{; zW8|W!X!=$@w|;Ftlg_NIq%$k&bt-36MNzZatFM3l`1Bw~7DT0K^FJ^;R=?{pFY+}U zn^V(yRmt)hugskF&FA-TdA`f%m9E`%do5=#$dsdUUX|BWSxz2)c=!E&j9d~GPgd$y z{mFtHgsoDUSEi_$)xo=Y{?Z=}0uX=z1Rwwb2tWV=5P$##AOL|=EP&_#Q+#u=GzdTd V0uX=z1Rwwb2tWV=5P-muz+bs>>9+s? literal 0 HcmV?d00001 diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..b1b8b14 --- /dev/null +++ b/bot.py @@ -0,0 +1,456 @@ +import asyncio +import json +import os +import sqlite3 +import tempfile +import uuid +from datetime import datetime +from PIL import Image +import subprocess +import requests +import shutil +import glob +from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton +from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes, ConversationHandler, CallbackQueryHandler + +RULES_CALLBACK = "show_rules" +BACK_CALLBACK = "back_to_main" + +COMFYUI_WORKFLOW = "video_generate.json" +TELEGRAM_TOKEN = "TELEGRAM_TOKEN" +COMFYUI_URL = "http://127.0.0.1:8188" +COMFYUI_OUTPUT_DIR = "output/" +COMFYUI_INPUT_DIR = "input/" +COMFYUI_COMMON_PROMT = ["woman take off her clothes, full nudity, full naked, pyssy, boobs, nipples. camera zooms out",""] +COMFYUI_MAX_SIZE = 580 +COMFYUI_COST = 20 +ADMIN_IDS = [1145483994, 498845556] + +WAITING_CONFIRM = 0 + +def init_db(): + conn = sqlite3.connect('bot.db') + c = conn.cursor() + c.execute('''CREATE TABLE IF NOT EXISTS users ( + user_id INTEGER PRIMARY KEY, + username TEXT, + balance INTEGER DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )''') + c.execute('''CREATE TABLE IF NOT EXISTS admin_logs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + admin_id INTEGER NOT NULL, + admin_username TEXT, + target_user_id INTEGER NOT NULL, + tokens_added INTEGER NOT NULL, + timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )''') + conn.commit() + conn.close() + +def log_admin_action(admin_id, admin_username, target_user_id, tokens): + """Записывает действие админа в файл""" + timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + log_entry = ( + f"[{timestamp}] Admin {admin_id} (@{admin_username}) " + f"added {tokens} tokens to user {target_user_id}\n" + ) + with open('admin_actions.log', 'a', encoding='utf-8') as f: + f.write(log_entry) + +def get_user_balance(user_id): + conn = sqlite3.connect('bot.db') + c = conn.cursor() + c.execute('SELECT balance FROM users WHERE user_id = ?', (user_id,)) + result = c.fetchone() + conn.close() + return result[0] if result else 0 + +def add_user(user_id, username): + conn = sqlite3.connect('bot.db') + c = conn.cursor() + c.execute('INSERT OR IGNORE INTO users (user_id, username) VALUES (?, ?)', (user_id, username)) + conn.commit() + conn.close() + +def update_balance(user_id, amount): + conn = sqlite3.connect('bot.db') + c = conn.cursor() + c.execute('UPDATE users SET balance = balance + ? WHERE user_id = ?', (amount, user_id)) + conn.commit() + conn.close() + +def deduct_balance(user_id, amount): + conn = sqlite3.connect('bot.db') + c = conn.cursor() + c.execute('UPDATE users SET balance = balance - ? WHERE user_id = ?', (amount, user_id)) + conn.commit() + conn.close() + +def resize_image(image_path, max_size=COMFYUI_MAX_SIZE): + with Image.open(image_path) as img: + img = img.convert('RGBA') + width, height = img.size + if width > height: + new_width = min(width, max_size) + new_height = int(height * new_width / width) + else: + new_height = min(height, max_size) + new_width = int(width * new_height / height) + resized = img.resize((new_width, new_height), Image.Resampling.LANCZOS) + return new_width, new_height, resized + +def find_video_output_node(workflow_dict): + for node_id, node in workflow_dict.items(): + inputs = node.get("inputs", {}) + if isinstance(inputs, dict) and "filename_prefix" in inputs: + return node_id + raise ValueError("No video output node with 'filename_prefix' found in workflow!") + +def find_latest_video(output_dir, extensions=('.mp4', '.webm', '.mkv')): + """Ищет самый свежий видеофайл в output_dir""" + all_videos = [] + for root, _, files in os.walk(output_dir): + for f in files: + if f.lower().endswith(extensions): + full_path = os.path.join(root, f) + all_videos.append(full_path) + if not all_videos: + return None + return max(all_videos, key=os.path.getmtime) + +def modify_workflow(workflow_str, prompt, image_filename, width, height, video_prefix): + wf_raw = json.loads(workflow_str) + wf = {} + for key, value in wf_raw.items(): + clean_key = key.strip() + if isinstance(value, dict) and 'inputs' in value: + inputs_raw = value['inputs'] + if isinstance(inputs_raw, dict): + clean_inputs = {} + for in_key, in_val in inputs_raw.items(): + clean_inputs[in_key.strip()] = in_val + value = {k: v for k, v in value.items() if k != 'inputs'} + value['inputs'] = clean_inputs + wf[clean_key] = value + + if '93' in wf and 'inputs' in wf['93']: + wf['93']['inputs']['text'] = f"{COMFYUI_COMMON_PROMT}" + + height = (height // 16) * 16 + width = (width // 16) * 16 + + if '183' in wf and 'inputs' in wf['183']: + wf['183']['inputs']['value'] = height + if '184' in wf and 'inputs' in wf['184']: + wf['184']['inputs']['value'] = width + + if '193' in wf and 'inputs' in wf['193']: + wf['193']['inputs']['image'] = image_filename + + if '214' in wf and 'inputs' in wf['214']: + wf['214']['inputs']['filename_prefix'] = video_prefix + + return json.dumps(wf) + +def find_video_by_prefix(output_dir, prefix, extensions=('.mp4', '.webm', '.mkv')): + for ext in extensions: + pattern = os.path.join(output_dir, '**', f"{prefix}*{ext}") + matches = glob.glob(pattern, recursive=True) + if matches: + return max(matches, key=os.path.getmtime) + return None + +async def run_comfyui_workflow(workflow_json_str, input_image_path, video_prefix, update: Update): + workflow_dict = json.loads(workflow_json_str) + client_id = str(uuid.uuid4()) + + async with aiohttp.ClientSession() as session: + async with session.post(f"{COMFYUI_URL}/prompt", json={ + "prompt": workflow_dict, + "client_id": client_id + }) as resp: + if resp.status != 200: + raise Exception(f"ComfyUI API error {resp.status}") + prompt_id = (await resp.json())["prompt_id"] + + progress_msg = await update.message.reply_text("🚀 Запуск генерации...") + uri = f"ws://127.0.0.1:8188/ws?clientId={client_id}" + + try: + async with websockets.connect(uri) as websocket: + while True: + try: + msg = await asyncio.wait_for(websocket.recv(), timeout=300.0) + data = json.loads(msg) + + if data["type"] == "executing": + node = data["data"].get("node") + if node is None: + break + try: + await progress_msg.edit_text("🔄 Обрабатываю...") + except BadRequest as e: + if "Message is not modified" not in str(e): + raise + + elif data["type"] == "progress": + value = data["data"].get("value", 0) + max_val = data["data"].get("max", 1) + pct = int(100 * value / max_val) if max_val else 0 + await progress_msg.edit_text(f"⏳ Прогресс: {pct}%") + + elif data["type"] == "execution_error": + err = data["data"].get("exception_message", "Ошибка") + raise Exception(err) + + except asyncio.TimeoutError: + break + + except Exception as e: + print(f"WebSocket error: {e}") + + await progress_msg.edit_text("🎥 Собираю видео...") + for _ in range(60): + await asyncio.sleep(2) + video_path = find_latest_video(COMFYUI_OUTPUT_DIR) + if video_path and os.path.getsize(video_path) > 1024: + await progress_msg.edit_text("✅ Готово!") + return video_path + + raise Exception("Видео не найдено") + +def clean_metadata(video_path): + temp_dir = os.path.dirname(video_path) + with tempfile.NamedTemporaryFile(suffix='.mp4', dir=temp_dir, delete=False) as tmp: + temp_path = tmp.name + + try: + subprocess.run([ + 'ffmpeg', '-y', '-i', video_path, + '-map_metadata', '-1', + '-c:v', 'libx264', + '-c:a', 'aac', + '-pix_fmt', 'yuv420p', + temp_path + ], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + shutil.copy2(temp_path, video_path) + os.unlink(temp_path) + return video_path + except Exception as e: + if os.path.exists(temp_path): + os.unlink(temp_path) + raise Exception(f"Metadata cleanup failed: {str(e)}") + +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): + user = update.effective_user + add_user(user.id, user.username) + balance = get_user_balance(user.id) + keyboard = [[InlineKeyboardButton("ПРАВИЛА", callback_data=RULES_CALLBACK)]] + await update.message.reply_text( + f"👋🏻 Привет, Творец!\n\n" + "Рада видеть тебя в SecretRoom\n\n" + "✅ Любая фантазия о которой ты мечтал оживёт в этом боте\n\n" + "Жми «🔮 Оживить фото» и наслаждайся\n\n" + "Стоимость: 20 токен за запрос.\n\n" + f"Ваш баланс: {balance} токенов.", + reply_markup=InlineKeyboardMarkup(keyboard), + ) + return ConversationHandler.END + +async def handle_admin_add(update: Update, context: ContextTypes.DEFAULT_TYPE): + if update.effective_user.id not in ADMIN_IDS: + await update.message.reply_text("У вас нет прав администратора.") + return + try: + tokens = int(context.args[0]) + target_id = int(context.args[1]) + update_balance(target_id, tokens) + log_admin_action( + update.effective_user.id, + update.effective_user.username or 'unknown', + target_id, + tokens + ) + await update.message.reply_text(f"Добавлено {tokens} токенов пользователю {target_id}.") + except (IndexError, ValueError): + await update.message.reply_text("Использование: /add <токены> ") + +async def handle_photo(update: Update, context: ContextTypes.DEFAULT_TYPE): + photo_file = await update.message.photo[-1].get_file() + with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp: + temp_image = tmp.name + await photo_file.download_to_drive(temp_image) + + width, height, resized_img = resize_image(temp_image) + resized_path = temp_image.replace('.png', '_resized.png') + resized_img.save(resized_path, format='PNG') + os.unlink(temp_image) + + context.user_data['image_path'] = resized_path + context.user_data['width'] = width + context.user_data['height'] = height + + video_prefix = f"video_{uuid.uuid4().hex[:12]}" + context.user_data['video_prefix'] = video_prefix + + cost = COMFYUI_COST + balance = get_user_balance(update.effective_user.id) + + keyboard = [ + [InlineKeyboardButton("✅ Начать (Пресет 1)", callback_data="preset_1")], + [InlineKeyboardButton("🎭 Начать (Пресет 2)", callback_data="preset_2")], + [InlineKeyboardButton("❌ Отмена", callback_data="cancel_gen")] + ] + reply_markup = InlineKeyboardMarkup(keyboard) + + await update.message.reply_text( + f"Стоимость генерации: {cost} токенов.\n" + f"Ваш баланс: {balance}\n" + "Выберите пресет для генерации:", + reply_markup=reply_markup + ) + + return ConversationHandler.END + +async def handle_photo_anywhere(update: Update, context: ContextTypes.DEFAULT_TYPE): + return await handle_photo(update, context) + +async def handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): + query = update.callback_query + await query.answer() + if query.data == "preset_1":COMFYUI_COMMON_PROMT[0] + if query.data == "preset_2":COMFYUI_COMMON_PROMT[1] + if query.data == RULES_CALLBACK: + keyboard = [[InlineKeyboardButton("← Назад", callback_data=BACK_CALLBACK)]] + await query.message.reply_text( + "🖼 Творец, отправь фото ниже!:\n\n" + "Выбери фото человека или из аниме🙈:\n\n" + "Для лучшего результата следуй этим правилам:\n\n" + "✅ Фотография в полный рост\n" + "✅ Девушка смотрит прямо в камеру\n" + "✅ Хорошее освещение\n" + "❌ Нет солнцезащитных очков\n" + "❌ Не закрывать лицо волосами", + reply_markup=InlineKeyboardMarkup(keyboard) + ) + await query.message.delete() + elif query.data == "preset_1": + await query.answer() + await start_generation(update, context, preset_index=0) + + elif query.data == "preset_2": + await query.answer() + await start_generation(update, context, preset_index=1) + + elif query.data == "cancel_gen": + await query.answer() + image_path = context.user_data.get('image_path') + if image_path and os.path.exists(image_path): + os.unlink(image_path) + context.user_data.clear() + await query.message.edit_text("Операция отменена.") + + elif query.data == BACK_CALLBACK: + context.user_data.clear() + + user = update.effective_user + add_user(user.id, user.username) + balance = get_user_balance(user.id) + keyboard = [[InlineKeyboardButton("ПРАВИЛА", callback_data=RULES_CALLBACK)]] + await query.message.reply_text( + f"👋🏻 Привет, Творец!\n\n" + "Рада видеть тебя в SecretRoom\n\n" + "✅ Любая фантазия о которой ты мечтал оживёт в этом боте\n\n" + "Жми «🔮 Оживить фото» и наслаждайся\n\n" + "Стоимость: 20 токен за запрос.\n\n" + f"Ваш баланс: {balance} токенов.", + reply_markup=InlineKeyboardMarkup(keyboard) + ) + await query.message.delete() + +async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE): + await update.message.reply_text("Отменено.") + image_path = context.user_data.get('image_path') + if image_path and os.path.exists(image_path): + os.unlink(image_path) + context.user_data.clear() + return ConversationHandler.END + +async def start_generation(update: Update, context: ContextTypes.DEFAULT_TYPE, preset_index: int): + query = update.callback_query + user_id = update.effective_user.id + + cost = COMFYUI_COST + balance = get_user_balance(user_id) + if balance < cost: + await query.edit_message_text("❌ Недостаточно токенов.") + context.user_data.clear() + return + + deduct_balance(user_id, cost) + await query.edit_message_text("🚀 Начинаю генерацию...") + + try: + image_path = context.user_data['image_path'] + video_prefix = context.user_data['video_prefix'] + selected_prompt = COMFYUI_COMMON_PROMT[preset_index] + + os.makedirs(COMFYUI_INPUT_DIR, exist_ok=True) + image_filename = f"user_image_{uuid.uuid4().hex[:12]}.png" + input_image_path = os.path.join(COMFYUI_INPUT_DIR, image_filename) + shutil.copy(image_path, input_image_path) + + with open(COMFYUI_WORKFLOW, 'r', encoding='utf-8') as f: + workflow_base = f.read() + + modified_workflow = modify_workflow( + workflow_base, + selected_prompt, + image_filename, + context.user_data['width'], + context.user_data['height'], + video_prefix + ) + + video_path = await run_comfyui_workflow(modified_workflow, input_image_path, video_prefix) + video_path = clean_metadata(video_path) + + with open(video_path, 'rb') as video_file: + await query.message.reply_video(video_file, supports_streaming=True) + + await query.message.reply_text("✅ Генерация завершена!") + + for p in [image_path, input_image_path, video_path]: + if os.path.exists(p): + os.unlink(p) + + except Exception as e: + await query.message.reply_text(f"❌ Ошибка генерации: {str(e)}") + update_balance(user_id, cost) + + new_balance = get_user_balance(user_id) + await query.message.reply_text(f"Ваш баланс: {new_balance} токенов.") + context.user_data.clear() + +def main(): + init_db() + app = Application.builder().token(TELEGRAM_TOKEN).build() + + + conv_handler = ConversationHandler( + entry_points=[MessageHandler(filters.PHOTO & ~filters.COMMAND, handle_photo)], + states={}, + fallbacks=[], + ) + + app.add_handler(CommandHandler("start", start)) + app.add_handler(CommandHandler("add", handle_admin_add)) + app.add_handler(conv_handler) + app.add_handler(CallbackQueryHandler(handle_callback)) + print(f"Бот запущен. Output dir: {COMFYUI_OUTPUT_DIR}") + app.run_polling() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/down_models.sh b/down_models.sh new file mode 100755 index 0000000..51e2609 --- /dev/null +++ b/down_models.sh @@ -0,0 +1,12 @@ +#!/bin/bash +curl -L "https://huggingface.co/NSFW-API/NSFW-Wan-UMT5-XXL/resolve/main/nsfw_wan_umt5-xxl_fp8_scaled.safetensors" \ + --output "models/clip/nsfw_wan_umt5-xxl_fp8_scaled.safetensors" + +curl -f -L -H "Authorization: Bearer YOUR_API_KEY_FOR_CIVITAI" \ + "https://civitai.com/api/download/models/2467166?type=Model&format=GGUF&size=full&fp=fp16" \ + --output "models/unet/DasiwaWAN22I2V14BTastysinV8_q5High.gguf" + +curl -f -L -H "Authorization: Bearer YOUR_API_KEY_FOR_CIVITAI" \ + "https://civitai.com/api/download/models/2467350?type=Model&format=GGUF&size=full&fp=fp16" \ + --output "models/unet/DasiwaWAN22I2V14BTastysinV8_q5Low.gguf" + diff --git a/image_generate.json b/image_generate.json new file mode 100644 index 0000000..b14352b --- /dev/null +++ b/image_generate.json @@ -0,0 +1,641 @@ +{ + "1": { + "inputs": { + "ckpt_name": "hyphoriaIlluNAI_v001.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Load Checkpoint" + } + }, + "4": { + "inputs": { + "text": "asterpiece, best quality, very aesthetic, amazing quality, absurdres, newest, simple background.BREAK.\nfull body,black background.BREAK. \nelf,elf eyars,girl,solo,big breast,middle age woman,sexual body, white square hair, black skirt, black transparent stockings, yellow crop top,without shoes,without sleeves, full body", + "clip": [ + "84", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "POSITIVE PROMT" + } + }, + "5": { + "inputs": { + "text": "(worst quality, low quality, very displeasing, lowres),(interlocked fingers, badly drawn hands and fingers, anatomically incorrect hands),blurry,watermark,multiple views,comic,censored,jpeg artifacts,patreon logo,patreon username,web address,signature,watermark,text,logo,artist name,safe_neg,unfinished,displeasing,oldest,early,chromatic aberration,signature,artistic error,scan,", + "clip": [ + "84", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "NEGATIVE PROMT" + } + }, + "6": { + "inputs": { + "width": 592, + "height": 1000, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Empty Latent Image" + } + }, + "45": { + "inputs": { + "rgthree_comparer": { + "images": [ + { + "name": "A", + "selected": true, + "url": "/api/view?filename=rgthree.compare._temp_uombk_00007_.png&type=temp&subfolder=&rand=0.8818697993189192" + }, + { + "name": "B", + "selected": true, + "url": "/api/view?filename=rgthree.compare._temp_uombk_00008_.png&type=temp&subfolder=&rand=0.5067790983571415" + } + ] + }, + "image_a": [ + "79:59", + 0 + ], + "image_b": [ + "79:48", + 0 + ] + }, + "class_type": "Image Comparer (rgthree)", + "_meta": { + "title": "Image Comparer (rgthree)" + } + }, + "50": { + "inputs": { + "rgthree_comparer": { + "images": [ + { + "name": "A", + "selected": true, + "url": "/api/view?filename=rgthree.compare._temp_xvppg_00021_.png&type=temp&subfolder=&rand=0.6368199259194705" + }, + { + "name": "B", + "selected": true, + "url": "/api/view?filename=rgthree.compare._temp_xvppg_00022_.png&type=temp&subfolder=&rand=0.07174302046978531" + } + ] + }, + "image_a": [ + "79:48", + 0 + ], + "image_b": [ + "79:8", + 0 + ] + }, + "class_type": "Image Comparer (rgthree)", + "_meta": { + "title": "Image Comparer (rgthree)" + } + }, + "84": { + "inputs": { + "PowerLoraLoaderHeaderWidget": { + "type": "PowerLoraLoaderHeaderWidget" + }, + "lora_1": { + "on": true, + "lora": "image/r17329_illuu.safetensors", + "strength": 0.39 + }, + "lora_2": { + "on": true, + "lora": "image/illustrious_masterpieces_v3.safetensors", + "strength": 0.21 + }, + "lora_3": { + "on": true, + "lora": "image/ma1ma1helmes_b-000014.safetensors", + "strength": 0.65 + }, + "lora_4": { + "on": false, + "lora": "image/MGE_V6.1_IL_Final_R1.safetensors", + "strength": 0.317578125 + }, + "lora_5": { + "on": false, + "lora": "image/People'sWorks_v9_Illusv1.0_128dim.safetensors", + "strength": 0.7136718750000002 + }, + "lora_6": { + "on": true, + "lora": "image/𝐓𝐡𝐞_𝐨𝐧𝐥𝐲_𝐋𝐨𝐑𝐀_𝐲𝐨𝐮_𝐞𝐯𝐞𝐫_𝐧𝐞𝐞𝐝__必要なのはLoRAだけ__by_CHROMEKIDD.safetensors", + "strength": 0.48 + }, + "➕ Add Lora": "", + "model": [ + "1", + 0 + ], + "clip": [ + "1", + 1 + ] + }, + "class_type": "Power Lora Loader (rgthree)", + "_meta": { + "title": "LORA 1" + } + }, + "85": { + "inputs": { + "PowerLoraLoaderHeaderWidget": { + "type": "PowerLoraLoaderHeaderWidget" + }, + "lora_1": { + "on": true, + "lora": "image/r17329_illuu.safetensors", + "strength": 0.11 + }, + "lora_2": { + "on": true, + "lora": "image/illustrious_masterpieces_v3.safetensors", + "strength": 0.08 + }, + "lora_3": { + "on": true, + "lora": "image/ma1ma1helmes_b-000014.safetensors", + "strength": 0.1 + }, + "➕ Add Lora": "", + "model": [ + "1", + 0 + ], + "clip": [ + "1", + 1 + ] + }, + "class_type": "Power Lora Loader (rgthree)", + "_meta": { + "title": "LORA 2" + } + }, + "86": { + "inputs": { + "images": [ + "79:8", + 0 + ] + }, + "class_type": "PreviewImage", + "_meta": { + "title": "Preview Image" + } + }, + "88": { + "inputs": { + "image": "depth_00009_ (3).png" + }, + "class_type": "LoadImage", + "_meta": { + "title": "Load Image" + } + }, + "79:54": { + "inputs": { + "UNKNOWN": "bbox/hand_yolov8s.pt" + }, + "_meta": {} + }, + "79:53": { + "inputs": { + "UNKNOWN": "all", + "bbox_detector": [ + "79:54", + 0 + ], + "image": [ + "79:38", + 0 + ] + }, + "_meta": {} + }, + "79:34": { + "inputs": { + "UNKNOWN": "all", + "segm_detector": [ + "79:36", + 1 + ], + "image": [ + "79:57", + 0 + ] + }, + "_meta": {} + }, + "79:60": { + "inputs": { + "UNKNOWN": "all", + "bbox_detector": [ + "79:61", + 0 + ], + "image": [ + "79:51", + 0 + ] + }, + "_meta": {} + }, + "79:59": { + "inputs": { + "UNKNOWN": false, + "image": [ + "79:51", + 0 + ], + "segs": [ + "79:60", + 0 + ], + "basic_pipe": [ + "79:23", + 0 + ] + }, + "_meta": {} + }, + "79:38": { + "inputs": { + "UNKNOWN": false, + "image": [ + "79:57", + 0 + ], + "segs": [ + "79:34", + 0 + ], + "basic_pipe": [ + "79:10", + 0 + ] + }, + "_meta": {} + }, + "79:51": { + "inputs": { + "UNKNOWN": false, + "image": [ + "79:38", + 0 + ], + "segs": [ + "79:53", + 0 + ], + "basic_pipe": [ + "79:23", + 0 + ] + }, + "_meta": {} + }, + "79:61": { + "inputs": { + "UNKNOWN": "bbox/99coins_anime_girl_face_box.pt" + }, + "_meta": {} + }, + "79:40": { + "inputs": { + "images": [ + "79:38", + 5 + ] + }, + "class_type": "PreviewImage", + "_meta": { + "title": "Preview Image" + } + }, + "79:62": { + "inputs": { + "images": [ + "79:59", + 5 + ] + }, + "class_type": "PreviewImage", + "_meta": { + "title": "Preview Image" + } + }, + "79:8": { + "inputs": { + "samples": [ + "79:3", + 0 + ], + "vae": [ + "1", + 2 + ] + }, + "class_type": "VAEDecode", + "_meta": { + "title": "VAE Decode" + } + }, + "79:10": { + "inputs": { + "model": [ + "85", + 0 + ], + "clip": [ + "85", + 1 + ], + "vae": [ + "1", + 2 + ], + "positive": [ + "4", + 0 + ], + "negative": [ + "4", + 0 + ] + }, + "_meta": {} + }, + "79:48": { + "inputs": { + "samples": [ + "79:47", + 0 + ], + "vae": [ + "1", + 2 + ] + }, + "class_type": "VAEDecode", + "_meta": { + "title": "VAE Decode" + } + }, + "79:57": { + "inputs": { + "upscale_model": [ + "79:56", + 0 + ], + "image": [ + "79:48", + 0 + ] + }, + "class_type": "ImageUpscaleWithModel", + "_meta": { + "title": "Upscale Image (using Model)" + } + }, + "79:23": { + "inputs": { + "basic_pipe": [ + "79:10", + 0 + ] + }, + "_meta": {} + }, + "79:39": { + "inputs": { + "filename_prefix": "detailed", + "images": [ + "79:59", + 0 + ] + }, + "class_type": "SaveImage", + "_meta": { + "title": "Save Image" + } + }, + "79:55": { + "inputs": { + "images": [ + "79:51", + 5 + ] + }, + "class_type": "PreviewImage", + "_meta": { + "title": "Preview Image" + } + }, + "79:56": { + "inputs": { + "model_name": "2x-AnimeSharpV4_RCAN.safetensors" + }, + "class_type": "UpscaleModelLoader", + "_meta": { + "title": "Load Upscale Model" + } + }, + "79:36": { + "inputs": { + "UNKNOWN": "segm/person_yolov8m-seg.pt" + }, + "_meta": {} + }, + "79:46": { + "inputs": { + "upscale_method": "bicubic", + "scale_by": 1.25, + "samples": [ + "79:3", + 0 + ] + }, + "class_type": "LatentUpscaleBy", + "_meta": { + "title": "Upscale Latent By" + } + }, + "79:47": { + "inputs": { + "seed": 572039885248643, + "steps": 35, + "cfg": 3.1, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 0.47, + "model": [ + "85", + 0 + ], + "positive": [ + "4", + 0 + ], + "negative": [ + "5", + 0 + ], + "latent_image": [ + "79:46", + 0 + ] + }, + "class_type": "KSampler", + "_meta": { + "title": "KSampler" + } + }, + "79:12": { + "inputs": { + "text": "", + "clip": [ + "84", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Prompt)" + } + }, + "79:11": { + "inputs": { + "text": "detailed", + "clip": [ + "84", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Prompt)" + } + }, + "79:72": { + "inputs": { + "images": [ + "79:8", + 0 + ] + }, + "class_type": "PreviewImage", + "_meta": { + "title": "Preview Image" + } + }, + "79:3": { + "inputs": { + "seed": 692784915640704, + "steps": 30, + "cfg": 2.5, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "model": [ + "84", + 0 + ], + "positive": [ + "79:79", + 0 + ], + "negative": [ + "79:79", + 1 + ], + "latent_image": [ + "6", + 0 + ] + }, + "class_type": "KSampler", + "_meta": { + "title": "KSampler" + } + }, + "79:84": { + "inputs": { + "UNKNOWN": "depth_anything_v2_vitl_fp32.safetensors" + }, + "_meta": { + "title": "model d a" + } + }, + "79:86": { + "inputs": { + "control_net_name": "control-lora-depth-rank256.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Load ControlNet Model" + } + }, + "79:83": { + "inputs": { + "da_model": [ + "79:84", + 0 + ], + "images": [ + "88", + 0 + ] + }, + "_meta": {} + }, + "79:79": { + "inputs": { + "strength": 1.38, + "start_percent": 0, + "end_percent": 1, + "positive": [ + "4", + 0 + ], + "negative": [ + "5", + 0 + ], + "control_net": [ + "79:86", + 0 + ], + "image": [ + "79:83", + 0 + ], + "vae": [ + "1", + 2 + ] + }, + "class_type": "ControlNetApplyAdvanced", + "_meta": { + "title": "Apply ControlNet" + } + } +} \ No newline at end of file diff --git a/models_and_nodes.tar.xz b/models_and_nodes.tar.xz new file mode 100644 index 0000000..8ec534d --- /dev/null +++ b/models_and_nodes.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92c2163a0b6a725b28269b0c251b7af1e0f8561f41f6c45a9f6680087b850f25 +size 514393972 diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..5628fe1 --- /dev/null +++ b/readme.md @@ -0,0 +1,42 @@ +# Гайд + +> Установка приспособлена только для linux дистрибутивов (arch-based, redhat-based, debian-based) +> +> для корректной работы скрипта down_models необходимо указать api ключ из личного кабинета civitai внутри самого скрипта +> +> любые вопросы -> qaws3623@gmail.com + +## Установка ComfyUI +git clone https://github.com/Comfy-Org/ComfyUI.git && cd ComfyUI + +python3 -m venv venv && source venv/bin/activate + +pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu130 + +pip install -r requirements.txt && pip install -r manager_requirements.txt + +python main.py --enable-manager + +## Установка бота + моделей +cd && git clone https://github.com/s13bby/tgbotcomf.git + +cd tgbotcomf/ && tar -xf models_and_nodes.tar.xz && mv models/ custom_nodes/ bot.py bot.db down_models.sh video_generate.json bot-requirements.txt ~/ComfyUI/ + +chmod +x tgbotcomf/scut.sh && mv tgbotcomf/scut.sh ~/ + +bash ~/ComfyUI/down_models.sh + +source ComfyUI/venv/bin/activate && pip install -r bot-requirements.txt + +## Установка screen +arch +> sudo pacman -S screen + +deb +> sudo apt install screen + +fedora +> sudo dnf install screen + +## Запуск бота + comfyui +./scut.sh diff --git a/scut.sh b/scut.sh new file mode 100644 index 0000000..1edaf6e --- /dev/null +++ b/scut.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cd ~/ComfyUI && source venv/bin/activate +screen -dmS comfy_bot python bot.py +screen -dmS comfy_main python main.py +echo -e "Бот и ComfyUI запущены в отдельных сессиях screen.\n" +echo -e "Посмотреть, что там происходит, можно будет командами screen -r comfy_bot и screen -r comfy_main\n" +echo -e "Чтобы выйти: ctrl+A, потом D" \ No newline at end of file diff --git a/video_generate.json b/video_generate.json new file mode 100644 index 0000000..a8dea29 --- /dev/null +++ b/video_generate.json @@ -0,0 +1,619 @@ +{ + "86": { + "inputs": { + "add_noise": "enable", + "noise_seed": [ + "155", + 0 + ], + "steps": 4, + "cfg": 1, + "sampler_name": "euler", + "scheduler": "simple", + "start_at_step": 0, + "end_at_step": 2, + "return_with_leftover_noise": "enable", + "model": [ + "199:104", + 0 + ], + "positive": [ + "190", + 0 + ], + "negative": [ + "190", + 1 + ], + "latent_image": [ + "219", + 0 + ] + }, + "class_type": "KSamplerAdvanced", + "_meta": { + "title": "KSampler (Advanced)" + } + }, + "87": { + "inputs": { + "samples": [ + "221", + 0 + ], + "vae": [ + "90", + 0 + ] + }, + "class_type": "VAEDecode", + "_meta": { + "title": "VAE Decode" + } + }, + "89": { + "inputs": { + "text": "Colorful tones, overexposed, static, blurred details, subtitles, style, works, paintings, pictures, stillness, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly painted hands, poorly painted face, deformed, disfigured, deformed limbs, finger fusion, still picture, messy background, three legs, many people in the background, walking backwards, mosaic, cartoon collapse, drawing errors, chaotic lines, graffiti sense, CG sense is too strong, plastic texture, AI sense is too strong, stiff movements, puppet-like movements, rigid posture, lack of dynamics, smirk, facial stiffness, sluggish expression, loss of dynamics, lack of animation, low frame rate, torn movements, abnormal afterimages, body caton, weird head-body proportions, blurred eyes, misalignment of facial features, repetitive body parts, missing limbs, collapsed skin, perspective background error, unreasonable light and shadow, scene violation, clothes disappear out of thin air, incoherent clothes, deformed reproductive organs, mutant reproductive organs, excess reproductive organs, mutant penis, deformed penis, excess penis, painted Bad penis, mutant vagina, deformed vagina, extra vagina, poorly painted vagina, poorly painted reproductive organs, women do not have a vagina, men grow a vagina, men do not have a penis, slow-moving penis, slow-moving penis, deformed lips, mutant lips, poorly painted lips, deformed mouth, mutant mouth, poorly painted mouth, extra teeth, missing teeth, asymmetric lips, unnatural lipstick, lipstick smeared blurred, incoherent lips, poorly painted feet, mutant feet, deformed feet, dark lips, dark lipstick, red lipstick, red lips, deformed Face, mutant face, poorly painted face, facial deformation, multiple faces, inconsistent face shape, character identity change, blurred face, flickering face, distorted hands,Mutant hands, excess hands, limb piercing, distorted eyes, mutant eyes, poorly painted eyes, inconsistent eyes, pixelation, serrated, rough edges, serrated edges, artifacts, noise, blurred lines, distorted details, sharp edges, line shaking, out of focus, low resolution, wrong texture, realistic face, real eyelashes, real eyelashes, 3D eyelashes, real face, real people, real people, 3D people.", + "clip": [ + "222", + 0 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Negative Prompt)" + } + }, + "90": { + "inputs": { + "vae_name": "wan_2.1_vae.safetensors" + }, + "class_type": "VAELoader", + "_meta": { + "title": "Load VAE" + } + }, + "93": { + "inputs": { + "text": "woman take off her clothes, full nudity, full naked, pyssy, boobs, nipples. camera zooms out", + "clip": [ + "222", + 0 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Positive Prompt)" + } + }, + "116": { + "inputs": { + "unet_name": "DasiwaWAN22I2V14BTastysinV8_q5High.gguf" + }, + "class_type": "UnetLoaderGGUF", + "_meta": { + "title": "Unet Loader (GGUF) - High" + } + }, + "117": { + "inputs": { + "unet_name": "DasiwaWAN22I2V14BTastysinV8_q5Low.gguf" + }, + "class_type": "UnetLoaderGGUF", + "_meta": { + "title": "Unet Loader (GGUF) - Low" + } + }, + "121": { + "inputs": { + "frame_rate": 10, + "loop_count": 0, + "filename_prefix": "video", + "format": "video/h264-mp4", + "pix_fmt": "yuv420p", + "crf": 8, + "save_metadata": true, + "trim_to_audio": false, + "pingpong": false, + "save_output": false, + "images": [ + "87", + 0 + ] + }, + "class_type": "VHS_VideoCombine", + "_meta": { + "title": "Video Combine 🎥🅥🅗🅢" + } + }, + "144": { + "inputs": { + "PowerLoraLoaderHeaderWidget": { + "type": "PowerLoraLoaderHeaderWidget" + }, + "lora_1": { + "on": false, + "lora": "DR34ML4Y_I2V_14B_HIGH_V2.safetensors", + "strength": 0.4 + }, + "lora_2": { + "on": false, + "lora": "wan2.2-i2v-high-oral-insertion-v1.0.safetensors", + "strength": 1 + }, + "lora_3": { + "on": false, + "lora": "SmoothXXXAnimation_High.safetensors", + "strength": 1.5 + }, + "lora_4": { + "on": false, + "lora": "2D_animation_effects_high_noise.safetensors", + "strength": 0.4 + }, + "lora_5": { + "on": false, + "lora": "NSFW-22-H-e8.safetensors", + "strength": 1 + }, + "lora_6": { + "on": false, + "lora": "BounceHighWan2_2.safetensors", + "strength": 0.2 + }, + "➕ Add Lora": "", + "model": [ + "116", + 0 + ] + }, + "class_type": "Power Lora Loader (rgthree)", + "_meta": { + "title": "LORAS - HIGH NOISE" + } + }, + "145": { + "inputs": { + "PowerLoraLoaderHeaderWidget": { + "type": "PowerLoraLoaderHeaderWidget" + }, + "lora_1": { + "on": false, + "lora": "DR34ML4Y_I2V_14B_LOW_V2.safetensors", + "strength": 0.4 + }, + "lora_2": { + "on": false, + "lora": "wan2.2-i2v-low-oral-insertion-v1.0.safetensors", + "strength": 1 + }, + "lora_3": { + "on": false, + "lora": "SmoothXXXAnimation_Low.safetensors", + "strength": 1.5 + }, + "lora_4": { + "on": false, + "lora": "2D_animation_effects_low_noise.safetensors", + "strength": 0.4 + }, + "lora_5": { + "on": false, + "lora": "NSFW-22-L-e8.safetensors", + "strength": 1 + }, + "lora_6": { + "on": false, + "lora": "BounceLowWan2_2.safetensors", + "strength": 0.2 + }, + "➕ Add Lora": "", + "model": [ + "117", + 0 + ] + }, + "class_type": "Power Lora Loader (rgthree)", + "_meta": { + "title": "LORAS - LOW NOISE" + } + }, + "146": { + "inputs": { + "anything": [ + "217", + 0 + ] + }, + "class_type": "easy cleanGpuUsed", + "_meta": { + "title": "Clean VRAM Used" + } + }, + "149": { + "inputs": { + "ckpt_name": "rife49.pth", + "clear_cache_after_n_frames": 1, + "multiplier": 2, + "fast_mode": false, + "ensemble": true, + "scale_factor": 1, + "frames": [ + "223", + 0 + ] + }, + "class_type": "RIFE VFI", + "_meta": { + "title": "Frame Interpolation (RIFE)" + } + }, + "155": { + "inputs": { + "seed": -1 + }, + "class_type": "Seed (rgthree)", + "_meta": { + "title": "Seed (rgthree)" + } + }, + "183": { + "inputs": { + "value": 842 + }, + "class_type": "INTConstant", + "_meta": { + "title": "HEIGHT" + } + }, + "184": { + "inputs": { + "value": 474 + }, + "class_type": "INTConstant", + "_meta": { + "title": "WIDTH" + } + }, + "190": { + "inputs": { + "width": [ + "193", + 2 + ], + "height": [ + "193", + 3 + ], + "length": 41, + "batch_size": 1, + "motion_amplitude": 1.4, + "positive": [ + "93", + 0 + ], + "negative": [ + "89", + 0 + ], + "vae": [ + "90", + 0 + ], + "start_image": [ + "193", + 0 + ] + }, + "class_type": "PainterI2V", + "_meta": { + "title": "PainterI2V" + } + }, + "193": { + "inputs": { + "image": "742cad1b01e30ef47b613ef3df009957.jpg", + "resize": true, + "width": [ + "184", + 0 + ], + "height": [ + "183", + 0 + ], + "repeat": 1, + "keep_proportion": false, + "divisible_by": 16, + "mask_channel": "alpha", + "background_color": "" + }, + "class_type": "LoadAndResizeImage", + "_meta": { + "title": "START IMAGE" + } + }, + "210": { + "inputs": { + "model_name": "2x-AnimeSharpV4_RCAN.safetensors" + }, + "class_type": "UpscaleModelLoader", + "_meta": { + "title": "Load Upscale Model" + } + }, + "214": { + "inputs": { + "frame_rate": 20, + "loop_count": 1, + "filename_prefix": "AnimateDiff", + "format": "video/h264-mp4", + "pix_fmt": "yuv420p", + "crf": 8, + "save_metadata": true, + "trim_to_audio": false, + "pingpong": false, + "save_output": true, + "images": [ + "224", + 0 + ] + }, + "class_type": "VHS_VideoCombine", + "_meta": { + "title": "FIENAL" + } + }, + "217": { + "inputs": { + "add_noise": "disable", + "noise_seed": 666124386785654, + "steps": 4, + "cfg": 1, + "sampler_name": "euler", + "scheduler": "simple", + "start_at_step": 2, + "end_at_step": 4, + "return_with_leftover_noise": "disable", + "model": [ + "200:103", + 0 + ], + "positive": [ + "190", + 0 + ], + "negative": [ + "190", + 1 + ], + "latent_image": [ + "86", + 0 + ] + }, + "class_type": "KSamplerAdvanced", + "_meta": { + "title": "KSampler (Advanced)" + } + }, + "219": { + "inputs": { + "anything": [ + "190", + 2 + ] + }, + "class_type": "easy cleanGpuUsed", + "_meta": { + "title": "Clean VRAM Used" + } + }, + "221": { + "inputs": { + "anything": [ + "146", + 0 + ] + }, + "class_type": "easy clearCacheAll", + "_meta": { + "title": "Clear Cache All" + } + }, + "222": { + "inputs": { + "clip_name": "nsfw_wan_umt5-xxl_fp8_scaled.safetensors", + "type": "wan", + "device": "default" + }, + "class_type": "CLIPLoader", + "_meta": { + "title": "Load CLIP" + } + }, + "223": { + "inputs": { + "upscale_model": [ + "210", + 0 + ], + "image": [ + "87", + 0 + ] + }, + "class_type": "ImageUpscaleWithModel", + "_meta": { + "title": "Upscale Image (using Model)" + } + }, + "224": { + "inputs": { + "anything": [ + "225", + 0 + ] + }, + "class_type": "easy clearCacheAll", + "_meta": { + "title": "Clear Cache All" + } + }, + "225": { + "inputs": { + "anything": [ + "149", + 0 + ] + }, + "class_type": "easy cleanGpuUsed", + "_meta": { + "title": "Clean VRAM Used" + } + }, + "200:200": { + "inputs": { + "value": 10 + }, + "class_type": "PrimitiveFloat", + "_meta": { + "title": "SHIFT" + } + }, + "199:204": { + "inputs": { + "value": 10 + }, + "class_type": "PrimitiveFloat", + "_meta": { + "title": "SHIFT" + } + }, + "199:195": { + "inputs": { + "sage_attention": "auto", + "allow_compile": true, + "model": [ + "144", + 0 + ] + }, + "class_type": "PathchSageAttentionKJ", + "_meta": { + "title": "Patch Sage Attention KJ" + } + }, + "200:196": { + "inputs": { + "sage_attention": "auto", + "allow_compile": true, + "model": [ + "145", + 0 + ] + }, + "class_type": "PathchSageAttentionKJ", + "_meta": { + "title": "Patch Sage Attention KJ" + } + }, + "199:197": { + "inputs": { + "enable_fp16_accumulation": true, + "model": [ + "199:195", + 0 + ] + }, + "class_type": "ModelPatchTorchSettings", + "_meta": { + "title": "Model Patch Torch Settings" + } + }, + "200:198": { + "inputs": { + "enable_fp16_accumulation": true, + "model": [ + "200:196", + 0 + ] + }, + "class_type": "ModelPatchTorchSettings", + "_meta": { + "title": "Model Patch Torch Settings" + } + }, + "199:124": { + "inputs": { + "nag_scale": 11, + "nag_alpha": 0.25, + "nag_tau": 2.5, + "input_type": "default", + "model": [ + "199:197", + 0 + ], + "conditioning": [ + "89", + 0 + ] + }, + "class_type": "WanVideoNAG", + "_meta": { + "title": "WanVideoNAG-High" + } + }, + "200:127": { + "inputs": { + "nag_scale": 11, + "nag_alpha": 0.25, + "nag_tau": 2.5, + "input_type": "default", + "model": [ + "200:198", + 0 + ], + "conditioning": [ + "89", + 0 + ] + }, + "class_type": "WanVideoNAG", + "_meta": { + "title": "WanVideoNAG-Low" + } + }, + "199:104": { + "inputs": { + "shift": [ + "199:204", + 0 + ], + "model": [ + "199:124", + 0 + ] + }, + "class_type": "ModelSamplingSD3", + "_meta": { + "title": "ModelSamplingSD3" + } + }, + "200:103": { + "inputs": { + "shift": [ + "200:200", + 0 + ], + "model": [ + "200:127", + 0 + ] + }, + "class_type": "ModelSamplingSD3", + "_meta": { + "title": "ModelSamplingSD3" + } + } +}