标签 文生图 下的文章

上个帖子已经分享了如何在润云进入ComfyUI界面。

下面我来具体分享ComfyUI的使用方法

一、文生图

界面上的节点和整个画布都可以拖动,也可以放大缩小。

ComfyUI 为我们提供了一个默认的文生图工作流。直接点击右边的 Queue Prompt 就能够触发生图流程,你可以看到有个绿色的边框会随着流程的进展在不同的节点上显示。

整个工作流由两个基本的部分组成:节点(Nodes)和边(Edges)。

• 每一个矩形块就是一个节点,比如 Load Checkpoint CLIP Text Encoder 等。可以把每个节点看成是函数,它们都具有输入、输出和参数三个属性。

• 连接每个节点的输入和输出的线就是边。

其他还有很多的细节和概念,我将会在接下来的内容中逐步解释。

我们直接从这个默认工作流开始,它包含了下面这些步骤。

1.1 选择模型

首先需要在 Load Checkpoint 这个节点中选择一个模型,这里的模型选项就是在上文中下载的那些模型文件。比如我这里就放置了多个可选的模型,我可以根据自己的需求选择我想要使用的模型。

1.2 构造提示词

选择完模型,下一步就是构造提示语了。

在界面上,有两个 CLIP Text Encode (Prompt) 节点,这两个节点都是用来构造我们的提示语的。

其中,上面一个节点用来输入正向提示语(Positive Prompt),即告诉模型做什么,而下面一个节点则用来输入负面提示语(Negative Prompt),即告诉模型不要做什么。

如果觉得容易混淆,可以像我这样直接双击节点名称改成它对应的功能的名称,就像下面这样。

下面的节点也可以看出哪个是正向哪个是负向

CLIP Text Encode 节点的作用是将提示语转换为标记,然后通过文本编码器将它们处理为嵌入(Embeddings)。

你可以使用 (关键词:权重) 的这样的语法来控制关键词的权重。

比如,使用 (keyword:1.4) 来增强效果,或 (keyword:0.9) 来减弱效果。

1.3 生成图像

点击下方的 Run,等待一会儿就能够看到有一张图像生成完成了。

二、ComfyUI 的工作机制

ComfyUI 的强大之处就在于它的高度可配置性。熟悉每个节点的功能之后可以让我们轻易地根据需求来定制化操作。

在介绍图生图工作流之前,我需要先向你详细介绍一下 ComfyUI 的工作机制。

Stable Diffusion 的生图过程可以总结为以下三个主要步骤:

  • 文本编码:用户输入的提示语通过一个称为文本编码器(Text Encoder) 的组件编译成各个单词的特征向量。这一步将文本转换为模型可以理解和处理的格式;
  • 潜在空间(Latent space)转换:来自文本编码器的特征向量与一个随机噪声图像一起被转换到潜在空间。在这个空间中,随机图像根据特征向量进行去噪处理,得到一个中间产物。这一步生图过程的是关键所在,因为模型会在这里学习将文本特征与视觉表现相联系。
  • 图像解码:最后,潜在空间中的中间产物由图像解码器(Image Decoder) 进行解码,转换为我们可以看到的实际图像。

了解了 Stable Diffusion 层面的生图流程之后,接下来我们深入了解一下 ComfyUI 在实现这个过程中的关键组件和节点。

2.1 Load Checkpoint 节点

Load Checkpoint 节点会加载一个模型,一个 Stable Diffusion 模型主要包含以下三个部分:

  • MODEL

MODEL 组件是一个在潜在空间(Latent Space)中运行的噪声预测模型。

这句话的意思是 Stable Diffusion 模型在潜在空间中对图像的生成过程进行建模,并通过预测和去除噪声逐渐还原图像的过程。

具体来说就是,在 Stable Diffusion 中,图像生成首先在潜在空间中引入随机噪声,然后模型通过一系列步骤逐渐去除这些噪声,生成符合提示语的图像。

这种逐步去噪的过程由噪声预测模型来完成。潜在空间是图像的一个简化、高度抽象化的表示,可以降低模型的计算复杂度,可以让模型在生成图像时更高效。

在 ComfyUI 中,Load Checkpoint 节点的 MODEL 输出连接到 KSampler 节点,KSampler 节点执行反向扩散过程。

KSampler 节点利用 MODEL 在潜在表示中进行迭代去噪,逐步优化图像,直到它符合给定的提示语。

  • CLIP (Contrastive Language-Image Pre-training)

CLIP 其实是一个负责预处理用户提供的正向和负面提示语的语言模型。它将文本提示转换为 MODEL 可以理解的格式,指导图像生成过程。

在 ComfyUI 中,Load Checkpoint 节点的 CLIP 输出连接到 CLIP Text Encode 节点。CLIP Text Encode 节点获取用户提供的提示语,并将它们输入到 CLIP 语言模型中,转换为向量嵌入。

这些向量嵌入可以捕捉单词的语义,为 MODEL 生成符合提示语的图像提供更多的指导。

  • VAE (Variational AutoEncoder)

它包含一个编码器和一个解码器,其中,编码器用于将图像压缩为低维的潜在表示,而解码器用于从潜在表示中重建图像。

在文生图的过程中,VAE 仅在最后一步使用,它的作用就是将生成的图像从潜在空间转换回像素空间。

ComfyUI 中的 VAE Decode 节点获取 KSampler 节点的输出,并利用 VAE 的解码器部分将潜在表示转换为最终的像素空间图像。

VAE 与 CLIP 语言模型是独立的组件。CLIP 主要处理文本提示语,而 VAE 负责在像素空间和潜在空间之间进行转换。

2.2 CLIP Text Encode 节点

