From a29e1c8db05743773072808407be3523187db561 Mon Sep 17 00:00:00 2001 From: Wang Xiuqiang Date: Tue, 1 Jul 2025 22:54:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6=E4=BB=A3=E7=A0=81=E4=BB=93?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- outputs/prompts.yaml | 2 +- requirements.txt | 61 +++- requirments.txt | Bin 0 -> 42152 bytes scripts/__pycache__/flux_con.cpython-311.pyc | Bin 0 -> 13891 bytes scripts/flux_con.py | 282 +++++++++++++++++ scripts/run_pipeline.py | 2 +- scripts/test.py | 220 +++++++++++++ .../20250526_163432_chat_history.json | 0 .../20250526_163433_chat_history.json | 0 scripts/workflows/flux_redux.json | 292 ++++++++++++++++++ scripts/workflows/flux_work.json | 226 ++++++++++++++ 11 files changed, 1074 insertions(+), 11 deletions(-) create mode 100644 requirments.txt create mode 100644 scripts/__pycache__/flux_con.cpython-311.pyc create mode 100644 scripts/flux_con.py create mode 100644 scripts/test.py create mode 100644 scripts/workflows/20250526_163432_chat_history.json create mode 100644 scripts/workflows/20250526_163433_chat_history.json create mode 100644 scripts/workflows/flux_redux.json create mode 100644 scripts/workflows/flux_work.json diff --git a/outputs/prompts.yaml b/outputs/prompts.yaml index 57fed3f..76ccf11 100644 --- a/outputs/prompts.yaml +++ b/outputs/prompts.yaml @@ -1,5 +1,5 @@ description: "Generated prompt based on user input: \u7AEF\u5348\u8282\u6D77\u62A5\ \uFF0C\u5305\u542B\u80CC\u666F\u3001\u6D3B\u52A8\u4EAE\u70B9\u548C\u56FE\u6807" -generated_at: 03:05 PM HKT on Monday, June 09, 2025 +generated_at: 02:50 PM HKT on Monday, June 09, 2025 user_prompt: "\u7AEF\u5348\u8282\u6D77\u62A5\uFF0C\u5305\u542B\u80CC\u666F\u3001\u6D3B\ \u52A8\u4EAE\u70B9\u548C\u56FE\u6807" diff --git a/requirements.txt b/requirements.txt index af1d048..8bbb3b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,52 @@ -fastapi>=0.68.0 -uvicorn>=0.18.0 -python-dotenv>=0.21.0 -pyyaml>=6.0 -websocket-client>=1.5.0 -requests>=2.28.0 -pillow>=9.0.0 -psd-tools>=1.9.0 -openai>=1.0.0 +# LLM和API相关 +fastapi==0.104.1 +uvicorn==0.24.0 +python-dotenv==1.0.0 +requests==2.31.0 +httpx==0.25.1 +pydantic==2.4.2 + +# 图像处理 +Pillow==10.1.0 +numpy==1.26.2 +opencv-python==4.8.1.78 +photoshop-python-api==0.19.0 # PSD文件处理 + +# 深度学习和AI +torch==2.1.1 +transformers==4.35.2 +diffusers==0.24.0 +accelerate==0.24.1 + +# 工具和辅助库 +python-multipart==0.0.6 +pyyaml==6.0.1 +tqdm==4.66.1 +colorama==0.4.6 +loguru==0.7.2 + +# 数据处理和存储 +pandas==2.1.3 +sqlalchemy==2.0.23 +pymongo==4.6.0 +redis==5.0.1 + +# 测试和开发工具 +pytest==7.4.3 +black==23.11.0 +isort==5.12.0 +mypy==1.7.0 + +# Web服务和异步 +aiohttp==3.9.0 +websockets==12.0 +gunicorn==21.2.0 + +# 文件处理 +python-magic==0.4.27 +python-multipart==0.0.6 +aiofiles==23.2.1 + +# 监控和日志 +prometheus-client==0.19.0 +sentry-sdk==1.32.0 diff --git a/requirments.txt b/requirments.txt new file mode 100644 index 0000000000000000000000000000000000000000..948a56915b27904ceb044603163ff7b09cd46b15 GIT binary patch literal 42152 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 VnBMy6@W3vi3Oxe+$VJnY|9>5K=Su(p literal 0 HcmV?d00001 diff --git a/scripts/__pycache__/flux_con.cpython-311.pyc b/scripts/__pycache__/flux_con.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d106d9753a03ecc6f1a639002d6d80dd745f3a5 GIT binary patch literal 13891 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 literal 0 HcmV?d00001 diff --git a/scripts/flux_con.py b/scripts/flux_con.py new file mode 100644 index 0000000..c7a551f --- /dev/null +++ b/scripts/flux_con.py @@ -0,0 +1,282 @@ +import json +import os +import sys +import time +import uuid +import random +from datetime import datetime +from websocket import create_connection, WebSocketTimeoutException, WebSocketConnectionClosedException +import urllib.request +import urllib.parse + +def comfyui_img_info(user_input_analysis_result, system_prompt): + """ + 根据提示词分析结果生成图片,并返回parse_imglist列表 + + 参数: + user_input_analysis_result: 用户输入的分析结果(字典) + system_prompt: 用户输入的system prompt内容 + + 返回: + parse_imglist (list): 图片解析列表,包含图片信息的字典 + """ + # 从分析结果中提取参数 + width = user_input_analysis_result.get('width', 1024) + height = user_input_analysis_result.get('height', 768) + batch_size = user_input_analysis_result.get('batch_size', 1) + + # 配置参数 + WORKING_DIR = 'outputs' + COMFYUI_ENDPOINT = '101.201.50.90:8188' + DEFAULT_WORKFLOW = './workflows/flux_work.json' + TEMP_WORKFLOW_DIR = './workflows/temp' + + # 创建临时目录 + os.makedirs(TEMP_WORKFLOW_DIR, exist_ok=True) + PROCESSED_WORKFLOW = os.path.join(TEMP_WORKFLOW_DIR, f"processed_workflow_{uuid.uuid4().hex}.json") + + # 1. 预处理工作流 + workflow_file = preprocess_workflow( + system_prompt=system_prompt, + width=width, + height=height, + batch_size=batch_size, + input_json=DEFAULT_WORKFLOW, + output_json=PROCESSED_WORKFLOW + ) + + # 2. 准备输出目录 + os.makedirs(WORKING_DIR, exist_ok=True) + + # 创建客户端ID + client_id = str(uuid.uuid4()) + + # 生成图像 + saved_files = generate_images( + workflow_file=workflow_file, + server_address=COMFYUI_ENDPOINT, + output_dir=WORKING_DIR, + client_id=client_id + ) + + # 构建parse_imglist + parse_imglist = [] + for file_path in saved_files: + # 提取图片信息 + filename = os.path.basename(file_path) + name_without_ext = os.path.splitext(filename)[0] + + # 构造图片信息字典 + img_info = { + "picture_name": name_without_ext, + "picture_type": "png", + "picture_description": system_prompt, + "picture_size": f"{width}x{height}" + } + parse_imglist.append(img_info) + + return parse_imglist + +def preprocess_workflow(system_prompt, width, height, batch_size, input_json='flux_work.json', output_json='processed_workflow.json'): + """ + 预处理工作流文件,更新系统提示和图像参数 + """ + try: + with open(input_json, 'r') as f: + workflow = json.load(f) + + # 更新系统提示 + workflow['31']['inputs']['system_prompt'] = system_prompt + + # 更新图像参数 + workflow['27']['inputs']['width'] = str(width) + workflow['27']['inputs']['height'] = str(height) + workflow['27']['inputs']['batch_size'] = str(batch_size) + + # 保存更新后的工作流 + with open(output_json, 'w') as f: + json.dump(workflow, f, indent=2) + + print(f"工作流已更新并保存到: {output_json}") + return output_json + + except Exception as e: + print(f"预处理工作流出错: {str(e)}") + sys.exit(1) + +def queue_prompt(prompt, server_address, client_id): + """向服务器队列发送提示信息""" + p = {"prompt": prompt, "client_id": client_id} + data = json.dumps(p).encode('utf-8') + req = urllib.request.Request(f"http://{server_address}/prompt", data=data) + return json.loads(urllib.request.urlopen(req).read()) + +def get_image(filename, subfolder, folder_type, server_address): + """获取生成的图像""" + data = {"filename": filename, "subfolder": subfolder, "type": folder_type} + url_values = urllib.parse.urlencode(data) + with urllib.request.urlopen(f"http://{server_address}/view?{url_values}") as response: + return response.read() + +def get_history(prompt_id, server_address): + """获取历史记录""" + with urllib.request.urlopen(f"http://{server_address}/history/{prompt_id}") as response: + return json.loads(response.read()) + +def get_images(ws, prompt, server_address, client_id, timeout=600): + """获取生成的所有图像""" + prompt_id = queue_prompt(prompt, server_address, client_id)['prompt_id'] + print(f'提示ID: {prompt_id}') + output_images = {} + + start_time = time.time() + while True: + if time.time() - start_time > timeout: + print(f"超时:等待执行超过{timeout}秒") + break + + try: + out = ws.recv() + if isinstance(out, str): + message = json.loads(out) + if message['type'] == 'executing': + data = message['data'] + if data['node'] is None and data['prompt_id'] == prompt_id: + print('执行完成') + break + except Exception as e: + print(f"接收消息出错: {str(e)}") + break + + history = get_history(prompt_id, server_address).get(prompt_id, {}) + if not history: + print("未找到该提示的历史记录") + return {} + + for node_id, node_output in history['outputs'].items(): + if 'images' in node_output: + images_output = [] + for image in node_output['images']: + try: + image_data = get_image(image['filename'], image['subfolder'], image['type'], server_address) + images_output.append({ + 'data': image_data, + 'filename': image['filename'], + 'subfolder': image['subfolder'], + 'type': image['type'] + }) + except Exception as e: + print(f"获取图像错误: {str(e)}") + output_images[node_id] = images_output + + print(f'获取到 {len(output_images)} 组图像输出') + return output_images + +def generate_images(workflow_file, server_address, output_dir, client_id): + """生成图像主函数""" + try: + # 加载工作流 + with open(workflow_file, 'r', encoding='utf-8') as f: + workflow_data = json.load(f) + + # 使用随机种子 + seed = random.randint(1, 10**8) + print(f'使用种子: {seed}') + + # 更新种子 + workflow_data['25']['inputs']['noise_seed'] = seed + + # 创建WebSocket连接 + ws_url = f"ws://{server_address}/ws?clientId={client_id}" + ws = create_connection(ws_url, timeout=600) + + # 获取图像 + images = get_images(ws, workflow_data, server_address, client_id) + ws.close() + + # 保存图像 + saved_files = [] + if images: + for node_id, image_list in images.items(): + for i, img in enumerate(image_list): + timestamp = datetime.now().strftime("%Y%m%d%H%M%S") + filename = f"{seed}_{timestamp}_{i}.png" + file_path = os.path.join(output_dir, filename) + + try: + with open(file_path, "wb") as f: + f.write(img['data']) + saved_files.append(file_path) + print(f'已保存: {file_path}') + except Exception as e: + print(f"保存图像错误: {str(e)}") + + return saved_files + + except Exception as e: + print(f"生成图像出错: {str(e)}") + return [] + +if __name__ == "__main__": + # 配置参数 + WORKING_DIR = 'output' + COMFYUI_ENDPOINT = '101.201.50.90:8188' + DEFAULT_WORKFLOW = './workflows/flux_work.json' + TEMP_WORKFLOW_DIR = './workflows/temp' + + # 从命令行获取输入参数 + if len(sys.argv) != 5: + print("用法: python test.py ") + print("示例: python test.py \"南开大学图书馆,大雨天\" 2048 1024 1") + sys.exit(1) + + system_prompt = sys.argv[1] + width = int(sys.argv[2]) + height = int(sys.argv[3]) + batch_size = int(sys.argv[4]) + + # 创建临时目录 + os.makedirs(TEMP_WORKFLOW_DIR, exist_ok=True) + + # 创建临时文件路径 + PROCESSED_WORKFLOW = os.path.join(TEMP_WORKFLOW_DIR, f"processed_workflow_{uuid.uuid4().hex}.json") + + # 1. 预处理工作流 + workflow_file = preprocess_workflow( + system_prompt=system_prompt, + width=width, + height=height, + batch_size=batch_size, + input_json=DEFAULT_WORKFLOW, + output_json=PROCESSED_WORKFLOW + ) + + # 2. 准备输出目录 + os.makedirs(WORKING_DIR, exist_ok=True) + + # 创建客户端ID + client_id = str(uuid.uuid4()) + + print(f"系统提示: {system_prompt}") + print(f"图像尺寸: {width}x{height}") + print(f"批次大小: {batch_size}") + print(f"工作流文件: {workflow_file}") + print(f"客户端ID: {client_id}") + print(f"开始使用ComfyUI生成图像: {COMFYUI_ENDPOINT}") + + start_time = time.time() + + # 生成图像 + print(f"\n===== 开始生成图像 =====") + saved_files = generate_images( + workflow_file=workflow_file, + server_address=COMFYUI_ENDPOINT, + output_dir=WORKING_DIR, + client_id=client_id + ) + + # 输出结果 + elapsed = time.time() - start_time + print(f"\n处理完成,耗时 {elapsed:.2f} 秒") + print(f"共生成 {len(saved_files)} 张图像") + print(f"保存位置: {WORKING_DIR}") \ No newline at end of file diff --git a/scripts/run_pipeline.py b/scripts/run_pipeline.py index bd64b77..9a57dfa 100644 --- a/scripts/run_pipeline.py +++ b/scripts/run_pipeline.py @@ -5,7 +5,7 @@ from generate_layout import call_deepseek, generate_vue_code, save_code from generate_text import load_config_from_file, get_poster_content_suggestions from fastapi import FastAPI, HTTPException from fastapi.responses import FileResponse -from ComfyUI.flux_con import comfyui_img_info # 导入已实现的图像生成函数 +from flux_con import comfyui_img_info # 导入已实现的图像生成函数 # 配置路径 config_paths = { diff --git a/scripts/test.py b/scripts/test.py new file mode 100644 index 0000000..daef436 --- /dev/null +++ b/scripts/test.py @@ -0,0 +1,220 @@ +import json +from websocket import create_connection, WebSocketTimeoutException, WebSocketConnectionClosedException +import uuid +import urllib.request +import urllib.parse +import random +import time +from datetime import datetime + +# 定义一个函数来显示GIF图片 +def show_gif(fname): + import base64 + from IPython import display + with open(fname, 'rb') as fd: + b64 = base64.b64encode(fd.read()).decode('ascii') + return display.HTML(f'') + +# 定义一个函数向服务器队列发送提示信息 +def queue_prompt(prompt): + p = {"prompt": prompt, "client_id": client_id} + data = json.dumps(p).encode('utf-8') + req = urllib.request.Request("http://{}/prompt".format(server_address), data=data) + return json.loads(urllib.request.urlopen(req).read()) + +# 定义一个函数来获取图片 +def get_image(filename, subfolder, folder_type): + data = {"filename": filename, "subfolder": subfolder, "type": folder_type} + url_values = urllib.parse.urlencode(data) + with urllib.request.urlopen("http://{}/view?{}".format(server_address, url_values)) as response: + return response.read() + +# 定义一个函数来获取历史记录 +def get_history(prompt_id): + with urllib.request.urlopen("http://{}/history/{}".format(server_address, prompt_id)) as response: + return json.loads(response.read()) + +# 定义一个函数来获取图片,这涉及到监听WebSocket消息 +def get_images(ws, prompt): + prompt_id = queue_prompt(prompt)['prompt_id'] + print('Prompt: ', prompt) + print('Prompt ID: ', prompt_id) + output_images = {} + + # 等待执行完成 + start_time = time.time() + while True: + if time.time() - start_time > 1200: # 设置2分钟超时 + print("超时:等待执行完成超过120秒") + break + + out = ws.recv() + if isinstance(out, str): + message = json.loads(out) + if message['type'] == 'executing': + data = message['data'] + if data['node'] is None and data['prompt_id'] == prompt_id: + print('Execution complete') + break # 执行完成 + else: + continue # 预览为二进制数据 + + # 获取完成的历史记录 + history = get_history(prompt_id).get(prompt_id, {}) + + if not history: + print("未找到该提示的历史记录") + return {} + + for node_id in history['outputs']: + node_output = history['outputs'][node_id] + # 图片分支 + if 'images' in node_output: + images_output = [] + for image in node_output['images']: + try: + image_data = get_image(image['filename'], image['subfolder'], image['type']) + images_output.append(image_data) + except Exception as e: + print(f"获取图像错误: {str(e)}") + output_images[node_id] = images_output + # 视频分支 + elif 'videos' in node_output: + videos_output = [] + for video in node_output['videos']: + try: + video_data = get_image(video['filename'], video['subfolder'], video['type']) + videos_output.append(video_data) + except Exception as e: + print(f"获取视频错误: {str(e)}") + output_images[node_id] = videos_output + + print(f'Obtained {len(output_images)} image/video sets') + return output_images + +# 解析工作流并获取图片 +def parse_workflow(prompt, seed, workflowfile): + print(f'Workflow file: {workflowfile}') + try: + with open(workflowfile, 'r', encoding="utf-8") as f: + prompt_data = json.load(f) + # 设置文本提示 + prompt_data["6"]["inputs"]["text"] = prompt + # 设置随机种子(如果需要) + if "Ksampler" in prompt_data: + if "seed" in prompt_data["Ksampler"]["inputs"]: + prompt_data["Ksampler"]["inputs"]["seed"] = seed + elif "noise_seed" in prompt_data["Ksampler"]["inputs"]: + prompt_data["Ksampler"]["inputs"]["noise_seed"] = seed + return prompt_data + except Exception as e: + print(f"工作流解析错误: {str(e)}") + return {} + +# 生成图像并保存 +def generate_clip(prompt, seed, workflowfile, idx): + print(f'Processing prompt #{idx}: "{prompt[:50]}{"..." if len(prompt) > 50 else ""}"') + print(f'Using seed: {seed}') + + try: + # 使用正确的WebSocket连接方式 + ws_url = f"ws://{server_address}/ws?clientId={client_id}" + + # 使用 create_connection + ws = create_connection(ws_url, timeout=600) + + # 解析工作流 + workflow_data = parse_workflow(prompt, seed, workflowfile) + if not workflow_data: + print("工作流数据为空") + return + + # 获取图像 + images = get_images(ws, workflow_data) + + # 关闭连接 + ws.close() + except WebSocketTimeoutException as e: + print(f"WebSocket连接超时: {str(e)}") + return + except WebSocketConnectionClosedException as e: + print(f"WebSocket连接已关闭: {str(e)}") + return + except Exception as e: + print(f"WebSocket错误: {str(e)}") + return + + saved_files = [] + if images: + for node_id, image_list in images.items(): + for i, image_data in enumerate(image_list): + # 格式化时间戳 + timestamp = datetime.now().strftime("%Y%m%d%H%M%S") + # 创建唯一文件名 + filename = f"{idx}_{seed}_{timestamp}_{i}.png" + file_path = f"{WORKING_DIR}/{filename}" + + print(f'Saving to: {file_path}') + try: + with open(file_path, "wb") as f: + f.write(image_data) + saved_files.append(file_path) + except Exception as e: + print(f"文件保存错误: {str(e)}") + else: + print("未获取到图像数据") + + if saved_files: + print(f"成功生成 {len(saved_files)} 张图片") + else: + print("未保存任何图片") + +# 直接在代码中定义提示词列表 +PROMPTS = [ + "A beautiful sunset over the ocean, realistic, cinematic lighting", + "A futuristic cityscape at night, cyberpunk style, neon lights", + "An ancient forest with magical creatures, fantasy, photorealistic", + "A steampunk laboratory with bubbling beakers and intricate machinery", + "Abstract geometric patterns in vibrant colors, digital art", + "A majestic lion in the African savannah, golden hour lighting", + "A cozy cabin in the mountains during winter, warm lights inside", + "A detailed close-up of a butterfly on a flower, macro photography", + "Underwater scene with coral reef and tropical fish, crystal clear water" +] + +if __name__ == "__main__": + # 设置工作目录和项目相关的路径 + WORKING_DIR = 'output' + workflowfile = './workflows/flux_redux.json' + COMFYUI_ENDPOINT = '101.201.50.90:8188' + + # 服务器配置 + global server_address, client_id + server_address = COMFYUI_ENDPOINT + client_id = str(uuid.uuid4()) # 生成一个唯一的客户端ID + + # 种子设置 - 可以选择固定或随机 + USE_RANDOM_SEED = True # 设为False则使用固定种子 + base_seed = 15465856 + + print(f"Starting image generation with ComfyUI at {server_address}") + print(f"Working directory: {WORKING_DIR}") + print(f"Workflow file: {workflowfile}") + print(f"Client ID: {client_id}") + + start_time = time.time() + + # 处理每个提示词 + for idx, prompt in enumerate(PROMPTS, start=1): + # 设置种子 + current_seed = random.randint(1, 10**8) if USE_RANDOM_SEED else base_seed + + print(f"\n===== Processing Prompt #{idx} of {len(PROMPTS)} =====") + generate_clip(prompt, current_seed, workflowfile, idx) + + # 添加延迟以避免服务器过载 + time.sleep(2) # 2秒延迟 + + elapsed = time.time() - start_time + print(f"\nProcessing completed in {elapsed:.2f} seconds") + print(f"Generated images for {len(PROMPTS)} prompts") \ No newline at end of file diff --git a/scripts/workflows/20250526_163432_chat_history.json b/scripts/workflows/20250526_163432_chat_history.json new file mode 100644 index 0000000..e69de29 diff --git a/scripts/workflows/20250526_163433_chat_history.json b/scripts/workflows/20250526_163433_chat_history.json new file mode 100644 index 0000000..e69de29 diff --git a/scripts/workflows/flux_redux.json b/scripts/workflows/flux_redux.json new file mode 100644 index 0000000..607b560 --- /dev/null +++ b/scripts/workflows/flux_redux.json @@ -0,0 +1,292 @@ +{ + "6": { + "inputs": { + "text": [ + "45", + 0 + ], + "clip": [ + "11", + 0 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Positive Prompt)" + } + }, + "8": { + "inputs": { + "samples": [ + "13", + 0 + ], + "vae": [ + "10", + 0 + ] + }, + "class_type": "VAEDecode", + "_meta": { + "title": "VAE解码" + } + }, + "9": { + "inputs": { + "filename_prefix": "ComfyUI", + "images": [ + "8", + 0 + ] + }, + "class_type": "SaveImage", + "_meta": { + "title": "保存图像" + } + }, + "10": { + "inputs": { + "vae_name": "ae.safetensors" + }, + "class_type": "VAELoader", + "_meta": { + "title": "加载VAE" + } + }, + "11": { + "inputs": { + "clip_name1": "t5xxl_fp16.safetensors", + "clip_name2": "clip_l.safetensors", + "type": "flux", + "device": "default" + }, + "class_type": "DualCLIPLoader", + "_meta": { + "title": "双CLIP加载器" + } + }, + "12": { + "inputs": { + "unet_name": "flux1-dev.safetensors", + "weight_dtype": "default" + }, + "class_type": "UNETLoader", + "_meta": { + "title": "UNet加载器" + } + }, + "13": { + "inputs": { + "noise": [ + "25", + 0 + ], + "guider": [ + "22", + 0 + ], + "sampler": [ + "16", + 0 + ], + "sigmas": [ + "17", + 0 + ], + "latent_image": [ + "27", + 0 + ] + }, + "class_type": "SamplerCustomAdvanced", + "_meta": { + "title": "自定义采样器(高级)" + } + }, + "16": { + "inputs": { + "sampler_name": "euler" + }, + "class_type": "KSamplerSelect", + "_meta": { + "title": "K采样器选择" + } + }, + "17": { + "inputs": { + "scheduler": "simple", + "steps": 20, + "denoise": 1, + "model": [ + "30", + 0 + ] + }, + "class_type": "BasicScheduler", + "_meta": { + "title": "基本调度器" + } + }, + "22": { + "inputs": { + "model": [ + "30", + 0 + ], + "conditioning": [ + "41", + 0 + ] + }, + "class_type": "BasicGuider", + "_meta": { + "title": "基本引导器" + } + }, + "25": { + "inputs": { + "noise_seed": 214516345808749 + }, + "class_type": "RandomNoise", + "_meta": { + "title": "随机噪波" + } + }, + "26": { + "inputs": { + "guidance": 3.5, + "conditioning": [ + "6", + 0 + ] + }, + "class_type": "FluxGuidance", + "_meta": { + "title": "Flux引导" + } + }, + "27": { + "inputs": { + "width": 1024, + "height": 1024, + "batch_size": 4 + }, + "class_type": "EmptySD3LatentImage", + "_meta": { + "title": "空Latent图像(SD3)" + } + }, + "30": { + "inputs": { + "max_shift": 1.15, + "base_shift": 0.5, + "width": 1024, + "height": 1024, + "model": [ + "12", + 0 + ] + }, + "class_type": "ModelSamplingFlux", + "_meta": { + "title": "采样算法(Flux)" + } + }, + "38": { + "inputs": { + "clip_name": "sigclip_vision_patch14_384.safetensors" + }, + "class_type": "CLIPVisionLoader", + "_meta": { + "title": "加载CLIP视觉" + } + }, + "39": { + "inputs": { + "crop": "center", + "clip_vision": [ + "38", + 0 + ], + "image": [ + "40", + 0 + ] + }, + "class_type": "CLIPVisionEncode", + "_meta": { + "title": "CLIP视觉编码" + } + }, + "40": { + "inputs": { + "image": "WechatIMG16695.jpeg" + }, + "class_type": "LoadImage", + "_meta": { + "title": "加载图像" + } + }, + "41": { + "inputs": { + "strength": 1, + "strength_type": "multiply", + "conditioning": [ + "26", + 0 + ], + "style_model": [ + "42", + 0 + ], + "clip_vision_output": [ + "39", + 0 + ] + }, + "class_type": "StyleModelApply", + "_meta": { + "title": "应用风格模型" + } + }, + "42": { + "inputs": { + "style_model_name": "flux1-redux-dev.safetensors" + }, + "class_type": "StyleModelLoader", + "_meta": { + "title": "加载风格模型" + } + }, + "45": { + "inputs": { + "user_prompt": "作为一个AI提示词专家,请你仿照范例,根据我给出的主题,生成一条符合下列要求的提示词,来让CLIP模型可以更好地理解画面主体。注意:你的输出将提供给图生图(image-to-image)模型,所以你只需要对用户输入中的风格和细节部分作扩展。\n 要求共五条,请严格遵守:\n 1: 用自然语言简单句来描述画面,请避免出现过于长的,或者格式过于复杂的句子,句子中不要出现*等特殊符号。\n 2.用英语表达。 \n 3.直接给出prompt内容即可,不需要解释和说明。\n 4. 每条prompt至少50词,不超过200词。\n 5.避免模棱两可的说法。\n 例如:[Reference Image Weight: 0.7] Cartoonized Nankai University Main Building, \nGothic-Revival architecture with rounded edges, crimson bricks and golden arched windows (ultra-high texture details), whimsical cloud-shaped eaves dripping liquid clock gears (steampunk elements), soft pastel gradients. \nDynamic elements: \nTranslucent 1919-era scholar phantoms floating with glowing books (semi-transparent mercury texture), oversized origami maple leaves spiraling around twin bell towers (visible musical notes in air). \nEnvironment: \nSurreal candy-pink to indigo gradient sky, emerald velvet lawns with squirrels wearing graduation caps (playful proportions:1.5x). Ground puddles reflecting calculus formula ripples (mathematical glow effect). \nTechnical parameters: \nStudio Ghibli style, watercolor rendering, 8K resolution, cinematic lighting, symmetry composition, ultra-detailed lineart", + "system_prompt": "南开大学鸟瞰图,3D电影高级风格。", + "enable_history": false, + "max_history": 10, + "history_json": "", + "save_path": "./chat_history.json", + "api_config": [ + "46", + 0 + ] + }, + "class_type": "DeepSeekChat", + "_meta": { + "title": "LLM Model Input Box" + } + }, + "46": { + "inputs": { + "config_name": "DeepSeek官方Chat API", + "temperature": 1, + "max_tokens": 512, + "stream": false, + "api_key": "" + }, + "class_type": "DeepSeekAPIConfig", + "_meta": { + "title": "LLM API Model Selector" + } + } +} \ No newline at end of file diff --git a/scripts/workflows/flux_work.json b/scripts/workflows/flux_work.json new file mode 100644 index 0000000..29b2fbd --- /dev/null +++ b/scripts/workflows/flux_work.json @@ -0,0 +1,226 @@ +{ + "6": { + "inputs": { + "text": [ + "31", + 0 + ], + "clip": [ + "11", + 0 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Positive Prompt)" + } + }, + "8": { + "inputs": { + "samples": [ + "13", + 0 + ], + "vae": [ + "10", + 0 + ] + }, + "class_type": "VAEDecode", + "_meta": { + "title": "VAE解码" + } + }, + "9": { + "inputs": { + "filename_prefix": "ComfyUI", + "images": [ + "8", + 0 + ] + }, + "class_type": "SaveImage", + "_meta": { + "title": "保存图像" + } + }, + "10": { + "inputs": { + "vae_name": "ae.safetensors" + }, + "class_type": "VAELoader", + "_meta": { + "title": "加载VAE" + } + }, + "11": { + "inputs": { + "clip_name1": "t5xxl_fp16.safetensors", + "clip_name2": "clip_l.safetensors", + "type": "flux", + "device": "default" + }, + "class_type": "DualCLIPLoader", + "_meta": { + "title": "双CLIP加载器" + } + }, + "12": { + "inputs": { + "unet_name": "flux1-dev.safetensors", + "weight_dtype": "default" + }, + "class_type": "UNETLoader", + "_meta": { + "title": "UNet加载器" + } + }, + "13": { + "inputs": { + "noise": [ + "25", + 0 + ], + "guider": [ + "22", + 0 + ], + "sampler": [ + "16", + 0 + ], + "sigmas": [ + "17", + 0 + ], + "latent_image": [ + "27", + 0 + ] + }, + "class_type": "SamplerCustomAdvanced", + "_meta": { + "title": "自定义采样器(高级)" + } + }, + "16": { + "inputs": { + "sampler_name": "euler" + }, + "class_type": "KSamplerSelect", + "_meta": { + "title": "K采样器选择" + } + }, + "17": { + "inputs": { + "scheduler": "simple", + "steps": 25, + "denoise": 1, + "model": [ + "30", + 0 + ] + }, + "class_type": "BasicScheduler", + "_meta": { + "title": "基本调度器" + } + }, + "22": { + "inputs": { + "model": [ + "30", + 0 + ], + "conditioning": [ + "26", + 0 + ] + }, + "class_type": "BasicGuider", + "_meta": { + "title": "基本引导器" + } + }, + "25": { + "inputs": { + "noise_seed": 142213168350829 + }, + "class_type": "RandomNoise", + "_meta": { + "title": "随机噪波" + } + }, + "26": { + "inputs": { + "guidance": 3.5, + "conditioning": [ + "6", + 0 + ] + }, + "class_type": "FluxGuidance", + "_meta": { + "title": "Flux引导" + } + }, + "27": { + "inputs": { + "width": "{{width}}", + "height": "{{height}}", + "batch_size": "{{batch_size}}" + }, + "class_type": "EmptySD3LatentImage", + "_meta": { + "title": "空Latent图像(SD3)" + } + }, + "30": { + "inputs": { + "max_shift": 1.1500000000000001, + "base_shift": 0.5000000000000001, + "width": 1024, + "height": 1024, + "model": [ + "12", + 0 + ] + }, + "class_type": "ModelSamplingFlux", + "_meta": { + "title": "采样算法(Flux)" + } + }, + "31": { + "inputs": { + "user_prompt": "作为一个AI提示词专家,请你仿照范例,根据我给出的主题,生成一条符合下列要求的提示词,来让CLIP模型可以更好地理解画面主体。注意:你需要仿照下面的示例详细分析(仅仿照写法,而不仿照任何内容),将用户的需求转化为详细的提示词。\\n 要求共六条,请严格遵守:\\n 1: 用自然语言简单句来描述画面,请避免出现过于长的,或者格式过于复杂的句子,句子中不要出现*等特殊符号。\\n 2.用英语表达。 \\n 3.直接给出prompt内容即可,不需要任何解释和说明。\\n 4. 每条prompt至少50词,不超过200词。\\n 5.避免模棱两可的说法。\\n 6.描述的最开始加入:“no text, no AI style”\\n 例如:\nCartoon-Style Nankai University Main Building​​,\nvividly depicted with rounded edges and pastel gradients, the iconic Gothic-Revival structure stands majestically. Crimson brick façade contrasts with golden-glowing arched windows, while whimsical cloud-shaped eaves drip melted clock details. A giant smiling sun hangs low, casting honey-golden rays through simplified pine trees, creating striped shadows dancing on marble stairs.\n\nTranslucent ghostly scholars from 1919 float near pillars holding glowing books, their outlines shimmering like liquid mercury. Oversized autumn leaves (stylized as maple-red origami) spiral around twin bell towers chiming visible musical notes. Puddles on the ground mirror upside-down building reflections rippling with calculus formulas.\n\n​​Environment​​:\nSurreal candy-pink sunset gradients blend into starry indigo sky above. Playful squirrels wearing tiny graduation caps scamper across emerald lawns textured like green velvet.", + "system_prompt": "{{system_prompt}}", + "enable_history": false, + "max_history": 10, + "history_json": "", + "save_path": "./chat_history.json", + "api_config": [ + "32", + 0 + ] + }, + "class_type": "DeepSeekChat", + "_meta": { + "title": "LLM Model Input Box" + } + }, + "32": { + "inputs": { + "config_name": "DeepSeek官方Chat API", + "temperature": 1, + "max_tokens": 512, + "stream": false, + "api_key": "" + }, + "class_type": "DeepSeekAPIConfig", + "_meta": { + "title": "LLM API Model Selector" + } + } +} \ No newline at end of file