i1:一份「完全开源」的强文生图配方

i1 生成样例
Fig. 1 — i1-3B 在 1024 分辨率下的生成样例(来自官方项目页)。i1 的主张是:强文生图能力**不需要**新架构、专有数据或重度工程,只要把现有设计空间**仔细探索一遍**即可。

ℹ️ 这是一篇「实证调查 + 配方」型论文,不是「新方法」论文。 它的贡献不在某个新公式,而在 300+ 个单变量控制实验把文生图扩散模型的设计选择逐个消融、给出 10 条 finding,并据此训出一个完全开源(weights + data + code + recipe)的 3B 模型 i1。本文按精读 5 段骨架展开,把每条结论尽量落到论文图表与仓库代码(JAX 实现)的具体行号上。

1. 出发点 (Motivation)

过去几年,文生图(text-to-image, T2I)扩散模型一路狂飙,但很难把进步归因到具体的建模/数据选择上。论文开篇点出两个病根[§1]:

  1. 领先模型不公开训练数据与完整配方。即使放出权重(FLUX.1、HiDream、Qwen-Image…),训练数据来源、规模、混合比例几乎都是黑箱,导致无法做受控分析和可靠的后续工作。
  2. 领先模型很少给出彻底的消融。一个 recipe 往往把架构、训练、数据上几十个决策捆绑在一起发布,没法把某个提升归因到某个具体因子。结果是:到今天,连「用单个文本编码器还是多个文本编码器」这种基础问题,社区都没有共识。

完全开源(weights + data + code)的模型虽然存在(BLIP3o、PixNerd、DeCo…),却显著弱于领先模型——此前最强的完全开源模型在五个 benchmark 上比 i1 平均低 29.5 个百分点[§Abstract]。

i1 的立场因此是:社区需要把强模型当成「可检视的科学对象」,而不是不透明的端点。做法是——

i1 高层配方流程图
Fig. 2(论文 Fig. 4)— i1 最终配方的高层示意。训练侧:6 真实 + 3 合成 + 2 文字渲染数据集**等权重**混合 → FLUX.2 VAE 编码 → 用 Qwen3-VL-30B-A3B 生成**长合成 caption** → T5Gemma-2B 文本编码器 + **2 个 transformer block 的大 adapter** → 双流 LightningDiT 骨干(+dual-stream +long-skip +no-AdaLN +norm 设计)预测 velocity。采样侧:输入 prompt 先经 Qwen3-30B-A3B **扩写**再喂入。注意:i1 几乎不引入新模块,全是「选对 + 微调标准组件」。

一句话动机:与其再发一个调好的黑箱,不如把设计空间一个个钉死,并把整套东西开源,让后续研究能站在一个可复现、可归因的强 baseline 上。

2. 方法 (Method)

i1 的「方法」= 一个标准的 flow-matching 扩散 transformer + 一组被实验筛选出来的设计选择。下面按「训练目标 → 骨干 → 文本/噪声条件 → 数据」拆开,每块都给数学 + 代码。

2.1 训练目标:rectified flow(velocity 预测)

i1 用 flow matching / rectified flow 训练。核心思想:在噪声 \(x_0\sim\mathcal N(0,I)\) 和真实图(的 VAE latent)\(x_1\) 之间走一条直线,让网络去预测这条直线的「速度」。

定义时间 \(t\in[0,1]\),插值点与目标速度为:

\[x_t = (1-t)\,x_0 + t\,x_1, \qquad u_t = x_1 - x_0\]

—— 翻译:$x_t$ 是「噪声到真图」直线上的一个中间点($t$ 越大越接近真图);目标速度 $u_t$ 就是这条直线的方向(终点减起点),是个**常向量**,与 $t$ 无关。网络的任务就是:看到带噪的 $x_t$ 和时间 $t$,猜出这个 $u_t$。

训练损失就是预测速度 \(v_\theta\) 与目标速度的均方误差:

\[\mathcal L = \mathbb E_{x_0,x_1,t}\big\| v_\theta(x_t, t, c) - u_t \big\|_2^2\]

