File size: 7,125 Bytes
e545366
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# comfyui-anima-incontext

Anima (circlestone-labs, Cosmos-Predict2 2B DiT) 向けの
**参照画像条件付け**カスタムノード集。2 つの独立したストリームを持つ:

- **キャラストリーム (in-context)** — 参照画像のVAE latentをDiTの
  時間軸(T軸)に「クリーンフレーム」として連結し、shared
  self-attentionでキャラの見た目を参照させる。CLIP埋め込み型
  IP-Adapterと違い、参照はモデル自身のVAE latentのまま自己注意に
  入るため、髪飾り・服の柄・瞳などの細部が原理的に落ちない
  (OminiControl / IC-LoRA / UNO 系のアプローチ)。
- **絵柄ストリーム (decoupled cross-attn)** — SigLIP パッチトークンを
  各ブロックのテキスト cross-attn に decoupled attention で注入する
  統計的転写(AnimeAdapter 系)。細部をコピーしないことが目的なので、
  あえて埋め込み注入型。**要学習済みアダプタ**。

2 つは別モジュール(self-attn / cross-attn)をパッチするので併用可能。
`char``style` の強度は独立に制御できる。

## なぜT軸連結か

ComfyUI本体の実装(`comfy/ldm/cosmos/predict2.py`, `comfy/ldm/anima/model.py`)
を読んだ結果:

- AnimaのDiTはvideoアーキテクチャで、latentは `(B, C, T, H, W)`、
  自己注意は `(t h w)` を平坦化した列に **3D RoPE** 付きで計算される。
  Animaのconfigは `max_frames=128`, `patch_temporal=1` なので、
  T=2(生成1 + 参照1)はRoPE的に完全に正当。参照トークンは時間座標が
  ずれるため、生成フレームと空間位置が衝突しない。
- `timesteps``(B, T)` のフレーム毎形式を受け付ける
  (`ndim==1` のときだけ unsqueeze)。よって **参照フレームだけ
  timestep=0(クリーン画像)としてAdaLN変調** できる。
- `forward``WrappersMP.DIFFUSION_MODEL` のWrapperExecutor経由
  なので、ModelPatcherのwrapper登録だけで非侵襲にフックできる。
- 各Blockの `self_attn.attn_op` は属性(`torch_attention_op`)なので、
  `add_object_patch` で差し替えて参照トークンへの
  attention bias(log(strength))による強度制御ができる。

## ノード

### Anima Reference Encode (in-context)
IMAGE (+ 任意で MASK) + VAE → LATENT。
マスクを与えるとキャラを白背景に合成してからエンコードする
(背景バイアス除去。アニメ被写体では効果が確認されている定石)。
`target_width` / `target_height` を生成解像度に合わせると、
アスペクト保持の白パディングでリサイズしてからエンコードする
(サンプリング時のlatent空間リサンプルを回避できるので推奨)。
複数枚バッチ入力可 — 各画像が独立した参照フレームになる。

### Anima Reference Latent Batch
解像度の異なる参照LATENT同士を1つの複数フレーム参照に結合する
(2つ目を1つ目のサイズにfit)。チェーン可能。

### Anima In-Context Reference Apply
MODEL + 参照LATENT → MODEL。

- `strength` — 参照トークンへのattention bias。1.0=中立、0=無効
- `start_percent` / `end_percent` — 参照を有効にするステップ範囲
- `cond_only`(既定 ON)— CFGのuncond側では参照キーをマスクする。
  学習契約(uncond=参照なし分布)と一致するので推奨
- `fit_mode` — 参照latentが生成解像度と違う場合のfit方法
  (`pad`=アスペクト保持+エッジ複製パディング(既定)/ `stretch` / `crop`- `ref_timestep` — 参照フレームのtimestep(既定0=クリーン。
  noise augmentation学習をした場合のみ変更)

### Anima Style Adapter Loader / Anima Style Encode (SigLIP) / Anima Style Apply
絵柄ストリーム。`models/anima_style_adapters/` に学習済みアダプタを置く。
SigLIP系の CLIP_VISION モデルでエンコードし、`style_weight` で強度制御。
`cond_only`(既定 ON)。未学習アダプタは gate=0 で完全no-op。

## ワークフロー例

```
LoadImage ─┐
           ├→ AnimaRefEncode ─┐
VAELoader ─┘                  │

UNETLoader → LoraLoader → AnimaInContextApply → (AnimaStyleApply) → KSampler → ...
             (in-context LoRA)      ▲
                                    │ (絵柄も使う場合)
CLIPVisionLoader → AnimaStyleEncode ┘ + AnimaStyleAdapterLoader
```

## 重要: 学習との契約 (training contract)

Anima本体は単フレームT2Iとして学習されているため、**このノード単体
(zero-shot)での参照効果は弱い/不安定**。専用のin-context LoRAを
学習して初めて本来の精度が出る。学習コード
(リポジトリの `training/anima_incontext_train_network.py`)は
以下の推論時仕様をバイト単位で再現する:

1. 参照latentは生成フレームの **後ろ** にT軸連結(生成frames→参照frames)
2. 参照フレームのtimestepは **0**(生成フレームはサンプラーのt)
3. 参照latentは `latent_format` 正規化済み(`process_latent_in` 相当、
   Wan21のper-channel mean/std)
4. 損失は生成フレームのみに適用(参照フレームの出力は破棄)
5. テキスト条件(LLMAdapter経由)は変更なし
6. 学習ペア: 同一キャラ・**異なる**出典の2枚(参照≠ターゲット)。
   同一画像ペアはコピー機化するため禁止
7. CFG dropout: 参照を確率~10%でドロップ(フレーム連結自体を外す)
   → 推論側 `cond_only=True` のuncondがこの分布に対応

## 実機検証結果(2026-07-04, RTX PRO 6000 / anima-base-v1.0)

- **strength=0 ⇔ 通常生成: bit単位で完全一致**(strength≤0 は連結自体を
  スキップする実装。連結+全マスクでも数学的には同値だが、bf16 では
  attention kernel差がステップ毎に複利で増幅する — fp32 では1ステップ差
  mean 0.05/255 と確認済み)
- 全バリアント完走: strength=1.0(cond_only 両方)/ 解像度違い参照
  (512x768→1024x1024, fit=pad) / 複数参照 (RefLatentBatch) / sigma窓
- **zero-shot(LoRA なし, strength=1.0)の挙動**: 参照キャラを
  ポーズ・衣装込みで**ほぼ完全にコピー**し、背景が崩壊する。
  video プライアが参照を「隣接フレーム」として扱うため。
  経路が機能している証拠だが、実用には in-context LoRA が必須
  (参照≠ターゲットのペア学習がこのコピー機挙動を
  「同一キャラ・別ポーズ/シーン」に矯正する)。
  strength を下げても中間にはならず画質が劣化するだけ

## 既知の制約

- 参照フレームのK/Vは全ステップ不変だがキャッシュしていない
  (2Bモデルなので実害は小さい。最適化はTODO)
- `tests/` にモックComfyUIでの契約テストあり