DAY 47 / PHASE 5 · 非 LLM 模态

图像生成工程

控制栈 · Prompt 反直觉 · 生成 Agent · Provenance

2026-06-26 · BigCat

文本 prompt 是最弱的控制旋钮;可控、可复现、可合规才是图像工程。

// WHY THIS MATTERS

大多数人对图像生成的认知停在「在 Midjourney 里写句咒语抽卡」。但当你要把生成图放进产品流水线——品牌一致的角色、固定构图的电商图、可批量复现的素材——抽卡立刻崩溃。图像模型和 LLM 是两套完全不同的工程学:扩散模型不是「听指令」,而是在条件分布里采样;文本 prompt 只是众多控制信号里最粗的一个。这一期不讲「扩散原理是什么」(那是概念课),讲已经会用工具的人怎么把不可控变可控:用 ControlNet/LoRA/IP-Adapter 分层叠加空间与风格控制、按扩散模型自己的规律写 prompt、把单次抽卡升级成「生成—评估—重绘」的 agentic loop、以及生产化绕不开的水印与版权 provenance 层。

// 01

控制栈:ControlNet / LoRA / IP-Adapter 怎么分层

论断:text prompt 控制不了构图与身份;空间结构交给 ControlNet,风格与主体交给 LoRA,参考图交给 IP-Adapter,三者正交叠加。

背景与原理

这三类工具作用在扩散过程的不同切面,不是互相替代而是叠加:

工程心法:先定结构(ControlNet),再定身份(LoRA),最后微调氛围(prompt + IP-Adapter)。把「想要什么」拆到对的控制通道上,而不是全堆进 text prompt。

扩散去噪循环 ──每一步同时接收多路条件──▶ ┌──────────────────────────────────────────────┐ │ text prompt ─┐ │ │ (CLIP 编码) │ 粗:主题/氛围 │ │ ▼ │ │ IP-Adapter ──▶ cross-attention ── 风格/人脸 │ │ (参考图) │ │ │ LoRA ──▶ UNet 权重增量 ── 角色/画风 │ │ │ │ │ ControlNet ─▶ UNet encoder 旁路 ─ 构图/骨架 │ │ (edge/depth/pose) ▲ 最强的空间锁定 │ └──────────────────────────────────────────────┘ 控制强度:ControlNet > LoRA > IP-Adapter > prompt

实战示例

# diffusers:ControlNet(姿态) + LoRA(角色) 叠加
from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel
cn = ControlNetModel.from_pretrained("...controlnet-openpose-sdxl")
pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", controlnet=cn)
pipe.load_lora_weights("./my_character.safetensors")  # 角色一致性

img = pipe(
    prompt="mychar, cinematic lighting, rooftop at dusk",
    image=pose_map,                 # openpose 骨架 → 锁定姿态
    controlnet_conditioning_scale=0.8,  # 别给 1.0,留余地
    guidance_scale=6.5, num_inference_steps=30,
    generator=torch.Generator().manual_seed(42),  # 可复现
).images[0]
失败模式:① 叠 3 个以上 ControlNet → 条件互相打架,出畸形;先单条件调通再加。② controlnet_conditioning_scale=1.0 把结构焊死,prompt 完全失效。③ LoRA rank 过大 + 数据少 → 过拟合,只会复刻训练图、不泛化。④ 忘了固定 seed,无法复现「上次那张好图」。
// 02

图像 Prompt:和 LLM 完全不同的规律

论断:扩散 prompt 不是「指令」而是「条件分布的坐标」;否定要走 negative 通道,CFG 决定听话程度,CLIP 只读前 77 token。

背景与原理

把 LLM 的 prompt 习惯搬到扩散模型上几乎全错。四条核心差异:

实战示例

# ❌ LLM 式(在扩散模型里几乎必翻车)
"Please generate a portrait. Make sure there is no blur,
 and don't include any text or watermark in the image."
# → 提到 blur/text/watermark 反而召唤它们;指令式废话占满 77 token

# ✅ 扩散式:正向只放「想要的」,排除走 negative
prompt = "portrait of a woman, soft window light, 85mm, \
          shallow depth of field, (sharp focus:1.2)"
negative_prompt = "blurry, text, watermark, extra fingers, \
                   lowres, deformed hands"
# guidance_scale=7  顺序:主体→光线→镜头→质量
失败模式:① 把负面诉求写进正向 prompt(最常见翻车)。② 堆几百词「质量咒语」,超 77 token 后半段被丢,自己还以为生效。③ CFG 拉到 15+ 求「更听话」,结果颜色烧穿、出油画感伪影。④ 跨模型抄 prompt:SD1.5 的咒语在 SDXL/Flux 上权重规律不同,要重调。
// 03