—— 翻译:$c$ 是文本条件。损失逼网络在每个噪声水平上都指对方向;采样时只要从纯噪声出发,沿网络给出的速度一步步积分(Euler)到 $t=1$,就得到一张图。

时间 \(t\) 不是均匀采样,而是 logit-normal(对 sigmoid 取正态),让训练更关注中间噪声水平。代码把上面三件事(采 \(t\)、造 \(x_t\)、算 \(u_t\))写得和公式一一对应:

repo/jax/diffusion/rectified_flow.py:L33-L70 — 采样 logit-normal 时间 + 构造 flow matching 训练输入

def sample_times(rng, batch_size, cfg, dtype=jnp.float32):
    if cfg.use_lognorm:
        rng, normal_key = jax.random.split(rng)
        normal_samples = cfg.lognorm_mu + cfg.lognorm_sigma * jax.random.normal(
            normal_key, (batch_size,), dtype=dtype)
        t = jax.nn.sigmoid(normal_samples)          # logit-normal: sigmoid(N(mu,sigma))
    else:
        t = jax.random.uniform(uniform_key, (batch_size,), dtype=dtype)
    ...
    return t

def prepare_rectified_flow_inputs(latents, noise_key, time_key, cfg):
    x1 = latents
    x0 = jax.random.normal(noise_key, latents.shape, dtype=latents.dtype)   # 噪声
    t  = sample_times(time_key, latents.shape[0], cfg, dtype=latents.dtype)
    t_expanded = _broadcast_t(t, latents.shape)
    xt = (1.0 - t_expanded) * x0 + t_expanded * x1   # x_t = (1-t)x0 + t x1
    ut = x1 - x0                                       # u_t = x1 - x0
    return xt, ut, t.astype(latents.dtype)

训练循环里就是一行 velocity-MSE:

repo/jax/training/main.py:L567-L638 — 调用上面构造输入、前向、算 velocity MSE 损失

xt, ut, t = rectified_flow.prepare_rectified_flow_inputs(
    latents, rng_noise_local, rng_timestep_local, rectified_flow_cfg)
model_latents, timesteps, target = xt, t, ut
...
model_output = _dit_forward(params, model_latents_mp, timesteps_mp,
                            encoder_hidden_states_mp, mask_mp, rng_dp, rng_dt)
...
velocity_pred   = _to_velocity(model_output_f32, model_latents_f32, timesteps_f32)
loss_mse = jnp.mean((velocity_pred - velocity_target) ** 2)   # 就是 ||v - u||^2

直觉版:把「去噪」想成在一团雾(噪声)和一张清晰照片之间拉一条直线。网络站在直线上某点,被要求指出「往清晰那头走的方向」。训练就是反复纠正它指的方向;生图就是从雾出发顺着它指的方向走到底。

2.2 骨干:双流 MMDiT + 长跳连接(long skip)

双流(dual-stream)MMDiT 指:图像 token 和文本 token 拼成一个长序列做联合注意力,但两条「流」用各自独立的 QKV/输出投影和 MLP 权重(图像一套、文本一套)。这与单流(共享权重)、cross-attention(文本只通过 cross-attn 注入)相对。论文实验(Fig. 12)显示双流在「性能/参数」权衡上最好(Finding 5)。

代码里这点非常直白——注意力模块为两条流各开一套 qkv/proj

repo/jax/models/dual_stream_backbone.py:L105-L118 — 双流:图像/文本各一套 QKV 与输出投影

self.qkv_image = nn.Dense(3 * self.hidden_size, use_bias=True, name="qkv_image")
self.qkv_text  = nn.Dense(3 * self.hidden_size, use_bias=True, name="qkv_text")
...
self.out_image = nn.Dense(self.hidden_size, use_bias=True, name="proj_image")
self.out_text  = nn.Dense(self.hidden_size, use_bias=True, name="proj_text")

注意力本身仍是全序列联合:把图像/文本的 Q、K、V 沿序列维拼起来一起算 softmax,让图文充分交互:

repo/jax/models/dual_stream_backbone.py:L161-L176 — 拼接图文 QKV 做联合注意力