在上文中有提到,在 CLIP Text Encode 节点中我们可以输入生成图像的提示语,而这个节点的作用就是获取我们提供的提示语,并将其输入到 CLIP 语言模型中。

CLIP 是一个强大的语言模型,能够理解单词的语义并将其与视觉概念相关联。当提示语输入到 CLIP Text Encode 节点后,它会将每个单词转换为向量嵌入。向量嵌入是高维的数字表示,包含了单词的语义信息,模型能够根据这些信息生成符合提示语的图像。

2.3 Empty Latent Image 节点

在 ComfyUI 的文生图的过程中,它首先会在潜在空间中生成一个随机图像,这个图像会作为模型处理的初始状态,它的大小与实际像素空间中的图像尺寸成比例。

在 ComfyUI 中,我们可以调整潜在图像的高度和宽度来控制生成图像的大小。此外,我们还可以设置批处理大小来确定每次运行生成的图像数量(batch_size)。

潜在图像的最佳尺寸取决于所使用的 Stable Diffusion 模型版本。

对于 v1.5 模型,推荐的尺寸是 512x512 或 768x768;对于 SDXL 模型,最佳尺寸是 1024x1024。ComfyUI 提供了多种常见的宽高比可供选择,但是需要注意的是,潜在图像的宽度和高度必须是 8 的倍数,这样才能确保与模型架构的兼容性。

2.4 VAE 节点

在界面中我们能看到 Load Checkpoint 节点的 VAE 属性就直接连接到了 VAE 节点。所以,这里的 VAE 节点其实就是上文中所提到的负责在像素空间和潜在空间之间转换图像的 VAE。

2.5 KSampler 节点

在 ComfyUI 中,生图过程的核心节点就是 KSampler 节点。它负责在潜在空间中对随机图像进行去噪,让生成的图像符合我们提供的提示语。KSampler 使用的是一种称为反向扩散的技术,可以迭代地去除噪声,并根据 CLIP 向量嵌入添加有意义的细节。

KSampler 节点提供了多个参数,让我们可以微调图像的生成过程:

  • Seed

    Seed 值控制了初始噪声和最终图像的构图。设置特定的 Seed 值,我们可以获得可重复的结果,可以保持多次生成的一致性。

  • Control_after_generate

    这个参数决定了每次生成后 Seed 值的变化方式,可以设置为随机化(每次运行生成新的随机 Seed)、递增、递减或者固定不变。

  • Step

    采样步数决定了优化过程的强度。如果设置步数较大,则会产生更少的伪影和更精细的图像,但也会增加生成时间。

  • Sampler_name

    这个参数用于选择 KSampler 所使用的特定采样算法。不同的采样算法可能会产生略有不同的结果,且生成速度也会有所不同。

  • Scheduler

    这个参数用于控制在去噪过程中的每一步中噪声水平的变化速率,它决定了从潜在表示中去除噪声的速度。

  • Denoise

    这个参数用于设置去噪过程应消除的初始噪声量。值为 1 表示去除所有噪声,从而生成干净且细节丰富的图像。

通过调整这些参数,我们可以微调图像的生成过程,从而获得理想的图像。

至此,我花了大量篇幅向你介绍了 ComfyUI 中的所有节点以及其对应的功能,希望到目前为止能够帮助你对 ComfyUI 有一个较为全面的认知和理解。

后续我会使用图生图、图片扩展等流程的教学。点点关注,之后会持续更新哦~~~

感谢:【开源欢迎star】即梦海外版2api :Dreamina2API 以及:jimeng-api

晚上看到海外版注册机,然后看到有个 2api 是 py 版本,想着能不能重构下,直接部署到大善人那儿,于是让 AI 搓了一个出来,目前只有文生图,其他还没弄(熬不动了,溜去睡了)


在线:https://j.aisk.de5.net

项目地址:dreamina-api

感谢支持


📌 转载信息
转载时间: 2026/1/25 08:05:03

引言

在上一篇文章中,我们探讨了 AI 绘画看似神奇的“魔法”背后的真相:它并非凭空创造,而是一个从混沌的噪点中,通过无数次“观察-脑补-修正”的循环,逐步建立秩序、生成图像的过程。理解了这一核心原理,一个自然的问题随之产生:我们该如何操控这个过程?是需要编写晦涩难懂的代码,还是有更直观、更易上手的方法?

答案是肯定的。今天,我们将介绍一位强大的幕后英雄——ComfyUI。作为一款基于节点流程的 Stable Diffusion 用户界面,ComfyUI 就像是一个透明的 AI 魔法工坊。它将复杂的 AI 生成过程拆解为一个个独立的模块,让使用者能够像搭积木一样,直观地构建和掌控自己的 AI 绘画工作流。本文将带领读者走进这个工坊,通过拆解一个最基础的文生图工作流,揭示每一个“积木”是如何分工协作,最终完成那场精彩的“脑补”大戏的。

第一部分:初识 ComfyUI —— AI 的可视化乐高

如果将传统的、集成度高的 AI 绘画 WebUI 比作一个功能齐全的“黑盒子”微波炉,用户只需放入食材、按下按钮即可得到成品,那么 ComfyUI 就更像是一套透明的乐高积木,或者一个开放式的中央厨房。

ComfyUI 的核心特点在于其“节点化 (Node-based)”的设计理念。在这里,每一个功能——无论是加载模型、处理文本,还是执行采样、解码图像——都被封装成了一个个独立的方块,称为“节点”。用户通过线缆将这些节点连接起来,定义数据的流向。

