ComfyUI可视化工作流集成:通义千问1.5-1.8B-Chat-GPTQ-Int4作为文本处理节点
ComfyUI可视化工作流集成:通义千问1.5-1.8B-Chat-GPTQ-Int4作为文本处理节点
1. 引言:当可视化工作流遇上智能文本生成
如果你用过ComfyUI,肯定被它那种用节点拖拽就能搭建复杂AI流程的自由度所吸引。从文生图到图生图,各种模型和功能像乐高积木一样拼接。但不知道你有没有遇到过这样的场景:流程跑了一半,突然需要根据一张中间生成的图片,写一段描述、编一个故事,或者生成一些营销文案。
这时候,你可能得手动把图片保存下来,打开另一个聊天窗口,把描述贴进去,等模型生成文本,再复制回ComfyUI里。整个过程不仅打断了流畅的创作,也破坏了自动化工作流的优雅。
今天要聊的,就是把一个轻量又好用的中文对话模型——通义千问1.5-1.8B-Chat的量化版本,直接做成一个ComfyUI的自定义节点。让它能无缝接入你的工作流,上游可以是任何能输出文本或图像描述的节点,下游可以连接需要文本输入的图像生成、视频合成或者其他处理节点。简单说,就是给你的可视化流水线,加一个“智能文本处理车间”。
2. 为什么选择通义千问1.5-1.8B-Chat-GPTQ-Int4?
在决定把哪个模型塞进ComfyUI之前,我对比过几个选项。最终选择这个版本,主要是出于几个很实际的考虑。
首先当然是尺寸和速度。1.8B参数,再经过GPTQ量化到INT4精度,模型文件体积能压缩到1GB左右。这意味着它不需要昂贵的独立显卡,甚至在一些性能不错的集成显卡或者有足够内存的CPU上也能跑起来。对于ComfyUI这种可能同时运行多个节点的环境来说,资源友好是第一位的。
其次是中文能力。通义千问在中文理解和生成上的表现,尤其是在这种小尺寸模型里,算是比较突出的。让它处理图片描述、生成文案、续写故事,输出的文本在通顺度和相关性上,对于辅助创作来说完全够用。毕竟我们的主要场景不是让它写学术论文,而是在工作流里快速产生可用的文本内容。
最后是易用性。这个量化版本社区支持度不错,有现成的加载和推理代码可以参考,把它封装成ComfyUI节点的工程量相对可控。我们的目标不是从零造轮子,而是高效地整合一个能即插即用的工具。
3. 核心思路:将模型封装为ComfyUI节点
在ComfyUI里,一切皆节点。一个节点通常有输入、处理逻辑和输出。我们要做的,就是创建一个新节点,它的输入可能是来自其他节点的文本(比如CLIP文本编码器的输出、图像描述符节点的结果),或者直接是一个字符串输入框。节点内部,则加载通义千问模型,根据输入和预设的提示词模板,生成新的文本,最后将这个文本输出给下一个节点。
听起来不复杂,对吧?但有几个关键点需要想清楚:
- 模型加载:节点初始化时加载模型,还是每次执行时加载?为了效率,我们肯定希望只加载一次。
- 输入输出定义:节点需要哪些输入参数?除了主要的文本输入,可能还需要控制生成长度、温度等参数。输出就是纯文本字符串。
- 提示词工程:如何设计一个通用的提示词模板,让模型能理解上游传来的信息(比如“这是一张图片的描述:XXX”),并执行我们想要的任务(比如“请扩展成一段生动的文案”)?
- 错误处理:模型推理可能出错,输入可能为空,这些情况节点要能妥善处理,避免导致整个工作流崩溃。
下面,我们就一步步把这些想法变成代码。
4. 动手实现:编写通义千问自定义节点
4.1 环境与依赖准备
假设你已经有一个可以正常运行的ComfyUI环境。我们需要额外安装模型运行所需的库。在你的ComfyUI项目目录下,或者在你的Python环境中,执行:
pip install transformers torch
# 如果需要使用特定的GPTQ加载功能,可能还需要安装auto-gptq
# pip install auto-gptq
接下来,在ComfyUI的custom_nodes目录下,为我们新节点创建一个文件夹,比如叫做Qwen-Comfy-Node。我们的主要代码文件就放在这里。
4.2 定义节点类与输入输出
我们创建一个名为qwen_node.py的文件。首先定义节点类,并注册它。
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
import comfy.sd
import comfy.utils
import nodes
import folder_paths
import sys
import os
# 将当前节点目录加入路径,方便导入可能存在的本地模块
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
class QwenTextProcessor:
"""
通义千问文本处理节点
输入一段文本或提示,调用Qwen模型生成扩展或转换后的文本。
"""
# 定义节点类别,这会在ComfyUI节点列表里显示
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {
"multiline": True,
"default": "请描述一张风景优美的山水画。"
}),
"prompt_template": ("STRING", {
"multiline": True,
"default": "用户输入:{user_input}\n请根据上述输入,生成一段丰富、生动的描述文本:"
}),
"max_new_tokens": ("INT", {
"default": 150,
"min": 10,
"max": 512,
"step": 10
}),
"temperature": ("FLOAT", {
"default": 0.7,
"min": 0.1,
"max": 2.0,
"step": 0.1
}),
},
"optional": {
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
}
}
# 定义节点返回类型
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("generated_text",)
FUNCTION = "process_text"
CATEGORY = "AI处理器/文本" # 节点在ComfyUI中的分类
def __init__(self):
# 初始化模型和分词器为None,延迟加载
self.model = None
self.tokenizer = None
self.pipe = None
self.model_loaded = False
def load_model(self):
"""懒加载模型,只在第一次执行时加载"""
if self.model_loaded:
return
model_name = "Qwen/Qwen1.5-1.8B-Chat-GPTQ-Int4" # Hugging Face模型ID
print(f"[Qwen节点] 正在加载模型: {model_name}")
try:
# 加载分词器
self.tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
# 加载量化模型。使用device_map="auto"让Transformers自动分配设备
self.model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map="auto",
trust_remote_code=True
)
# 创建文本生成管道,简化调用
self.pipe = pipeline(
"text-generation",
model=self.model,
tokenizer=self.tokenizer,
max_new_tokens=50, # 这里设个默认值,具体在调用时覆盖
)
self.model_loaded = True
print(f"[Qwen节点] 模型加载成功。")
except Exception as e:
print(f"[Qwen节点] 模型加载失败: {e}")
raise e
这段代码做了几件事:
- 定义了节点类
QwenTextProcessor。 INPUT_TYPES定义了节点的输入参数:一个主文本输入框、一个提示词模板、生成长度和温度参数,以及一个可选的随机种子。RETURN_TYPES和RETURN_NAMES指定节点输出一个名为generated_text的字符串。- 在
__init__中初始化模型相关变量,但并未真正加载,采用懒加载模式。 load_model方法包含了从Hugging Face加载模型和分词器的逻辑。trust_remote_code=True对于通义千问模型通常是必需的。
4.3 实现文本处理核心逻辑
接下来,在同一个类中添加process_text方法,这是节点的核心功能。
def process_text(self, text, prompt_template, max_new_tokens, temperature, seed=0):
"""
处理输入文本,调用模型生成新文本。
"""
# 1. 确保模型已加载
if not self.model_loaded:
self.load_model()
# 2. 准备输入:将用户文本填入提示词模板
# 如果模板中包含 {user_input},则替换,否则直接拼接。
if "{user_input}" in prompt_template:
formatted_prompt = prompt_template.format(user_input=text)
else:
formatted_prompt = f"{prompt_template}\n{text}"
# 3. 设置生成参数
generate_kwargs = {
"max_new_tokens": max_new_tokens,
"temperature": temperature,
"do_sample": temperature > 0, # 温度大于0时启用采样
"pad_token_id": self.tokenizer.eos_token_id,
}
if seed > 0:
torch.manual_seed(seed)
generate_kwargs["seed"] = seed
print(f"[Qwen节点] 生成提示: {formatted_prompt[:100]}...") # 打印前100字符便于调试
# 4. 调用模型生成
try:
# 使用pipeline进行生成
outputs = self.pipe(
formatted_prompt,
**generate_kwargs
)
generated_text = outputs[0]['generated_text']
# 5. 后处理:移除输入提示部分,只返回新生成的内容
# 简单的方法:如果生成文本以输入提示开头,则去掉它。
if generated_text.startswith(formatted_prompt):
result = generated_text[len(formatted_prompt):].strip()
else:
# 有时模型输出格式可能略有不同,返回全部文本
result = generated_text.strip()
print(f"[Qwen节点] 生成成功,长度: {len(result)}")
return (result,)
except Exception as e:
print(f"[Qwen节点] 文本生成过程中出错: {e}")
# 出错时返回错误信息或原始文本,避免工作流中断
return (f"[生成错误] {e}。输入文本为: {text}",)
这个方法串联了整个流程:格式化提示词、设置生成参数、调用模型、处理输出。这里采用了简单的后处理来剥离输入提示,你可以根据模型的实际输出格式进行调整。
4.4 注册节点并创建节点清单
最后,我们需要告诉ComfyUI这个新节点的存在。在qwen_node.py文件末尾添加:
# 将节点类注册到ComfyUI
NODE_CLASS_MAPPINGS = {
"QwenTextProcessor": QwenTextProcessor
}
NODE_DISPLAY_NAME_MAPPINGS = {
"QwenTextProcessor": "通义千问文本处理器"
}
同时,在Qwen-Comfy-Node文件夹下创建一个__init__.py文件(可以为空),以及一个__pycache__文件夹(如果不存在,运行后会自动生成)。
为了让ComfyUI识别,还需要创建一个node_list.json文件,不过更常见的做法是,ComfyUI会自动扫描custom_nodes目录下所有模块。确保你的目录结构如下:
ComfyUI/
├── custom_nodes/
│ └── Qwen-Comfy-Node/
│ ├── __init__.py
│ ├── qwen_node.py
│ └── (其他资源文件)
└── (其他ComfyUI目录和文件)
5. 在ComfyUI工作流中应用
启动ComfyUI,你应该在节点菜单的AI处理器/文本分类下找到通义千问文本处理器节点。
5.1 基础串联示例
一个最简单的用法是:
- 添加一个
CLIP文本编码器节点,输入一段简单的描述,比如“一只猫”。 - 将编码器的输出(或者直接使用一个文本节点)连接到
通义千问文本处理器的text输入。 - 在节点的
prompt_template中设置模板,例如:“这是一幅关于'{user_input}'的画作描述初稿,请将其扩展为一段富有画面感的详细描述:” - 连接一个
K采样器,将通义千问节点生成的文本,输入给正面提示词。 - 运行工作流,你会发现,用来生成图像的提示词,从简单的“一只猫”,变成了由模型扩展后的、更丰富的描述,从而可能引导生成更具细节的图像。
5.2 进阶多模态交互场景
更复杂的玩法在于闭环创作:
- 图像分析 -> 文本生成 -> 图像再生成:使用一个图像描述模型节点(如BLIP),分析一张初始图片,生成描述文本。将该文本输入通义千问节点,让其“从另一个角度描述”或“写一个关于此场景的短故事”。再将生成的新文本输入文生图模型,创造一张风格、内容相关联的新图像。
- 剧本/分镜生成:第一个文本节点输入故事大纲,通义千问节点将其扩展为详细场景描述。后续可以连接多个图像生成节点,为每个场景生成配图。
- 营销素材自动化:输入产品基础信息,通过通义千问节点生成不同平台(微博、小红书、电商详情页)的广告文案,再分别用不同的风格模型生成配图。
节点的prompt_template是这个玩法的核心杠杆。通过精心设计模板,你可以让同一个模型节点扮演“文案扩充员”、“风格转换器”、“故事编剧”等多种角色。
6. 效果与体验分享
在实际测试中,这个集成方案表现出了不错的实用性。将1.8B的量化模型集成到节点里,首次加载需要一点时间(取决于网络和硬盘速度),但加载完成后,后续的推理速度在CPU上也可接受,在GPU上则更快。
生成文本的质量对于工作流中的“辅助创作”定位是合格的。它能把一个简单的关键词扩展成一段流畅的描述,能根据指令转换文本风格。当然,它偶尔也会出现重复或偏离主题的情况,这时可以通过调整temperature参数(降低它以减少随机性)或优化prompt_template来改善。
最大的价值在于流程的自动化与集成化。你不再需要离开ComfyUI环境,不再需要手动复制粘贴。文本生成变成了工作流中一个可配置、可重复使用的环节,与图像生成、图像处理等节点平起平坐,真正实现了多模态创作的流水线作业。
7. 总结
把通义千问这样的语言模型做成ComfyUI自定义节点,思路并不复杂,但带来的灵活性提升是巨大的。它打破了文本生成与图像生成工具之间的壁垒,让AI创作的各个环节可以在一个可视化界面里自由组合。
这个实现只是一个起点。你可以在此基础上继续优化,比如增加模型参数(top_p, repetition_penalty)的控制,支持加载本地模型文件,或者实现更复杂的对话历史管理,让节点能进行多轮交互。甚至,你可以参考这个模式,将其他类型的模型(如图像描述、语音识别)也封装成节点,不断丰富你的ComfyUI创作工具箱。
试试看,把你脑海中那个需要跨软件、手动操作的创作步骤,用几个节点连接起来。你会发现,当AI工具之间能够对话,你的创作流程会变得前所未有的顺畅和强大。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)