q = jnp.concatenate([q_image, q_text], axis=2)
k = jnp.concatenate([k_image, k_text], axis=2)
v = jnp.concatenate([v_image, v_text], axis=2)
attn_logits = jnp.einsum("bhqd,bhkd->bhqk", q * self.scale, k).astype(jnp.float32)
...
attn = nn.softmax(attn_logits, axis=-1).astype(q.dtype)
out  = jnp.einsum("bhqk,bhkd->bhqd", attn, v)

长跳连接(long skip) 来自 U-ViT:把前半段 block 的输出缓存起来,后半段对称地把它们拼回来(concat 后过一个线性层降维)。这是个老设计,但现代 T2I 很少用;论文 Fig. 11 显示它能稳定改善「性能/参数」权衡(Finding 4)。实现是 U 形的 in/mid/out 三段:

repo/jax/models/dual_stream_backbone.py:L604-L640 — long skip 的 U 形执行:in_blocks 压栈、out_blocks 出栈

if cfg.use_long_skip:
    skips = []
    for block in self.in_blocks:                 # 前半段:每层输出压栈
        image_tokens, text_tokens = block(image_tokens, text_tokens, cond, ...)
        skips.append((image_tokens, text_tokens))
    image_tokens, text_tokens = self.mid_block(image_tokens, text_tokens, cond, ...)
    for block in self.out_blocks:                # 后半段:弹栈,作为 skip 拼回
        image_tokens, text_tokens = block(image_tokens, text_tokens, cond, ...,
                                          skips.pop())

而 out_blocks 里的拼接 + 降维(skip_linearconcat([x, skip]) 投回 hidden_size):

repo/jax/models/dual_stream_backbone.py:L227-L243 — skip 拼接后用线性层降回原维度

skip_image, skip_text = skip
skip_linear_image = nn.Dense(self.hidden_size, ...)   # concat -> hidden_size
skip_linear_text  = nn.Dense(self.hidden_size, ...)
image_tokens = skip_linear_image(jnp.concatenate([image_tokens, skip_image], axis=-1))
text_tokens  = skip_linear_text(jnp.concatenate([text_tokens,  skip_text],  axis=-1))
i1 整体架构
Fig. 3(论文 Fig. 21a)— i1 整体架构。caption 经 T5Gemma-2B + **2 个 transformer block 的大 adapter**;图像 latent 经 patch embed + **sinusoidal 位置编码**(同时还用 RoPE);中间是 N 组 **不带 AdaLN** 的 MMDiT attention/FFN block,外面套一圈**长跳连接**;最后 RMS norm + linear 输出 velocity。

2.3 文本/噪声条件:单编码器 + 大 adapter,砍掉 AdaLN

这是 i1 最有意思的两条发现。

(a) 用「单个强编码器 + 更大 adapter」替代「多文本编码器」(Finding 2)。 很多模型(SD3、HiDream)拼接多个文本编码器(CLIP+T5+LLM)的特征。i1 做了一个关键消融(Table 3):把 同一个 T5Gemma-2B 的特征复制两份——用两个独立 adapter 时 LongText 0.211→0.309 明显涨,用共享 adapter 时几乎不动。这说明「多编码器」的增益主要来自多出来的 adapter 参数,而非不同编码器的多样特征。于是 i1 干脆用单编码器配一个更大的 transformer adapter(从 2.6M 参数的 MLP 换成 17.2M 参数/block 的 transformer),用极小的参数代价、且不增加文本序列长度(省显存/算力)就拿到同等增益。

adapter 是个标准的小 transformer(attention + MLP + 残差),还顺手做了整条 caption 级别的 dropout 给 CFG 用:

repo/jax/models/components.py:L188-L211 — 大 transformer adapter 的一个 block(投影→若干层 attn+MLP 残差)

def _apply_connector(x, suffix):
    x = nn.Dense(self.hidden_size, **inits, name=f"connector_in{suffix}")(x)  # 投到骨干维度
    for block_idx in range(self.num_blocks):                                  # i1 用 2 个 block
        norm1 = norm_cls(self.hidden_size, ...); norm2 = norm_cls(self.hidden_size, ...)
        attn  = base.Attention(self.hidden_size, self.num_heads, ...)
        mlp   = base.SwiGLUFFN(self.hidden_size, int(2/3*mlp_hidden), ...)
        attn_out = attn(norm1(x), None, not train)
        x = x + attn_out                 # 残差
        x = x + mlp(norm2(x))            # 残差
    return x