这种可视化流向的设计,使得 AI 的工作过程不再神秘。使用者看到了什么连接,AI 后台就执行了什么操作。数据从哪里来,到哪里去,经过了怎样的处理,一切都一目了然。更重要的是,这种极致的灵活性赋予了用户无限的创造空间。使用者可以根据自己的需求,像搭积木一样自由组合各种节点,构建出从简单到无比复杂的个性化创意工作流。

第二部分:解剖一只麻雀 —— 最基础的文生图工作流拆解

面对 ComfyUI 的界面,初学者可能会对满屏的节点和连线感到困惑。但无需担心,万丈高楼平地起。理解了最基础的工作流,就掌握了通往复杂应用的钥匙。下面展示的是一个最典型的 ComfyUI 文生图(Text-to-Image)工作流界面,我们将逐一拆解其中的核心角色。

1. 大管家:加载器 (Checkpoint Loader Simple)

一切工作的起点,是这个被称为“加载器”的节点。它就像是整个魔法工坊的物料仓库大管家。

它的作用是加载预先训练好的模型文件,通常称为 Checkpoint。这个文件至关重要,因为它打包了 AI 的核心能力:负责图像生成的“大脑”(UNet 网络)、负责理解文本的“眼睛”(CLIP 模型)以及负责图像数据转换的“翻译器”(VAE)。选择不同的 Checkpoint 文件,就决定了 AI 的“阅历”和基础“画风”,是擅长二次元动漫,还是写实摄影,全赖于此。它是所有后续工作的基石。

2. 翻译官与指挥棒:CLIP 文本编码器 (CLIP Text Encode)

人类使用自然语言描述画面,而 AI 的核心模型只能理解数学化的向量。这就需要“CLIP 文本编码器”充当人类与 AI 之间的沟通桥梁。

这个节点的作用是将用户输入的文本提示词(Prompt),“翻译”成 AI 能懂的数学指令,在技术上称为“条件 (Conditioning)”

在基础工作流中,通常会看到两个这样的节点。一个负责翻译正向提示词,生成“正向条件”,告诉 AI “画面里必须出现什么”(如:一只猫、高质量、阳光);另一个负责翻译反向提示词,生成“反向条件”,告诉 AI “画面里绝对不能出现什么”(如:低质量、变形、水印)。这两个条件就像是两根指挥棒,将在后续的生成过程中,严格引导和约束 AI 的创作方向。

3. 魔术师与沙盘:K 采样器 (KSampler)

“K 采样器”是整个工坊的核心车间,是奇迹真正发生的地方。它负责执行我们之前提到的“从噪点到清晰图像”的去噪循环。

为了高效地处理图像生成这一庞大的计算工程,AI 极其聪明地选择了一个策略:不在巨大的像素级画布上直接作画,而是在一个被称为“潜在空间 (Latent Space)”的沙盘上搭建一个精巧的“小模型”(潜在图像)。KSampler 就是在这个沙盘上进行精细化作业的魔术师。因为它处理的是高度浓缩的信息,而非海量的像素数据,所以效率极高。

这位魔术师在沙盘上工作时,并非随心所欲。它需要三种原料:从加载器获取的“模型”能力、一个初始的“空白画布”(通常是一个纯噪声的潜在图像),以及最重要的——从文本编码器传来的两根“指挥棒”。

在设定的步数内,KSampler 执行着“观察-脑补-修正”的循环。在每一步操作中,它都会严格参照“正向条件”的指南和“反向条件”的禁令,努力将沙盘上混沌的噪声,逐步转化为符合人类要求的、有意义的“小模型”。

4. 神奇打印机:VAE 解码 (VAE Decode)

当 KSampler 在沙盘上完成了创作,我们得到的是一个“潜在图像”。它虽然包含了画面的所有核心信息,但却是一团人类肉眼无法辨识的压缩数据。

这时就需要“VAE 解码”节点出场了。它就像是一台神奇的建筑打印机。它接过沙盘上那个抽象的“小模型”,利用大管家提供的 VAE 工具(图像数据转换的翻译器),按照特定的规则将这份压缩数据“解压”,并最终“打印”成我们眼前这座宏伟、清晰、色彩斑斓的像素大图。

5. 展示台:保存/预览图像 (Save/Preview Image)

工作流的终点是“保存/预览图像”节点。它的任务非常直观:将 VAE 解码器输出的最终像素图像展示在界面上供用户检阅,并将其保存到计算机的硬盘中,完成整个创作流程。

第三部分:连线——让数据流动起来

在 ComfyUI 中,节点之间的连线不仅仅是视觉上的连接,它们代表了数据显性的流动路径。理解了连线,就理解了 AI 工作的逻辑。

就像不同形状的积木插口一样,ComfyUI 中只有相同类型的数据端口才能连接,这保证了流程的正确性。

  • 模型连模型 (MODEL):将加载器中的绘画能力传递给采样器。
  • 条件连条件 (CONDITIONING):将文本编码器生成的“指挥棒”传递给采样器,指引创作方向。
  • 潜在图像连潜在图像 (LATENT):在采样器和解码器之间传递那个核心的沙盘“小模型”。
  • VAE 连 VAE (VAE):将加载器中的翻译规则传递给解码器,用于最终图像的还原。

整个流程可以总结为一条清晰的主线:加载模型备物料 -> 输入文字变指挥棒 -> 准备沙盘造噪声 -> 采样核心搞创作(受指挥棒引导) -> VAE 解码打印出图像。

结语

ComfyUI 以其独特的节点化设计,看似复杂,实则提供了一种最直观、最透彻的方式来理解和掌控 AI 绘画。它将深奥的 AI 生成原理拆解为一个个清晰可见的步骤,让我们不仅能“知其然”(看到最终的精美图像),更能“知其所以然”(理解图像是如何一步步生成的)。

