角色 Embedding 技术入门:AI 视频角色锁定的底层原理

面向工程师的技术入门:现代 AI 视频技术栈中角色 embedding 系统的架构、设计取舍、失败模式和未解决的开放问题。

·9 min read·technical

本文写给工程师研究员、ML 实践者、以及搭建或评估 AI 视频技术栈的开发者。如果你想要的是面向非技术读者的"为什么角色一致性重要"的总览,请从 完整指南开始。

这里我们讨论现代 AI 视频系统中角色 embedding 是如何工作的:架构、设计取舍、失败模式,以及尚未被很好解决的一些开放问题。

问题陈述

给定一个生成式视频模型 M 和一个角色 C,我们希望存在一种方法:对任何引用 C 的提示词序列 p_1, p_2, , p_n,生成的输出都保持 C 的身份。

最朴素的做法在每个提示词里加上角色描述行不通,因为扩散采样是随机的,而提示词描述的是类别(category)而非身份(identity)。每次生成都是从"匹配该描述的有效角色分布"里抽一次样;身份会在多次抽样间漂移。

我们需要的是一种把模型输出条件化到一个具体的、已学习好的身份上的机制,而不仅仅是条件化到一段描述上。

架构

一个现代角色一致性系统通常包含 6 个组件:

1. 特征抽取(Feature extraction)       — 从参考图产出身份 embedding
2. 存储(Storage)                       — 把 embedding 持久化并绑定 character_id
3. Negative prompt 合成                  — 基于漂移目录自动生成 negative_prompts
4. Conditioning 注入                     — 把 embedding 注入到模型 conditioning
5. 生成(Generation)                    — 用条件化模型做扩散采样
6. 一致性校验(Consistency verification)— 事后做相似度校验,必要时重生

下面逐一展开。

1. 特征抽取

角色上传时,对参考图跑多个专门模型:

将上述向量拼接(或通过 attention 融合)成一个高维角色 embedding e_C。总维度通常在 1500-3000 之间。

为什么用多个模型而不是一个?因为身份是多轴的,没有单一编码器能完整覆盖。人脸编码器擅长"是不是同一张脸",但对身体比例无感。体形解析器对面部细节无感。CLIP 擅长语义层面的外观,但会丢失精细身份。拼起来才能拿到正交覆盖。

取舍:抽取流水线越复杂,上传时算力开销越大(业内一些方案在 30-90 秒级)。对面向消费者的工具是可接受的。对高吞吐量场景,可以在上传时一次性预计算 embedding,生成时直接引用。

2. 存储

每个角色以 (character_id, embedding_vector, metadata) 形式存储。元数据包含:

存储一般用向量数据库(Pinecone、Qdrant、Weaviate)或自研的索引结构。查询要快亚 100ms因为每次生成都会触发。

对隐私敏感的部署,embedding 可以按租户密钥加密存储。抽取过程是单向函数(无法从 embedding 反推参考图),但对处理真实人物的系统而言,把 embedding 当作 PII(个人身份信息)对待是合理的默认值。

3. Negative prompt 合成

这是系统里非显然但工程量最大的部分。

业内的做法是维护一份常见漂移模式(drift mode)目录从大量生成里观察到的、可分类的失败类型。每个模式对应一段 negative_prompt 片段,用来抑制对应的失败。

目录里的一些示例:

漂移模式Negative prompt 片段
眼睛颜色漂移(棕 绿)"green eyes, hazel eyes"(参考为棕色时)
下颌线变窄"narrow jaw, weak chin, soft jawline"
发际线后退"high hairline, thinning hair, receding hairline"
肤色变暖"warm skin tone, golden complexion"(参考为冷色时)
不对称蔓延"asymmetric face, uneven features"
眼距漂移"wide-set eyes, close-set eyes"

建立这个目录需要标注数据。业内一些团队会从公开 AI 视频工具(Runway、Pika、Sora 等)的生成结果里采上万条样本,标注出现的具体漂移模式。聚类后通常能得到约 30 个不同模式,覆盖约 85% 的可观测漂移。

对每次生成,系统会:

  1. 检索该角色的参考属性
  2. 计算各属性的"反向值"(例如参考为深色眼睛,反向是浅色眼睛)
  3. 组装出该角色专属的 negative prompt,把相关漂移抑制项串起来

由此得到的 conditioning 信号比纯靠提示词的版本要强得多。

4. Conditioning 注入

不同的视频模型对 conditioning 的接入方式不同:

一般而言,API 级注入比基于参考图的方式有效得多,但多数公开 API 不开放这种深度。在公开 API 暴露的接口面上工作时,把强 negative prompt 和"通过参考图编码进去的 embedding"组合起来,能拿到大约 80-90% 的 API 级注入效果。

这也是为什么在不掌控底层模型的情况下,搭一层角色一致性仍然是有意义的公开 API 已经暴露的 conditioning 接口面上,仍有大量可挖掘的空间。

5. 生成

标准扩散采样,区别在于此时 conditioning 是以下几项的组合:

生成开销通常是普通生成的 1.0-1.2×,边际成本很小。

6. 一致性校验

生成完后,跑一个独立的身份模型(通常就是步骤 1 里那个人脸编码器)对输出做特征抽取。计算输出身份 embedding 与原参考 embedding 的余弦相似度(cosine similarity)。

阈值通常取 0.85。高于阈值即接受输出。低于阈值则触发重生,并提高 negative prompt 权重、加大 embedding 注入强度。

这层平均增加 5-10% 生成开销(多数镜头一遍过),但能挡住最严重的漂移,避免它们到达用户。

什么有效,什么仍困难

有效的部分:

仍困难的部分:

开放研究问题

如果你也在这个方向上做事,有几个值得解的问题:

  1. 形态变体下的身份不变量。什么样的可学习表示能既捕捉身份不变的面部结构,又允许任意状态变换?
  2. 采样过程中的实时漂移检测。当前的一致性校验都是事后的。能否在扩散过程中检测漂移并在采样中途纠正?
  3. 隐式 vs 显式身份的取舍。什么时候训一个小的 per-character LoRA 优于基于 embedding 的条件化?分界点在哪?
  4. 多角色交互建模。不仅锁住两个身份,还要让他们之间的关系动态在跨镜头中也保持一致,怎么做?
  5. 身份不确定性量化。当模型对身份不确定时,能否把这种不确定性输出出来,而不是产出一个自信的漂移结果?

如果你正在做上述任何一项并希望交流,Juying 团队真心感兴趣。欢迎联系。

给 builder 的实战建议

如果你打算自己给产品搭一层角色一致性,三条建议:

1. 从 negative prompt 目录开始。这是性价比最高的一招。不需要 API 级模型访问;negative prompt 是任何公开 API 都暴露的接口。花一周时间标 1000 条生成结果,就能拿到一个覆盖大多数漂移的目录。

2. 不要低估事后校验。加一个简单的"相似度 < 0.85 就重生"循环,能挡掉最差的 10% 失败,并显著提升观感质量。这是从 90/100 到 95/100 最便宜的一档提升。

3. 早点投资存储。把角色 embedding 当作持久化资产,是会复利的架构洞见。把对的原语建好一次,未来所有功能(风格锁、场景库、资产复用)都能自然延伸。

相关阅读

如果你也在做这一块、想聊聊info@juying.art