(b) 砍掉 AdaLN(Finding 3)。 AdaLN(Adaptive LayerNorm)是 DiT 的标配:从「时间步嵌入 + pooled 文本嵌入」线性投影出每层的 scale/shift/gate。它参数巨大(在 cross-attn baseline 上占 0.89B→0.66B 中的 0.23B)。论文发现:在用了大 adapter 后,完全去掉 AdaLN 几乎不掉点(Table 4),于是 i1 直接不用 AdaLN——更省参数。代码里这是一个 use_adaln=False 的分支,block 退化成纯 pre-norm transformer(norm→attn→残差→norm→MLP→残差),不再有 timestep/pooled-text 调制:

repo/jax/models/dual_stream_backbone.py:L272-L289 — use_adaln=False 时 block 退化为标准残差,无任何 timestep 调制

if not self.use_adaln:
    image_attn, text_attn = attn(norm1_image(image_tokens), norm1_text(text_tokens), ...)
    image_tokens = image_tokens + (norm3(image_attn) if norm3 is not None else image_attn)
    text_tokens  = text_tokens  + (norm3(text_attn)  if norm3 is not None else text_attn)
    image_mlp_out = mlp_image(norm2_image(image_tokens))
    text_mlp_out  = mlp_text(norm2_text(text_tokens))
    image_tokens = image_tokens + (norm4(image_mlp_out) if norm4 is not None else image_mlp_out)
    text_tokens  = text_tokens  + (norm4(text_mlp_out)  if norm4 is not None else text_mlp_out)
    return image_tokens, text_tokens

⚠️ 代码 vs 论文的一个细节:虽然 AdaLN 被砍,timestep 信息并没有完全消失——_dit_forward 里仍把 t_embedder(t) 加到 pooled 文本嵌入上得到 condcond = t_emb + pooled,见 dual_stream_backbone.py:L588)。只是当 use_adaln=False 时,这个 cond 在 block 内部不被使用(上面分支根本没引用 cond)。也就是说 i1 是真正的 noise-unconditional block——与论文「removing noise conditioning only minimally affects performance for flow matching」的引用(Sun et al. 2025)一致。

文本编码器对比
Fig. 4(论文 Fig. 8)— 不同文本编码器的下游 T2I 表现。编码器-解码器型的 **T5Gemma 系**整体最强,超过解码器型 LLM(Qwen3)、VLM(Qwen3-VL)和 CLIP 型(FG-CLIP 2)。还发现:指令微调影响很小、更大的编码器不一定更好(T5Gemma-2B ≳ T5Gemma-9B)。i1 据此选 T5Gemma-2B(Finding 1)。
更大 adapter 的增益
Fig. 5(论文 Fig. 10)— 把 adapter 从 MLP 换成 1/2/3 个 transformer block,在 cross-attn/单流/双流三种骨干上**一致提升**;超过 2 个 block 后收益变得边际。i1 取 2 个 block(Finding 2)。

2.4 数据:长 caption + 推理扩写、等权重混合

(a) 训长 caption、推理扩写短 prompt(Finding 7)。 只用长合成 caption 训练 → 在长 prompt(DPG/LongText)上强,但在短 prompt(GenEval)上崩(GenEval 0.17)。原因是训练/推理的 prompt 长度分布不匹配。解法不是去训短 caption,而是推理时用 LLM(Qwen3-4B)把短 prompt 扩写成长段落,对齐训练分布——GenEval 直接回到 0.73(Table 5)。扩写用的 meta-prompt 很朴素:

"I have a short text-to-image prompt {prompt}. Please expand it into a descriptive paragraph, while making sure the generated image still clearly includes all the items mentioned in the original prompt. ..."

训练 caption 则统一用 Qwen3-VL-30B-A3B 生成,prompt 就是「Describe the image in detail using one paragraph.」:

repo/jax/data_processing/synthetic_captioning/caption.py:L141 — 长合成 caption 的生成 prompt