图像生成 Agent:把抽卡变成生成—评估—重绘循环

论断:单次生成是赌博;可靠产出来自 agentic loop——VLM 当评审,局部 inpaint 当修正,固定 seed 当版本控制。

背景与原理

生产场景不接受「跑十张挑一张」。把图像生成接进 agent loop,复用你已经熟的 harness 思路(Day 3):生成 → VLM 评估是否符合 brief → 不符合则对问题区域做 mask + inpaint 局部重绘 → 升采样定稿。关键是用一个多模态模型(Claude / GPT-4V)当 eval gate,把「人眼挑图」自动化成结构化判分。重绘只改坏的局部(手、文字、多余物体),而不是整张重抽——既省成本又保住已经对的部分。

┌─────────────────────────────────────────────┐ │ brief ──▶ ① text-to-image (seed=固定) │ │ │ │ │ ▼ │ │ ② VLM 评审 ──符合 brief?──┐ │ │ (Claude/GPT-4V) │ no │ │ │ yes ▼ │ │ │ ③ 定位坏区域 → mask │ │ │ ④ inpaint 局部重绘 │ │ │ │ (loop≤N) │ │ ▼ ◀───────────────┘ │ │ ⑤ upscale 升采样 → 定稿 │ │ │ │ 人工 gate:N 轮仍不过 → 升级人审,不无限重绘 │ └─────────────────────────────────────────────┘

实战示例

# VLM 当评审:结构化判分,驱动是否重绘
import anthropic
client = anthropic.Anthropic()

def critique(image_b64, brief):
    msg = client.messages.create(
        model="claude-opus-4-8", max_tokens=400,
        messages=[{"role":"user","content":[
            {"type":"image","source":{"type":"base64",
             "media_type":"image/png","data":image_b64}},
            {"type":"text","text":
             f"Brief: {brief}\n严格判分,返回 JSON:"
             '{"pass":bool,"issues":[...],"worst_region":"hands|text|..."}'}
        ]}])
    return msg.content[0].text   # → 解析后决定 inpaint 哪块

# loop:max_iters=3,超出转人工,避免无限重绘烧钱
失败模式:① VLM 也会幻觉——对生成图「脑补」出不存在的细节,判分需配一致性校验或多次投票。② 没有 max_iters 和人工 gate → 一张图反复重绘烧掉几美元。③ 每轮换 seed → 修一处坏另一处,永不收敛;inpaint 时锁住未 mask 区域。④ 把整图重抽当「修正」,丢掉上一轮已经对的部分。
// 04

水印与版权:生产化绕不开的 Provenance 层

论断:可见水印是装饰;真正的来源证明是 SynthID(鲁棒不可见水印)+ C2PA(密码学签名元数据)双层,且版权风险主要在训练数据侧。

背景与原理

把生成图发到产品里,合规问题立刻浮现,工程上分两层:

实战示例

# 给输出图签 C2PA Content Credentials(c2patool)
c2patool input.png \
  --manifest manifest.json \   # 声明:AI 生成 + 模型 + 时间
  --output signed.png

# manifest.json 关键字段
{
  "claim_generator": "my-pipeline/1.0",
  "assertions": [
    {"label": "c2pa.actions",
     "data": {"actions": [{"action": "c2pa.created",
              "digitalSourceType": "trainedAlgorithmicMedia"}]}}
  ]
}
# 双层:C2PA 签名(可剥离但可验)+ 平台侧 SynthID(鲁棒不可见)
失败模式:① 只靠 metadata/EXIF 水印——用户一次截图全没。② 以为「加了水印就免责」:版权问题在训练数据与风格复制侧,水印解决不了。③ 商用 LoRA 训练集混入受版权/隐私保护的人脸或作品,埋下下游法律雷。④ 误以为 C2PA 防篡改——它证明来源,不阻止剥离,必须配鲁棒水印。

// 综合实战 · 一条「可复现品牌素材」流水线

把四点串成一个能批量产出、风格统一、可追溯的素材工厂——这是抽卡和工程的分水岭:

  1. 身份层:用 20–40 张品牌素材训一个 LoRA(rank 16–32)锁住画风/角色,固定触发词。
  2. 结构层:每个版位准备 openpose / depth 图当 ControlNet 条件,conditioning_scale≈0.7,构图可复用、可微调。
  3. Prompt 层:正向只写「想要的」,质量与排除项进 negative;CFG 锁 6–7;全程固定 seed 表保证可复现。
  4. Agent 层:VLM 评审每张是否符合 brand brief,坏区域 inpaint 局部重绘,max_iters=3 后转人审。
  5. Provenance 层:定稿统一签 C2PA + 平台 SynthID;LoRA 训练集做版权审查留痕。