通过理解“潜在空间”这个高效运作的沙盘,以及“条件”这两根强有力的指挥棒,我们揭开了 AI 绘画魔法的一角。掌握基础工作流只是第一步,ComfyUI 的魅力在于其无限的扩展性。鼓励每一位使用者去探索更多的高级节点,如 ControlNet、LoRA 等,搭建属于自己的、独一无二的 AI 绘画流水线,释放无限的创造潜能。

本文由mdnice多平台发布

【2026年01月19日】 FlowyAIPC 现已更新至 v4.0.5 版本。本次更新聚焦于 AI 创作体验与本地推理使用门槛的优化,带来了全新的 文生图功能,同时对 WinML NPU 系列模型的使用引导进行了加强,让更多用户可以更清楚、更安心地使用本地 AI 能力。

新功能上线:文生图(Text to Image)

在 v4.0.5 中,FlowyAIPC 正式支持 文生图功能。用户只需输入文字描述,即可生成对应图片,用于创意设计、内容配图、灵感草稿等多种场景。

FlowyAIPC文生图功能具有更丰富的生成控制能力,包括:

    • 支持设置生成风格(如人像摄影、经典日漫、赛博朋克等)
    • 支持自定义图片比例(如1:1、3:2、9:16等),适配不同使用场景
    • 同时支持 本地模型生成 与 云端模型生成

其中,本地文生图基于 Z-image 模型,生成过程在本地完成,更加注重数据可控性与隐私安全。


⚠️ 文生图功能使用说明(请务必查看)

FlowyAIPC本地文生图最低配置:Intel Core Ultra系列芯片 + 内存 32GB 及以上

如果设备暂不满足本地文生图功能最低配置,也可直接使用云端文生图模式,无需额外配置即可体验完整功能。

FlowyAIPC文生图效果展示

WinML · NPU 模型使用引导优化

在 v4.0.5 版本中,FlowyAIPC 还针对 WinML 的 NPU 系列模型 增加了更多用户引导与提醒,包括硬件适配提示、使用条件说明等,帮助用户在使用本地模型时更清楚地了解设备支持情况,降低上手成本,减少试错。

FlowyAIPC 将持续围绕 本地 AI、可控数据、真实效率提升不断迭代与完善。
欢迎大家更新至 v4.0.5,体验全新的文生图能力,也欢迎在使用过程中向我们反馈你的建议。

访问FlowyAIPC官网:www.flowyaipc.cn

美团 LongCat 全新上线 AI 生图功能,该功能基于 LongCat 系列模型「LongCat-Image」打造而成。不仅在文生图任务中实现了“快、真、准” :出图快速响应、达到摄影棚拍摄质感、中文渲染精准度高;更在图像编辑任务上做到了精准便捷,无需复杂指令,可以用自然语言对图像进行二次编辑。无论是追求高效出图的普通用户,还是需要精准落地创意的专业创作者,LongCat 都以 “轻量化模型 + 流畅体验” ,让 AI 生图真正成为人人可用的创作工具。

目前,AI 生图功能已在 LongCat APP 和 https://longcat.ai/ 同步上线,轻松解锁高效创作新方式。

LongCat · AI 生图「三大功能亮点 」

亮点一:图像生成 + 编辑一体化,创意落地无断点

从 “文字生成图片” 到 “用嘴改图” 一步到位,帮你轻松拿捏专业创作:

  • 简单提示词也能高效出图:基于深度优化语义理解能力,简单提示词也能生成效果高度契合画面、布局、氛围及内容,在保障质量的前提下大幅提升创作效率。
  • 全场景编辑无断点:支持物体增删、风格迁移、视角转换、人像精修、文本修改等 15 类细分任务,无论是简单的背景替换,还是复杂的多轮复合指令,均能精准执行。
  • 多轮编辑不丢质感:修改后画面和原图风格、光影保持一致,不会出现 “拼接感”,人像编辑保留面部特征,多轮编辑画面不跑偏。

prompt:头发颜色变成灰色,衣服颜色变成米色,面带微笑

prompt:拉远镜头,显示更多室内场景

prompt:将人物变为棕色的熊,保持相同的姿态

prompt:消除最左边的饮料

prompt:让猫闭上眼睛

prompt:变成真的老虎,在海边

prompt:在红色圈添加一个白色的钟表,绿色框添加黑色的手提包,黑色框添加一只白色的猫

亮点二:中文文字生成超能打,生僻字也不翻车

中文文字生成能力优异,生僻字生成也不在话下:

  • 字符渲染优异:店铺牌匾、海报标题、书籍封面等场景的中文文字,无错字、漏字、字体扭曲,多行排版、段落文本均能精准渲染
  • 生僻字高覆盖率:非常见字、异体字、书法字体(楷体、行书)准确率较高,适配传统文化、专业领域等特殊创作需求
  • 智能排版:自动匹配场景调整文字大小、颜色、行距,如古风文案搭配书法字体,科技主题适配现代无衬线字体,无需手动调整

亮点三:快速生成摄影棚级质感画面

  • 快速响应不等待:轻量化技术优化让单张高清图高效生成,效率较同类工具有一定提升,高频创作无需久候。
  • 质感堪比棚拍实景:优化构图与光影美学,物体纹理、场景光影精准复刻真实世界,人物肢体、物体比例遵循物理规律,实现摄影棚拍质感。

强大功能背后的「技术底座」