return img, stem, "Describe the image in detail using one paragraph."

这条 finding 反直觉但很实用:训练分布 > 迎合测试分布。与其为短 prompt 训一个弱模型,不如训一个强的长 prompt 模型,再在推理侧把短 prompt「拉长」去够它。

(b) 各数据集等权重(Finding 8)。 原始语料严重不均衡(YFCC 占 168M 里的 98M),naive 混合等于给少数大数据集巨大权重。i1 借鉴 VLM 训练里「给每个来源的数据量设上限」的做法,对每个数据集的采样权重设阈值;实验(Fig. 9 / threshold 图)发现阈值取到让所有数据集等权重(counting repetitions,即按「采样次数」而非「唯一图像数」算)时整体最好。配置里就是所有数据集权重都填 1

repo/jax/configs/i1_training/256_resolution.py:L58-L73 — 11 个数据集权重全部为 1(等权重)

path_and_count = [
    ('gs://path/to/yfcc/tfrecord', 1),
    ('gs://path/to/imagenet22k/tfrecord', 1),
    ('gs://path/to/rendered_text/tfrecord', 1),
    ('gs://path/to/fluxreason/tfrecord', 1),
    ('gs://path/to/textatlas/tfrecord', 1),
    ('gs://path/to/pexels/tfrecord', 1),
    ... # 共 11 个,全 1
]
sum_count = sum([item[1] for item in path_and_count])
path_and_count = [(item[0], float(item[1])/float(sum_count)) for item in path_and_count]

整份 i1 配方在 256 配置的 model_kwargs 里一目了然——长跳、transformer adapter(2 block)、不要 AdaLN、sinusoidal+RoPE、sandwich norm:

repo/jax/configs/i1_training/256_resolution.py:L22-L37 — i1 最终建模配方(每个 flag 对应一条 finding)

config.model_kwargs = mlc.ConfigDict(dict(
    use_long_skip=True,                       # Finding 4
    text_encoder_adapter_type="transformer",  # Finding 2
    text_encoder_adapter_num_blocks=2,         # Finding 2(2 个 block 即可)
    use_adaln=False,                           # Finding 3(砍掉 AdaLN)
    position_embedding="sinusoidal_and_rope",  # 附录 C.1 消融
    use_sandwich_norm=True,
    repeat_text_emb=False,
))
config.backbone = "dual_stream"               # Finding 5
config.text_encoder_type = "T5Gemma"          # Finding 1

3. 实验结果 (Results)

3.1 主结果:五个 benchmark 上压过更大的开源模型

最终 i1-3B 在 1024 分辨率评测(Table 8),与领先系统对比的硬数字:

模型 参数 GenEval DPG PRISM CVTG-2K LongText
i1(ours) 3B 0.84 86.73 70.1 0.8531 0.922
FLUX.1 [Dev](仅权重) 12B 0.66 83.84 65.1 0.4965 0.607
HiDream-I1-Full(仅权重) 17B 0.83 85.89 66.1 0.7738 0.543
Lumina-Image 2.0(仅权重) 3B 0.73 87.20 63.5 0.1577 0.088
BLIP3o-N-G-T(完全开源,此前最强) 3B 0.86 79.77 56.8 0.3330 0.153
Qwen-Image(仅权重,参照天花板) 20B 0.87 88.32 73.9 0.8288 0.943

要点:

头条结果柱状图
Fig. 6(论文 Fig. 1 同源)— 各模型在五 benchmark 上的平均得分。i1(3B,红)在「完全开源」阵营里断层第一,并越过多个体量大数倍的「仅权重」模型。

3.2 受控实验里的 10 条 finding(论文真正的「结果」)