跑通这一套,你交付的不再是「几张好看的图」,而是一个参数化、可复现、可审计的生成系统——这正是图像工程与图像玩票的区别。

// ENGLISH GLOSSARY

ControlNet
注入空间条件(边缘/深度/骨架)的旁路网络,给扩散过程 pixel 级构图控制。
LoRA
低秩权重增量微调;几十张图即可固化一个风格或角色,文件小、靠触发词激活。
IP-Adapter
把参考图编码为 image prompt 注入 cross-attention,零训练迁移风格/人脸。
CFG (Classifier-Free Guidance)
条件与无条件预测的外推强度;决定模型「多听话」,过高会过饱和。
Negative Prompt
独立的排除通道;扩散模型靠它实现「否定」,而非在正向里写 don't。
Inpainting
对 mask 区域局部重绘,只改坏的部分、保住已对的部分,是图像 agent 的修正手段。
Seed
采样初始噪声的随机种子;固定 seed 才能复现同一张图,是图像版本控制的根。
SynthID
Google DeepMind 的鲁棒不可见水印,分布全图,扛截图/压缩/裁剪。
C2PA / Content Credentials
密码学签名的来源元数据标准;可验证可追溯,但可被剥离,需配鲁棒水印。
DreamBooth
用少量图把唯一标识符绑定到特定主体的个性化微调法,角色一致性的经典路线。

// 深入思考

LLM 的 prompt 是「指令」,扩散模型的 prompt 是「分布坐标」。这个差异的根源是训练目标的不同吗?
是。LLM 经 RLHF 对齐成「遵循指令」的助手,于是把 prompt 当命令解析,能理解否定、条件、元指令。扩散模型只学了「文本→图像」的条件概率,CLIP 把整段文本压成一个嵌入向量,没有「执行指令」的机制——它只是把你推向潜空间里某个区域。所以「don't」无效(模型只看到 hat 这个 token 把你推向有帽子的区域),所以顺序即权重(越靠前对嵌入贡献越大)。理解这点,就不会再把自然语言指令塞进扩散 prompt。
用 VLM 给生成图当评审,是否陷入「裁判和选手同源」的问题?两个都可能在同一处幻觉。
风险真实存在但可缓解。同源指生成与评估都基于相似的视觉先验,可能共享盲区(如都对手指数量不敏感)。缓解:① 评审用和生成不同家族的模型;② 对结构性硬约束(手指数、文字 OCR、物体计数)用专用检测器而非泛 VLM;③ 多次投票或要求 VLM 先定位坐标再判分,降低脑补。本质上这和 LLM-as-judge 的去偏是同一类问题——VLM 评审能挡住明显废品,但不能替代关键场景的人审。
ControlNet 给了 pixel 级控制,但控制越强、模型的创造性空间越小。这个 trade-off 的最优点在哪?
取决于任务的「确定性需求」。电商主图、UI 资产、需对齐版式的场景:高 conditioning_scale(0.8–1.0),牺牲多样性换可控。概念探索、moodboard:低 scale(0.3–0.5)或不用 ControlNet,让模型多发挥。实践上很少用 1.0——那等于把结构焊死、prompt 失效,模型退化成「填色工具」。更聪明的做法是分阶段:先低控制探方向,定稿阶段再上高控制锁结构。控制不是越多越好,是在对的阶段用对的强度
SynthID 这类鲁棒水印若被广泛部署,会不会催生「去水印」军备竞赛?工程上该怎么看它的有效性边界?
会,且已在发生。任何水印都是概率性而非密码学保证:足够激进的再生成(用另一个模型 img2img 重画)、强降质、对抗扰动都可能削弱它。所以工程定位要诚实——SynthID 解决的是「无意传播」和「平台侧批量检测」,不是防住蓄意攻击者。正确心态:把它当纵深防御的一层(配 C2PA 签名 + 平台政策 + 法律),而非银弹。它的价值在规模——DeepMind 称已水印超千亿件内容,让「默认可检测」成为生态常态,抬高滥用成本,而不是做到 100% 不可去除。
训练数据的版权风险无法靠水印解决。对个人创作者,怎么在能力和风险之间画线?
分级处理。低风险:用明确授权/CC0 数据训 LoRA、生成通用素材、复刻自己的作品风格。高风险:复刻在世艺术家的可识别画风、微调他人受版权作品、生成可能侵犯肖像权的真人脸。中间地带(如学习某种通用美学)法律仍在演化。务实建议:①商用前审查训练集来源并留痕(provenance 也是给自己的法律证据);②避开「能点名某位在世艺术家」的风格复制;③把 C2PA「AI 生成」声明当默认,主动透明而非藏。能力越强,越需要把合规当成工程的一等公民,而非事后补丁。

// 延伸阅读