LongCat-Image具备出色的跨语言图像编辑能力,通过共享 MM-DiT+Single-DiT 混合主干架构与VLM条件编码器,文生图与编辑能力相互辅助,继承文生图的出图质量并具备出色的指令遵循、一致性保持能力,在主流公开评测基准上达到第一梯队水平。文字生成专项能力上,覆盖全量通用规范汉字并在在商业海报、自然场景文字上都展现出极强的适用性。此外,通过精细化模型设计及多阶段训练策略优化,极大提升生成真实度、合理性并可支持消费级显卡高效推理。

文字生成基准测试

图像编辑基准测试性能比较

用 LongCat 记录你的「灵感瞬间」吧!

LongCat APP 体验入口:在「LongCat APP」中,你可以:输入一句话,生成高质量图像,或对生成图像进行迭代编辑、多轮生成,快速响应。

LongCat Web 端入口

您可以登录 https://longcat.ai/  ,体验高效的 AI 生图功能,或对生成图像进行多轮编辑。

iOS 用户可在 APPStore 中搜索 「LongCat」

更多玩法探索

美团 LongCat 全新上线 AI 生图功能,该功能基于 LongCat 系列模型「LongCat-Image」打造而成。不仅在文生图任务中实现了“快、真、准” :出图快速响应、达到摄影棚拍摄质感、中文渲染精准度高;更在图像编辑任务上做到了精准便捷,无需复杂指令,可以用自然语言对图像进行二次编辑。无论是追求高效出图的普通用户,还是需要精准落地创意的专业创作者,LongCat 都以 “轻量化模型 + 流畅体验” ,让 AI 生图真正成为人人可用的创作工具。

目前,AI 生图功能已在 LongCat APP 和 https://longcat.ai/ 同步上线,轻松解锁高效创作新方式。

LongCat · AI 生图「三大功能亮点 」

亮点一:图像生成 + 编辑一体化,创意落地无断点

从 “文字生成图片” 到 “用嘴改图” 一步到位,帮你轻松拿捏专业创作:

  • 简单提示词也能高效出图:基于深度优化语义理解能力,简单提示词也能生成效果高度契合画面、布局、氛围及内容,在保障质量的前提下大幅提升创作效率。
  • 全场景编辑无断点:支持物体增删、风格迁移、视角转换、人像精修、文本修改等 15 类细分任务,无论是简单的背景替换,还是复杂的多轮复合指令,均能精准执行。
  • 多轮编辑不丢质感:修改后画面和原图风格、光影保持一致,不会出现 “拼接感”,人像编辑保留面部特征,多轮编辑画面不跑偏。

prompt:头发颜色变成灰色,衣服颜色变成米色,面带微笑

prompt:拉远镜头,显示更多室内场景

prompt:将人物变为棕色的熊,保持相同的姿态

prompt:消除最左边的饮料

prompt:让猫闭上眼睛

prompt:变成真的老虎,在海边

prompt:在红色圈添加一个白色的钟表,绿色框添加黑色的手提包,黑色框添加一只白色的猫

亮点二:中文文字生成超能打,生僻字也不翻车

中文文字生成能力优异,生僻字生成也不在话下:

  • 字符渲染优异:店铺牌匾、海报标题、书籍封面等场景的中文文字,无错字、漏字、字体扭曲,多行排版、段落文本均能精准渲染
  • 生僻字高覆盖率:非常见字、异体字、书法字体(楷体、行书)准确率较高,适配传统文化、专业领域等特殊创作需求
  • 智能排版:自动匹配场景调整文字大小、颜色、行距,如古风文案搭配书法字体,科技主题适配现代无衬线字体,无需手动调整

亮点三:快速生成摄影棚级质感画面

  • 快速响应不等待:轻量化技术优化让单张高清图高效生成,效率较同类工具有一定提升,高频创作无需久候。
  • 质感堪比棚拍实景:优化构图与光影美学,物体纹理、场景光影精准复刻真实世界,人物肢体、物体比例遵循物理规律,实现摄影棚拍质感。

强大功能背后的「技术底座」

LongCat-Image具备出色的跨语言图像编辑能力,通过共享 MM-DiT+Single-DiT 混合主干架构与VLM条件编码器,文生图与编辑能力相互辅助,继承文生图的出图质量并具备出色的指令遵循、一致性保持能力,在主流公开评测基准上达到第一梯队水平。文字生成专项能力上,覆盖全量通用规范汉字并在在商业海报、自然场景文字上都展现出极强的适用性。此外,通过精细化模型设计及多阶段训练策略优化,极大提升生成真实度、合理性并可支持消费级显卡高效推理。

文字生成基准测试

图像编辑基准测试性能比较

用 LongCat 记录你的「灵感瞬间」吧!

LongCat APP 体验入口:在「LongCat APP」中,你可以:输入一句话,生成高质量图像,或对生成图像进行迭代编辑、多轮生成,快速响应。

LongCat Web 端入口

您可以登录 https://longcat.ai/  ,体验高效的 AI 生图功能,或对生成图像进行多轮编辑。

iOS 用户可在 APPStore 中搜索 「LongCat」

更多玩法探索

基本上需要的功能齐全了

Antigravity+GemeniCLI 双额度
原生 Google_Search
原生大香蕉文生图 图生图

在 opencode 里可以和 Antigravity 里一样自动调用生图工具制作 / 修改项目需要的图片


📌 转载信息
转载时间:
2026/1/16 16:50:22

账号密码需要自己改下,搜索xxx改为你想设置的,首次加载网页的时候会有点慢,我没写成两个容器

注意:部署完别大量分享

# =============================================================================
# Z-Image-Turbo Gradio Web UI (文生图) - Gradio + ComfyUI 后端
# =============================================================================
# 部署命令: modal deploy z_image_turbo_gradio_deploy.py
# =============================================================================

import modal
import json
import os
import subprocess
from pathlib import Path