论文的核心产出是 10 条可复用结论:

  1. 编码器-解码器(T5Gemma)和解码器型 LLM/VLM 都能当好文本编码器;i1 选 T5Gemma-2B。
  2. 「多文本编码器」的增益可由「单编码器 + 更大 adapter」等价获得,且更省显存/算力。
  3. AdaLN(对 pooled 文本/timestep 的调制)收益边际,可整块砍掉。
  4. 长跳连接改善「性能/参数」权衡。
  5. 双流骨干在三类骨干里「性能/参数」最优。
  6. 合成 captioner 的选择对下游影响很大
  7. 训长 caption > 训短 caption;短 prompt 的劣势靠推理扩写补回。
  8. 等权重混合数据集是简单又强的默认。
  9. 数据多样时,重复训练数据只带来边际下降(4.4M 唯一图像 ≈ 88.1M,见 Table 7)——少图多 epoch 也行。
  10. 强高清生成不需要高清数据覆盖到低清预训练的全部广度(只用 real 或只用 synthetic 在 512 训练,LongText 增益与全量相当)。
长跳连接 scaling
Fig. 7(论文 Fig. 11)— 在多个模型宽度下,**带长跳**(蓝)一致优于**不带长跳**(橙),DPG/PRISM/LongText 三指标皆然 → Finding 4。
骨干家族对比
Fig. 8(论文 Fig. 12)— cross-attn / 单流 / 双流三类骨干随参数量的表现。双流(绿)在性能/参数权衡上最优 → Finding 5。
等权重阈值
Fig. 9(论文 Fig. 18)— 给每个数据集的采样权重设上限阈值。阈值降到 1.2M(≈ 所有数据集等权重)时整体最好 → Finding 8。
合成 captioner 对比
Fig. 10(论文 Fig. 13)— 用 5 种不同 VLM 生成训练 caption(仅在 ImageNet-22K 上),下游 T2I 表现差异显著 → Finding 6。i1 用 Qwen3-VL-30B-A3B。

3.3 训练规模

4. 实现细节 (Implementation)

交叉阅读 JAX 仓库后值得记下的实现细节(均带行号):

  1. velocity MSE 在 float32 里算以稳数值,即使前向用 bf16:model_output_f32 = model_output.astype(jnp.float32) 后再算 loss(repo/jax/training/main.py:L627-L637)。
  2. i1-3B 的实际尺寸是 DiT-XL_2016:hidden=2016、depth=29、heads=28、patch=2(repo/jax/models/dual_stream_backbone.py:L687 + configs/i1_training/256_resolution.py:L18-L21)。注意命名仍叫 "XL" 但宽度被加到 2016 才凑到 3B。
  3. long skip 的 U 形是按 depth 对半切num_in_blocks = depth // 2,in/mid/out 三段;out_block 用 use_skip=True 触发 skip_lineardual_stream_backbone.py:L453-L505)。depth=29 是奇数,正好 14 in + 1 mid + 14 out。
  4. 位置编码是「双保险」:同时用可学习的 sinusoidal pos_embed(加到 patch token 上) Multimodal-RoPE(作用在 Q/K 上)。position_embedding="sinusoidal_and_rope" 两者都建(dual_stream_backbone.py:L419-L448, L536-L546)。
  5. 高清微调靠 RoPE 索引插值 + sinusoidal 插值,而非重训:image_resolution != 256 时走 _get_interpolated_pos_embed,且 RoPE 的 image_scale = 256.0 / cfg.image_resolution 缩放空间轴(dual_stream_backbone.py:L371-L382, L441-L442)。
  6. pooled 文本嵌入是 mask 加权平均(不是简单 mean),再与 timestep 嵌入相加成 condpooled = einsum("bth,bt->bh", caption_emb, weights)/denom; cond = t_emb + pooleddual_stream_backbone.py:L581-L588)。在 use_adaln=False 时这个 cond 不参与 block 计算(见 §2.3 的代码-论文差异)。
  7. CFG 用「区间 CFG + Rescale CFG」组合:先按 cfg_interval_start 决定哪些 \(t\) 施加 guidance,再做 Lin et al. 2024 的方差 rescale(guided = cond + mask*(scale-1)*(cond-uncond),随后按 std_c/std_g 重缩放),推理 CFG scale=12、rescale 强度=1(repo/jax/diffusion/inference_pipeline.py:L290-L308)。
  8. 采样器是 Euler + 常步长,时间网格按 inference_timestep_shift 做 shift(把更多步花在高噪声段),对应 diffrax 的 dfx.Euler()inference_pipeline.py:L245-L259)。
  9. CFG dropout 在 adapter 里做:训练时按 drop_text_prob 把整条 caption 换成可学习的 learnable_null_captioncomponents.py:L253-L267)——空条件不是全 0,而是学出来的。
  10. **多文本编码器是「序列维拼接 + 各自 adapter」**而非 embedding 维拼接,避免 pad 到统一长度(components.py:L213-L251,i1 最终未用多编码器,但代码保留)。

