通义千问1.5-1.8B-Chat-GPTQ-Int4与ComfyUI工作流结合:可视化AI应用搭建探索
最近在折腾AI应用自动化流程时,我发现了一个挺有意思的组合:把轻量级的对话模型,比如通义千问的1.8B版本,和ComfyUI这个可视化工具连起来用。你可能用过ComfyUI来跑图生图或者文生图,但有没有想过,让它在生成图片之前,先跟一个“大脑”聊聊天,根据聊天的内容来决定生成什么?
这听起来有点绕,但实际做出来效果很实用。比如,你可以做一个自动化的营销海报生成器:用户输入一个简单的产品描述,工作流先调用通义千问模型,让它把这个描述扩展成一段富有吸引力的广告文案和详细的关键词,然后再把这些内容喂给Stable Diffusion去生成最终的图片。整个过程,从文字理解到创意构思再到图像生成,都在一个可视化的流程里自动完成。
今天,我就来分享一下怎么把通义千问的API能力,“塞进”ComfyUI,变成一个你可以拖拽、连接的自定义节点,从而搭建出这种更智能、更可控的自动化AI应用。
1. 为什么要把对话模型和ComfyUI结合?
在深入具体操作之前,我们先聊聊这么做的价值。ComfyUI的核心优势在于其可视化、可编排、可复现的工作流。你可以把不同的AI模型(如图像生成、图像处理、超分辨率)像搭积木一样连接起来,构建复杂的处理管线。但它的“思考”能力通常依赖于用户预先输入、固定的提示词(Prompt)。
而像通义千问这样的对话模型,恰恰擅长理解、推理和生成结构化的文本。它的加入,相当于给这个可视化的流水线装上了一个“实时决策大脑”。这个大脑可以根据上游的输入(比如用户的一句话、一张图片的分析结果),动态地生成下游任务所需的指令或内容。
结合后能做什么?想象几个场景:
- 智能提示词工程师:用户说“画一只在星空下奔跑的卡通狐狸”,工作流先让通义千问把这个简单描述,细化成包含风格、构图、光影、细节的SD提示词,再交给画图模型。
- 多轮交互式创作:在ComfyUI界面里,你可以先和“内置”的对话模型聊天,反复调整对画面的描述,直到满意,再一键触发生成。这比在外部聊天工具和绘图工具间来回切换流畅得多。
- 条件化内容生成:结合图像识别节点,先分析一张用户上传的风景图,让通义千问根据图片内容写一首诗或一段故事,然后再用这段文本的风格去生成新的配图。
- 自动化内容流水线:批量处理产品列表,让对话模型为每个产品生成不同的广告语和场景描述,然后自动调用绘图模型生成对应的宣传图。
简单说,这种结合打破了“静态提示词”的局限,让AI工作流具备了动态理解和内容生成的能力,自动化程度和智能水平都上了一个台阶。
2. 准备工作:模型与工具
要把这两者结合起来,我们需要准备好“积木块”。
2.1 模型选择:为什么是Qwen1.5-1.8B-Chat-GPTQ-Int4?
通义千问有多个尺寸的模型,从0.5B到72B不等。我选择1.5-1.8B这个尺寸的Chat模型,并特别强调GPTQ-Int4量化版本,主要是出于在ComfyUI中实际部署的考虑:
- 资源占用低:1.8B参数模型经过Int4量化后,显存占用可以控制在2GB左右。这意味着你可以在消费级显卡(如RTX 3060 12G)上轻松运行,同时还能为ComfyUI中的图像生成模型留出足够显存。
- 推理速度快:小模型+量化,使得单次对话响应速度非常快(通常在秒级),这对于需要频繁调用的工作流节点至关重要,能保证整体流程的流畅性。
- 能力足够:对于我们设想的场景——解析用户指令、扩写提示词、进行简单对话——1.8B模型已经能提供相当不错的结果。它理解意图准确,生成文本通顺,完全能满足作为“工作流逻辑控制器”的需求。
- 易于部署:GPTQ量化格式被
transformers库和auto-gptq库良好支持,在Python环境中加载和调用非常方便,便于我们封装成API服务。
你可以从Hugging Face等模型社区找到这个模型的量化版本文件(通常包含config.json,model.safetensors,quantize_config.json等)。
2.2 核心工具:ComfyUI与自定义节点
- ComfyUI:我们的可视化“画布”。确保你已经安装好ComfyUI,并且能正常使用其基础功能。
- ComfyUI自定义节点:这是实现功能的关键。ComfyUI允许用户通过Python编写自定义节点,扩展其功能。我们的目标就是编写一个节点,它能向通义千问的API发送请求并获取回复。
- 模型API服务:我们需要一个桥梁,让ComfyUI节点能调用到通义千问模型。有两种主流方式:
- 本地启动API服务器:使用
FastAPI、Flask等框架,编写一个简单的服务,加载我们下载好的Qwen-1.8B-Chat-GPTQ模型,提供/chat/completions类似的接口。这种方式数据完全本地,延迟低,但需要自己写服务端代码。 - 使用现有API:如果模型部署在云端或通过其他服务(如OpenAI兼容的API)提供,则可以直接让节点调用该API地址。本文将以本地启动API服务为例进行说明,因为它更通用,且不依赖外部网络。
- 本地启动API服务器:使用
3. 第一步:封装通义千问为本地API服务
为了让ComfyUI能调用,我们先把模型包装成一个HTTP服务。这里用一个非常简单的FastAPI应用示例。
创建一个名为qwen_api_server.py的文件:
from fastapi import FastAPI, HTTPException from pydantic import BaseModel from transformers import AutoTokenizer from auto_gptq import AutoGPTQForCausalLM import uvicorn import torch # 1. 定义请求/响应数据结构 class ChatRequest(BaseModel): messages: list # 格式:[{"role": "user", "content": "你好"}] max_new_tokens: int = 512 temperature: float = 0.7 class ChatResponse(BaseModel): response: str # 2. 加载模型和分词器(请修改为你的实际模型路径) model_name_or_path = "/your/path/to/Qwen1.5-1.8B-Chat-GPTQ-Int4" tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=True) model = AutoGPTQForCausalLM.from_quantized( model_name_or_path, device="cuda:0", # 根据你的GPU情况调整 use_triton=False, inject_fused_attention=False, trust_remote_code=True ) model.eval() app = FastAPI(title="Qwen-1.8B-Chat Local API") @app.post("/v1/chat/completions", response_model=ChatResponse) async def chat_completion(request: ChatRequest): try: # 3. 构建模型输入的prompt格式(遵循Qwen的Chat格式) text = tokenizer.apply_chat_template( request.messages, tokenize=False, add_generation_prompt=True ) inputs = tokenizer(text, return_tensors="pt").to(model.device) # 4. 生成回复 with torch.no_grad(): outputs = model.generate( **inputs, max_new_tokens=request.max_new_tokens, temperature=request.temperature, do_sample=True ) generated_ids = outputs[0][inputs.input_ids.shape[-1]:] response_text = tokenizer.decode(generated_ids, skip_special_tokens=True) return ChatResponse(response=response_text) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) if __name__ == "__main__": # 5. 启动服务,默认运行在 http://127.0.0.1:8000 uvicorn.run(app, host="0.0.0.0", port=8000)运行这个脚本:
python qwen_api_server.py如果看到服务启动信息,说明你的本地通义千问API服务已经就绪了。你可以用curl或Postman测试一下接口是否正常。
4. 第二步:创建ComfyUI自定义节点
接下来,我们在ComfyUI的custom_nodes目录下创建一个新的文件夹,比如comfyui-qwen-node,然后创建必要的文件。
节点文件结构:
comfyui-qwen-node/ ├── __init__.py ├── nodes.py └── web └── logo.svg (可选,节点图标)核心逻辑在nodes.py中。我们将创建一个继承自ComfyUI节点基类的新节点。
import requests import json import nodes class QwenChatNode: @classmethod def INPUT_TYPES(cls): return { "required": { "prompt": ("STRING", {"multiline": True, "default": "你好,请介绍一下你自己。"}), "api_url": ("STRING", {"default": "http://127.0.0.1:8000/v1/chat/completions"}), "max_tokens": ("INT", {"default": 512, "min": 1, "max": 2048}), "temperature": ("FLOAT", {"default": 0.7, "min": 0.1, "max": 2.0, "step": 0.1}), }, } RETURN_TYPES = ("STRING",) # 这个节点输出一个字符串 RETURN_NAMES = ("response",) FUNCTION = "generate" CATEGORY = "AI对话" # 在ComfyUI节点列表中的分类 def generate(self, prompt, api_url, max_tokens, temperature): # 构造请求数据,遵循我们本地API的格式 messages = [{"role": "user", "content": prompt}] payload = { "messages": messages, "max_new_tokens": max_tokens, "temperature": temperature } headers = {"Content-Type": "application/json"} try: response = requests.post(api_url, json=payload, headers=headers, timeout=30) response.raise_for_status() result = response.json() # 假设我们的API返回格式是 {"response": "..."} answer = result.get("response", "").strip() except requests.exceptions.RequestException as e: answer = f"API请求失败: {e}" except json.JSONDecodeError: answer = "API返回格式错误" # 将回答文本输出到下一个节点 return (answer,) # 将节点注册到ComfyUI NODE_CLASS_MAPPINGS = { "QwenChatNode": QwenChatNode } NODE_DISPLAY_NAME_MAPPINGS = { "QwenChatNode": "通义千问对话" }__init__.py文件可以很简单:
from .nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']将comfyui-qwen-node文件夹放到ComfyUI的custom_nodes目录下,然后重启ComfyUI。如果一切正常,你应该在节点搜索框里输入“通义千问”或“Qwen”时,找到我们新创建的节点。
5. 第三步:在ComfyUI中构建可视化工作流
现在,好玩的来了。我们打开ComfyUI,开始搭建一个简单的智能提示词生成工作流。
- 添加节点:在空白处右键,搜索并添加“通义千问对话”节点。
- 配置节点:在节点的属性面板中,
api_url填写你本地服务的地址(如http://127.0.0.1:8000/v1/chat/completions)。在prompt输入框里,写下你的初始指令,例如:“请为‘夏日冰爽柠檬汽水’生成一段详细的、适合图像生成的英文提示词,要求画面明亮、有水滴、背景虚化。” - 连接节点:从“通义千问对话”节点的
response输出端口拉出一根线。 - 添加KSampler节点:这是ComfyUI用于Stable Diffusion图像生成的核心节点。搜索并添加一个
KSampler节点。 - 连接文本到提示词:将“通义千问对话”节点的
response输出,连接到KSampler节点所需的positive(正向提示词)输入端口。你可能需要一个CLIP Text Encode节点作为中介,这是ComfyUI的标准做法:Qwen输出->CLIP Text Encode (positive)->KSampler的positive输入。 - 配置其他参数:为
KSampler节点选择你喜欢的Checkpoint模型,设置好采样步数、CFG等参数,并连接好Empty Latent Image(潜在空间图像)节点。 - 执行工作流:点击“Queue Prompt”按钮。ComfyUI会先调用你的本地通义千问API,将你的指令转化为一段详细的提示词,然后将这段提示词送给Stable Diffusion模型,最终生成一张符合描述的“夏日柠檬汽水”图片。
工作流的意义:你刚刚构建的,就是一个动态提示词生成器。用户只需要输入一个简单的想法,剩下的创意构思和细节描述,都由工作流中的对话模型自动完成,并驱动图像生成。你可以保存这个工作流,以后只需修改最开始的用户指令,就能生成完全不同主题和风格的图片。
6. 更复杂的应用场景与优化思路
上面的例子只是一个起点。基于这个框架,你可以玩出更多花样:
- 多轮对话节点:改造节点,使其能保存对话历史,实现工作流内的多轮交互。这需要节点有“记忆”能力,可以将历史消息列表也作为输入/输出。
- 条件分支:结合ComfyUI的
Conditioning相关节点,让通义千问的输出不仅作为提示词,还能作为选择不同模型分支或参数的依据。例如,让模型判断用户描述的情感是“积极”还是“消极”,从而选择不同的LoRA模型或采样器。 - 连接图像识别节点:使用
CLIPVision等节点分析输入图片,将分析结果(如标签、描述)作为通义千问的输入,让它根据图片内容生成故事、诗歌或新的创作灵感。 - 批量处理与队列:将通义千问节点放在一个循环或批处理逻辑中,自动处理一列输入文本(如产品名称列表),并生成对应的图片。
- 节点UI优化:为你的自定义节点设计更友好的输入界面,比如增加系统提示词(system prompt)的输入框,增加历史对话的显示窗口等。
在实际使用中,你可能会遇到API调用超时、响应格式解析等问题。这就需要你在节点代码中加入更完善的错误处理、重试机制和日志记录。同时,本地API服务的性能调优(如启用模型并行、使用更快的推理后端如vLLM)也能提升整体工作流的体验。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。