# =============================================================================
# 镜像配置 - 强制重建: 2025-12-02-v15 (参考wan2简洁风格)
# =============================================================================
comfy_image = (
    modal.Image.debian_slim(python_version="3.11")
    .apt_install("git", "wget", "curl")
    .pip_install(
        "fastapi[standard]==0.115.4",
        "comfy-cli==1.5.3",
        "requests==2.32.3",
        "huggingface_hub[hf_transfer]==0.34.4",
        "pillow",
        "websocket-client",
    )
    .env({"HF_HUB_ENABLE_HF_TRANSFER": "1"})
    .run_commands(
        "comfy --skip-prompt install --fast-deps --nvidia",
        # 更新到最新 master 代码
        "cd /root/comfy/ComfyUI && git fetch origin && git reset --hard origin/master",
        # 添加 z_image 到 DualCLIPLoader 类型列表 (nodes.py)
        "sed -i 's/\"hunyuan_video_15\"\\]/\"hunyuan_video_15\", \"z_image\"]/g' /root/comfy/ComfyUI/nodes.py",
        # 添加 Z_IMAGE 到 CLIPType 枚举 (sd.py)
        "sed -i 's/CHROMA = 15/CHROMA = 15\\n    Z_IMAGE = 16/g' /root/comfy/ComfyUI/comfy/sd.py",
        # 添加 z_image 处理逻辑到 load_dual_clip
        "sed -i 's/elif clip_type == CLIPType.HUNYUAN_IMAGE:/elif clip_type == CLIPType.Z_IMAGE:\\n            clip_target.clip = comfy.text_encoders.z_image.te(**llama_detect(clip_data))\\n            clip_target.tokenizer = comfy.text_encoders.z_image.ZImageTokenizer\\n        elif clip_type == CLIPType.HUNYUAN_IMAGE:/g' /root/comfy/ComfyUI/comfy/sd.py",
    )
    .pip_install("gradio==3.41.0")
)

app = modal.App(name="z-image-turbo-gradio", image=comfy_image)
vol = modal.Volume.from_name("z-image-turbo-gradio-cache", create_if_missing=True)


# =============================================================================
# 模型下载函数
# =============================================================================
def download_models():
    """下载 Z-Image-Turbo 模型"""
    from huggingface_hub import hf_hub_download

    hf_token = os.getenv("HF_TOKEN")
    repo_id = "Comfy-Org/z_image_turbo"

    print(f"? 从 {repo_id} 下载模型...")

    models = [
        {
            "filename": "split_files/diffusion_models/z_image_turbo_bf16.safetensors",
            "target_dir": "/root/comfy/ComfyUI/models/diffusion_models",
            "target_name": "z_image_turbo_bf16.safetensors",
            "desc": "主扩散模型"
        },
        {
            "filename": "split_files/text_encoders/qwen_3_4b.safetensors",
            "target_dir": "/root/comfy/ComfyUI/models/text_encoders",
            "target_name": "qwen_3_4b.safetensors",
            "desc": "Qwen3 文本编码器"
        },
        {
            "filename": "split_files/vae/ae.safetensors",
            "target_dir": "/root/comfy/ComfyUI/models/vae",
            "target_name": "ae.safetensors",
            "desc": "VAE 解码器"
        }
    ]

    for model in models:
        target_path = f"{model['target_dir']}/{model['target_name']}"

        if os.path.exists(target_path) or os.path.islink(target_path):
            print(f"   ✅ {model['desc']} 已存在,跳过")
            continue

        print(f"? 下载 {model['desc']}: {model['target_name']}...")

        cached_path = hf_hub_download(
            repo_id=repo_id,
            filename=model["filename"],
            cache_dir="/cache",
            token=hf_token
        )

        Path(model["target_dir"]).mkdir(parents=True, exist_ok=True)
        subprocess.run(f"ln -sf {cached_path} {target_path}", shell=True, check=True)
        print(f"   ✅ {model['desc']} 完成")

    print("? 所有模型准备就绪!")