论文 vs 代码:未发现实质性矛盾。 仓库的 256_resolution.py 配方与论文 §6/Fig. 21 的描述逐项一致(双流、long skip、no-AdaLN、transformer adapter×2、T5Gemma-2B、等权重)。唯一需要澄清的是 §2.3 提到的 cond:代码无条件构造它,但在 i1 的 use_adaln=False 路径下不消费——属于「为支持消融而保留的死代码路径」,不影响结论。另外配置里的数据路径是占位 gs://path/to/...(需自填),数据本身在 HuggingFace 开源。

5. 批判性总结 (Critical Summary)

真正的贡献:i1 不是「又一个更强的模型」,而是一份带 700K TPU 小时背书的、可复现的设计空间地图。它把社区里若干含糊的「常识」做了硬消融并钉死了答案(多编码器其实是 adapter 在起作用、AdaLN 可砍、长跳值得用、等权重是强默认、训长 caption + 推理扩写)。对开源社区,这比一个黑箱 SOTA 更有长期价值——它把「完全开源」阵营的天花板一次性抬高了 ~30 个点。

值得警惕的弱点(部分作者自己承认)

  1. 评测几乎全是自动 benchmark,缺人类偏好。作者坦言 i1 在整体视觉质量上仍明显逊于 Qwen-Image 这类领先模型(附录有 failure case)。而它领先最多的恰恰是 CVTG-2K/LongText 这类文字渲染指标——这类指标对「训练数据里塞了多少文字渲染图」高度敏感,部分领先可能是数据配比红利,而非建模优越性。换句话说,「平均 +29.5 点」里文字渲染贡献了很大一块,看 DPG(通用跟随)差距其实没那么悬殊。
  2. 所有结论都在 ≤3B 规模上得出。作者明确说不知道这些 finding 在更大规模是否成立。尤其「AdaLN 可砍」「等权重最好」「重复数据没事」这几条,很可能是容量/数据规模受限下的现象,scale 上去后未必继续成立。
  3. GenEval 被边缘化处理得略方便。i1 的 GenEval(0.84)并不比对手突出,论文用「GenEval 不可靠 + 别人靠 BLIP3o-60K 刷分」来淡化它。这个论证本身有道理,但也恰好回避了 i1 在这个老牌组合性 benchmark 上不占优的事实。
  4. 设计空间只扫了一个子集。multi-aspect-ratio 训练、数据过滤、LLM 与 DiT 的深度融合(text encoding)、RL 对齐(DPO/GRPO 这类,参见 krea-2-2026flow-opd-2026)都被显式留作 future work。所以 i1 是「在一条固定主干上的局部最优探索」,不是全局配方。
  5. 「单变量、不累积」的实验范式有盲点。每次只改一个设计、在固定 baseline 上比较,干净但忽略了设计之间的交互——论文自己其实已经撞见一例:AdaLN 该不该砍,取决于 adapter 大小(小 MLP 时砍 AdaLN 涨点多,大 adapter 时几乎不动)。这说明这些 finding 之间并非正交,最终组合是否真的最优,单变量实验并不能保证。

一句话评价:把它当「文生图设计选择的实证手册 + 一个诚实的强开源 baseline」来用,价值很高;但别把那 10 条 finding 当成跨规模、跨主干都成立的物理定律——它们是「在 3B、在这条 LightningDiT 主干上、用这套数据」的局部真理。

📌 延伸阅读:同为「全栈开源/工程配方」型的 T2I 报告可对照 krea-2-2026(更偏基建与对齐流水线)、sefi-image-2026qwen-image-2-2026;on-policy 蒸馏方向见 flow-opd-2026

讨论 / Comments

评论托管在本仓库的 GitHub Discussions, 需 GitHub 账号。