# =============================================================================
# Gradio 应用
# =============================================================================
@app.function(
    max_containers=1,
    gpu="L40S",
    volumes={"/cache": vol},
    timeout=86400,
    scaledown_window=600,
)
@modal.web_server(7860, startup_timeout=600)
def serve():
    """Z-Image-Turbo Gradio Web UI"""

    # 下载模型
    download_models()

    # 启动 ComfyUI 后端 (端口 8188)
    print("? 启动 ComfyUI 后端...")
    subprocess.Popen(
        "comfy launch -- --listen 127.0.0.1 --port 8188",
        shell=True
    )

    # 等待 ComfyUI 启动
    import time
    time.sleep(30)

    # 写入 Gradio 脚本
    gradio_script = '''
import gradio as gr
import requests
import json
import uuid
import time
import os
import io
import threading
from PIL import Image
import websocket

COMFYUI_URL = "http://127.0.0.1:8188"

# 队列管理 - 使用文件持久化统计
STATS_FILE = "/cache/stats.json"
queue_lock = threading.Lock()
queue_count = 0

# 内存缓存,避免频繁读取文件
_stats_cache = {'total': 0, 'date': ''}

def get_today():
    """获取今天日期 (UTC+8)"""
    import datetime
    # 使用 UTC+8 时区
    return (datetime.datetime.utcnow() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d')

def load_stats():
    """从文件加载统计"""
    global _stats_cache
    try:
        if os.path.exists(STATS_FILE):
            with open(STATS_FILE, 'r') as f:
                data = json.load(f)
                _stats_cache['total'] = data.get('total_generated', 0)
                _stats_cache['date'] = data.get('date', '')
                print(f"[STATS] 加载统计: {_stats_cache}", flush=True)
                return _stats_cache['total'], _stats_cache['date']
    except Exception as e:
        print(f"[STATS] 加载失败: {e}", flush=True)
    return 0, ''

def save_stats(total):
    """保存统计到文件"""
    global _stats_cache
    try:
        today = get_today()
        _stats_cache = {'total': total, 'date': today}
        with open(STATS_FILE, 'w') as f:
            json.dump({'total_generated': total, 'date': today}, f)
            f.flush()
            os.fsync(f.fileno())  # 强制刷新到磁盘
        print(f"[STATS] 保存统计: total={total}, date={today}", flush=True)
    except Exception as e:
        print(f"[STATS] 保存失败: {e}", flush=True)

def get_total_generated():
    """获取今日生成总数"""
    global _stats_cache
    today = get_today()
    # 优先使用内存缓存
    if _stats_cache['date'] == today and _stats_cache['total'] > 0:
        return _stats_cache['total']
    # 否则从文件加载
    total, date = load_stats()
    if date != today:
        return 0  # 新的一天重置
    return total

def increment_total():
    """增加生成计数"""
    global _stats_cache
    today = get_today()
    # 使用内存缓存
    if _stats_cache['date'] == today:
        total = _stats_cache['total']
    else:
        total, date = load_stats()
        if date != today:
            total = 0
    total += 1
    save_stats(total)
    print(f"[STATS] 生成计数+1, 今日总计: {total}", flush=True)
    return total

def get_queue_status():
    """获取当前队列状态"""
    with queue_lock:
        if queue_count == 0:
            return "✅ 当前无排队,可立即生成"
        else:
            return f"⏳ 当前排队: {queue_count} 个任务等待中"

def get_stats():
    """获取统计信息"""
    with queue_lock:
        total = get_total_generated()
        return f"? 今日已生成: {total} 张 | 当前队列: {queue_count} 个"

# 启动时初始化加载统计
print("[STATS] 初始化加载统计...", flush=True)
load_stats()
print(f"[STATS] 初始化完成, 缓存: {_stats_cache}", flush=True)

# 分辨率选项
RESOLUTIONS = {
    "1:1 (1024x1024)": (1024, 1024),
    "16:9 (1024x576)": (1024, 576),
    "9:16 (576x1024)": (576, 1024),
    "4:3 (1024x768)": (1024, 768),
}

def create_workflow(prompt, width, height, steps, seed):
    """创建 ComfyUI 工作流"""
    return {
        "1": {
            "class_type": "UNETLoader",
            "inputs": {
                "unet_name": "z_image_turbo_bf16.safetensors",
                "weight_dtype": "default"
            }
        },
        "2": {
            "class_type": "DualCLIPLoader",
            "inputs": {
                "clip_name1": "qwen_3_4b.safetensors",
                "clip_name2": "qwen_3_4b.safetensors",
                "type": "z_image"
            }
        },
        "3": {
            "class_type": "VAELoader",
            "inputs": {
                "vae_name": "ae.safetensors"
            }
        },
        "4": {
            "class_type": "CLIPTextEncode",
            "inputs": {
                "text": prompt,
                "clip": ["2", 0]
            }
        },
        "6": {
            "class_type": "EmptyLatentImage",
            "inputs": {
                "width": width,
                "height": height,
                "batch_size": 1
            }
        },
        "7": {
            "class_type": "KSampler",
            "inputs": {
                "model": ["1", 0],
                "positive": ["4", 0],
                "negative": ["4", 0],
                "latent_image": ["6", 0],
                "seed": seed if seed != -1 else int(time.time() * 1000) % (2**32),
                "steps": steps,
                "cfg": 1.0,
                "sampler_name": "euler",
                "scheduler": "simple",
                "denoise": 1.0
            }
        },
        "8": {
            "class_type": "VAEDecode",
            "inputs": {
                "samples": ["7", 0],
                "vae": ["3", 0]
            }
        },
        "9": {
            "class_type": "SaveImage",
            "inputs": {
                "filename_prefix": "z_image_turbo",
                "images": ["8", 0]
            }
        }
    }

def generate_image(prompt, resolution, steps, seed):
    """生成图像"""
    global queue_count, total_generated

    if not prompt.strip():
        raise gr.Error("请输入提示词")

    # 加入队列
    with queue_lock:
        queue_count += 1
        my_position = queue_count

    print(f"[{time.strftime('%H:%M:%S')}] 任务加入队列,当前位置: {my_position}", flush=True)

    start_time = time.time()
    width, height = RESOLUTIONS[resolution]

    print(f"[{time.strftime('%H:%M:%S')}] 开始生成: {width}x{height}, {steps}步", flush=True)

    try:
        # 创建工作流
        workflow = create_workflow(prompt, width, height, int(steps), int(seed))

        # 生成客户端 ID
        client_id = str(uuid.uuid4())

        # 提交任务
        response = requests.post(
            f"{COMFYUI_URL}/prompt",
            json={"prompt": workflow, "client_id": client_id}
        )

        if response.status_code != 200:
            raise gr.Error(f"提交任务失败: {response.text}")

        prompt_id = response.json()["prompt_id"]
        print(f"[{time.strftime('%H:%M:%S')}] 任务已提交: {prompt_id}", flush=True)

        # 等待完成
        while True:
            time.sleep(0.5)
            history_response = requests.get(f"{COMFYUI_URL}/history/{prompt_id}")

            if history_response.status_code == 200:
                history = history_response.json()
                if prompt_id in history:
                    outputs = history[prompt_id].get("outputs", {})
                    if "9" in outputs and "images" in outputs["9"]:
                        image_info = outputs["9"]["images"][0]
                        filename = image_info["filename"]
                        subfolder = image_info.get("subfolder", "")

                        # 获取图像
                        params = {"filename": filename, "subfolder": subfolder, "type": "output"}
                        img_response = requests.get(f"{COMFYUI_URL}/view", params=params)

                        if img_response.status_code == 200:
                            # 保存图像
                            image_dir = "/tmp/gradio_images"
                            os.makedirs(image_dir, exist_ok=True)
                            image_path = f"{image_dir}/{uuid.uuid4()}.png"

                            image = Image.open(io.BytesIO(img_response.content))
                            image.save(image_path)

                            elapsed = time.time() - start_time
                            print(f"[{time.strftime('%H:%M:%S')}] 生成完成! 耗时: {elapsed:.1f}秒", flush=True)

                            # 完成,减少队列并更新统计
                            with queue_lock:
                                queue_count -= 1
                            increment_total()

                            return image_path

            # 超时检查 (5分钟)
            if time.time() - start_time > 300:
                with queue_lock:
                    queue_count -= 1
                raise gr.Error("生成超时,请重试")

    except gr.Error:
        raise
    except Exception as e:
        # 出错,减少队列
        with queue_lock:
            queue_count -= 1
        elapsed = time.time() - start_time
        print(f"[{time.strftime('%H:%M:%S')}] 错误: {e}")
        raise gr.Error(f"生成失败 ({elapsed:.0f}秒): {str(e)[:200]}")

# 示例提示词
example_prompts = [
    ["一只可爱的橘猫在阳光下打盹"],
    ["赛博朋克风格的未来城市夜景"],
    ["中国水墨画风格的山水"],
    ["宇航员在月球上骑自行车"],
]

# CSS - 参考 wan2 简洁风格
custom_css = """
html, body {
    background: linear-gradient(135deg, #f5f7fa 0%, #e4e8ec 100%) !important;
    min-height: 100vh !important;
}
.gradio-container {
    background: transparent !important;
}
h1, h2, h3 {
    background: linear-gradient(90deg, #10b981, #3b82f6);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
/* 圆角样式 */
.gr-button, .gr-input, .gr-textbox textarea, .gr-box {
    border-radius: 8px !important;
}
.gr-image {
    border-radius: 12px !important;
    background: #fff !important;
}
"""

with gr.Blocks(css=custom_css, title="Z-Image-Turbo") as demo:
    gr.Markdown("# ? Z-Image-Turbo AI 图像生成")
    gr.Markdown("**文生图 (T2I) | Turbo 快速生成 | Powered by Z-Image**")

    # 队列状态显示
    with gr.Row():
        queue_status = gr.Markdown(value=get_queue_status())
        refresh_btn = gr.Button("? 刷新状态", scale=0)

    with gr.Row():
        stats_display = gr.Markdown(value=get_stats())

    with gr.Row():
        with gr.Column():
            prompt = gr.Textbox(
                label="提示词",
                lines=5,
                value="",
                placeholder="请输入您想要生成的图像描述..."
            )

            gr.Markdown("### ? 提示词示例 (点击使用)")
            gr.Examples(
                examples=example_prompts,
                inputs=prompt,
                label=""
            )

            with gr.Accordion("⚙️ 高级设置", open=False):
                resolution = gr.Dropdown(
                    choices=list(RESOLUTIONS.keys()),
                    value="1:1 (1024x1024)",
                    label="分辨率"
                )
                steps = gr.Slider(
                    minimum=4,
                    maximum=20,
                    value=4,
                    step=1,
                    label="采样步数"
                )
                seed = gr.Number(value=-1, label="种子 (-1 为随机)")

            gr.Markdown("? **推荐设置**: 4-8步即可获得高质量图像")
            btn = gr.Button("✨ 生成图像", variant="primary")

        with gr.Column():
            output = gr.Image(label="生成结果", type="filepath")

    # 刷新状态按钮 - 不走队列,立即执行
    def refresh_status():
        return get_queue_status(), get_stats()

    refresh_btn.click(
        refresh_status,
        outputs=[queue_status, stats_display],
        queue=False,  # 不走队列,避免等待
        api_name=False  # 不创建 API 端点
    )

    # 生成按钮 - 生成后自动刷新状态
    def generate_and_refresh(prompt, resolution, steps, seed):
        result = generate_image(prompt, resolution, steps, seed)
        return result, get_queue_status(), get_stats()

    btn.click(generate_and_refresh, [prompt, resolution, steps, seed], [output, queue_status, stats_display])

print("? 启动 Gradio 界面...")
demo.launch(
    server_name="0.0.0.0",
    server_port=7860,
    share=False,
    auth=("xxx", "xxx"), // 账号密码自己改下
    allowed_paths=["/tmp/gradio_images", "/tmp/gradio", "/tmp"]
)

import time
while True:
    time.sleep(1)
'''

    script_path = "/tmp/gradio_app.py"
    with open(script_path, "w") as f:
        f.write(gradio_script)

    subprocess.Popen(["python", script_path])


# =============================================================================
# 本地入口
# =============================================================================
@app.local_entrypoint()
def main():
    print("=" * 60)
    print("Z-Image-Turbo Gradio Web UI")
    print("=" * 60)
    print("\n? 模型: Comfy-Org/z_image_turbo")
    print("\n? GPU: L40S")
    print("\n? 特点:")
    print("   - Gradio 前端界面")
    print("   - ComfyUI 后端推理")
    print("   - 支持多种分辨率")
    print("   - 4-20步快速生成")
    print("\n? 部署命令: modal deploy z_image_turbo_gradio_deploy.py")
    print("=" * 60)

【MODAL】发个简洁版的modal z-image-turbo 部署脚本