Animaの4人プロンプトをQwenとT5へ分けてキャラクターの描き分けを調べた
目次

2026-08-09 追記: この交差実験の続きとして、凍結Qwen3-0.6B+resamplerで成功時のconditioningを短いトリガーから再現できるかを実測した → Qwen3.8 Maxで教師データを増やし、Animaの成功conditioningを短文へ蒸留できるか試した
前回の4人LoRAのプロンプトを段階的に削った実験では、トリガー語だけのLv0で指定した全員がそろったのは3/33で、識別アンカー・位置文・服装文まで入れたLv3では11通り中8通りが3seedとも通った。
同じAnima-Baseと4人LoRAでも、指定を長く書いたLv3でだけ、4人がそれぞれ別のキャラクターとして描き分けられた。現行のQwen3-0.6Bを交換する前に、短い失敗プロンプトP0と長い成功プロンプトP3が、Anima内部のどの経路を通ってこの描き分けの成否を決めているのかを調べた。
実装を調べると、AnimaのconditioningはQwenだけで決まっていなかった。Qwenのhidden stateとT5トークンIDを、LLMAdapterが両方受け取ってconditioningにする。そこでテンソルの観測と介入に加え、Qwen側とT5側へP0・P3を別々に入れる交差実験まで行ってみた。
AnimaのconditioningはQwenとT5の2経路から作られる
現在のComfyUI実装では、プロンプトはQwen3-0.6B-BaseとT5トークナイザーの2経路へ分かれ、Anima本体に含まれる6層のLLMAdapterを通って1つのconditioningになる。経路の確認には、実験時に使ったComfyUIコミット0764232429b8cfb10b79b6f186c8cb23e0b22897のAnimaのトークナイザー実装とAnima本体のLLMAdapter実装を使った。
flowchart TD
P[Prompt] --> Q[Qwen3-0.6B<br/>last hidden state]
P --> T[T5 tokenizer<br/>token IDsとweights]
Q --> A[LLMAdapter<br/>6 transformer blocks]
T --> A
A --> C[conditioning<br/>1024次元]
C --> D[Anima DiT<br/>cross-attention]
D --> I[生成画像]
現行コードではQwenの最終hidden stateが1024次元で、LLMAdapterも1024次元を前提にしている。Qwen側の重みは1.0固定、プロンプトの重みはT5側からLLMAdapter出力へ掛かる。
実測した経路とshape
実行環境はローカルのComfyUI本体。genserverが組み立てているワークフローを確認すると、実際の生成経路はCLIPLoader(qwen_3_06b_base.safetensors、type=qwen_image)→CLIPTextEncode→KSampler(UNETLoaderで読んだanima-base-v1.0.safetensors)になる。
comfy側の実装では、LLMAdapterはDiTのチェックポイント(anima-base-v1.0.safetensors)側に含まれ、DiTのforward内部(comfy/ldm/anima/model.pyのAnima.preprocess_text_embeds)で呼ばれる。CLIPTextEncodeが返すのはQwen3-0.6Bの最終層hidden stateと、T5トークンID・重みだけで、T5-XXL本体(4.9GBのt5xxl_fp8_e4m3fn.safetensors)はロードされない。T5トークナイザーは「どのIDをLLMAdapterの学習済み埋め込み(nn.Embedding(32128, 1024))から引くか」を決めるためだけに使われている。
| 項目 | 実測値 |
|---|---|
| ComfyUI commit | 0764232429b8cfb10b79b6f186c8cb23e0b22897 (2026-08-03)。comfy/ldm/anima/model.py等の直近変更は57500fc5bc92566a63f2046824f522cd55c335ca (2026-08-02) |
| text encoder checkpoint | qwen_3_06b_base.safetensors(1.19GB、bf16) |
| DiT checkpoint | anima-base-v1.0.safetensors(4.18GB、bf16、685テンソル中118個がnet.llm_adapter.*) |
| Qwen入力shape | (1, seq_len) int64。プロンプトごとにseq_lenは可変(38〜184を実測、後述) |
| Qwen最終hidden shape | (1, seq_len, 1024) float32。padding位置はゼロクリア済み(comfy/text_encoders/anima.pyのQwen3_06BModelはlayer_norm_hidden_state=False) |
| Qwenレイヤー数 | 28層(Qwen3_06B→Llama2_のmodel.layers実測) |
| LLMAdapter出力shape | (1, t5_seq_len, 1024) bf16。クエリ側の系列長はQwenではなくT5トークン数(LLMAdapterはT5 idをquery、Qwen hidden stateをcross-attentionのcontextとして使うため) |
| DiT入力conditioning shape | (1, 512, 1024)。LLMAdapter出力をt5xxl_weightsで重み付けした後、512トークン未満はゼロpadding(comfy/ldm/anima/model.pyのpreprocess_text_embeds) |
| 備考 | フックを入れてもCLIPTextEncode部分の出力値は変わらないことを、フックあり/なしでcondテンソルを比較して確認済み(bit-exact) |
失敗するP0と成功するP3を同じ条件で再現した
生成条件は前回の記事とそろえた。最初に前回の出力を1組だけ再現し、観測コードを挟む前後で画像が変わらないことを確認した。
| 項目 | 固定値 |
|---|---|
| ベースモデル | Anima-Base v1.0 |
| LoRA | anima-4char-v1_epoch100、rank256、strength 1.0 |
| 生成設定 | Turbo 8step / cfg 1.0 / er_sde / simple |
| seed | 42 / 1234 / 9999 |
| 解像度 | 832×1216(anima_baseのdefault_w/default_h) |
| negative prompt | worst quality, low quality, blurry, jpeg artifacts, text, watermark, signature, multiple views, split view, cropped(前回実験と同一) |
| 生成経路 | genserver /api/generate(同期JSON API)経由。ComfyUI本体はすでに起動中のプロセスをそのまま使う |
テンソル抽出は別プロセス(CPU固定、ComfyUIサーバーとは別のPythonプロセス)で行っており、生成中のComfyUIサーバーの状態は変更していない。
再現結果
いずれもseed 42で生成した。
| 条件 | 前回の判定 | 再実行の判定 |
|---|---|---|
| 4人・Lv0 | ×(3seedとも0/3) | ×(kanachanが出ず、左から2人ともkuraraになった。片方は背が低い) |
| 4人・Lv3 | ○ | ○(4人とも学習時の識別特徴を保ったまま描き分けられた) |


Lv0/Lv3とも判定は前回記事と一致した。判定基準の「指定した全員が本人の見た目になっているか」で判定するとLv0=×、Lv3=○になるので、以降のconditioning比較・介入実験はこの2枚を基準画像として進める。
P0からP3までの中間プロンプトも用意した
内部状態は66件全部からではなく、前回の結果で同じseedのまま失敗と成功が分かれた代表ペアだけから取った。
| 系統 | 比較する条件 | 確かめたこと |
|---|---|---|
| 4人の描き分け | 4人Lv0と、同seedの4人Lv3 | 4人が別々のキャラクターとして描き分けられるか |
| 2人の描き分け | Lv0で本人にならず、Lv3でそろったペア | 人数を減らしても同じ崩れ方をするか |
| 弱い属性 | koharu+keichanの身長文なしとあり | 1文だけの差がどの段階で強くなるか |
各系統には、必要に応じて次の中間条件を足した。
| 条件 | 内容 | 目的 |
|---|---|---|
| P0 | トリガー語のみ | 失敗側の基準 |
| P0-length | 人物固有情報を増やさず、全体説明だけでP3に近い長さへ増やす | 単なるトークン数増加の影響を確かめる |
| P1-separate | 各トリガーを別文にするが、外見属性は書かない | 人物を区切る構造だけの影響を確かめる |
| P2-anchor | 各人物に識別アンカーを付ける | 外見属性の紐付けを確かめる |
| P3 | 前回成功した全文をそのまま使う | 成功側の基準 |
P0-lengthは意味を一定に保てていないため、長さだけを分離した条件にはなっていない。
比較に使ったプロンプト
# 4人 P0(前回から引用)
masterpiece, best quality, safe, 4girls, multiple girls, kurara, keichan, kanachan, koharu, full body, white background, simple background
# 4人 P0-length(実験時に作成、長さ合わせ)
masterpiece, best quality, safe, 4girls, multiple girls, kurara, keichan, kanachan, koharu, full body, white background, simple background, standing together in a clean and bright studio with soft even lighting, a plain seamless backdrop, high resolution digital illustration with clean line art and detailed shading, four figures visible from head to toe in a single unbroken row
# 4人 P1-separate(実験時に作成)
masterpiece, best quality, safe, 4girls, multiple girls, full body, white background, simple background. kurara is present. keichan is present. kanachan is present. koharu is present.
# 4人 P2-anchor(前回から引用)
masterpiece, best quality, safe, 4girls, multiple girls, kurara, keichan, kanachan, koharu, full body, white background, simple background. kurara has long rose-brown hair, stud earrings and light makeup. keichan is a blonde girl with a blue ribbon. kanachan has a brown side ponytail and an ahoge. koharu has short dark hair and red eyes.
# 4人 P3(前回から引用)
masterpiece, best quality, safe, 4girls, multiple girls, kurara, keichan, kanachan and koharu, full body, four girls standing in a row facing the viewer, white background, simple background. kurara, with long rose-brown hair, stud earrings and light makeup, is on the far left. keichan, a blonde girl with a blue ribbon, is second from the left, the same height as kurara. kanachan, with a brown side ponytail and an ahoge, is third from the left, half a head shorter. koharu, with short dark hair and red eyes, is on the far right, the shortest. everyone is wearing a plain white t-shirt and blue jeans.
# 4人 P3-order-reversed(実験時に作成、人物順を反転)
masterpiece, best quality, safe, 4girls, multiple girls, koharu, kanachan, keichan and kurara, full body, four girls standing in a row facing the viewer, white background, simple background. koharu, with short dark hair and red eyes, is on the far left, the shortest. kanachan, with a brown side ponytail and an ahoge, is second from the left, half a head shorter than the tallest. keichan, a blonde girl with a blue ribbon, is third from the left. kurara, with long rose-brown hair, stud earrings and light makeup, is on the far right, the same height as keichan. everyone is wearing a plain white t-shirt and blue jeans.
# 2人 kurara+kanachan Lv0(前回から引用)
masterpiece, best quality, safe, 2girls, kurara, kanachan, full body, white background, simple background
# 2人 kurara+kanachan Lv3(前回から引用)
masterpiece, best quality, safe, 2girls, kurara and kanachan, full body, two girls standing side by side facing the viewer, white background, simple background. kurara, with long rose-brown hair, stud earrings and light makeup, is on the left. kanachan, with a brown side ponytail and an ahoge, is on the right, half a head shorter. everyone is wearing a plain white t-shirt and blue jeans.
# koharu+keichan 身長文なし(前回から引用)
masterpiece, best quality, safe, 2girls, koharu and keichan, full body, two girls standing side by side facing the viewer, white background, simple background. koharu, with short dark hair and red eyes, is on the left. keichan, a blonde girl with a blue ribbon, is on the right. everyone is wearing a plain white t-shirt and blue jeans.
# koharu+keichan 身長文あり(前回から引用、3seedとも成功した版)
masterpiece, best quality, safe, 2girls, koharu and keichan, full body, two girls standing side by side facing the viewer, white background, simple background. koharu, a shorter girl with short dark hair and red eyes, is on the left. keichan, a blonde girl with a blue ribbon, is on the right. everyone is wearing a plain white t-shirt and blue jeans.
トークン分割とtruncationからは失敗の理由がわからなかった
比較プロンプトを2つのトークナイザーへ通し、トークンID、元プロンプト中の文字位置、attention mask、重み、有効トークン数、トリガー語の分割、512トークンでのtruncation有無を保存した。
Qwen3-0.6Bはdecoder-onlyなので、各トークンのhidden stateはそのトークンより前の文脈だけで決まる。人物順の影響も確かめるため、P3は人物順を反転した条件も加えた。
トークナイザーは、genserverが生成時に使うのと同じcomfy/text_encoders/anima.pyのAnimaTokenizerを使った。Qwen側はqwen25_tokenizer(Qwen2Tokenizer、has_start_token=False・has_end_token=False)、T5側はt5_tokenizer(T5TokenizerFast)。
トークナイズ結果
| prompt | Qwen実トークン数 | T5実トークン数 | truncation |
|---|---|---|---|
| 4人 P0 | 38 | 43 | なし |
| 4人 P0-length | 82 | 92 | なし |
| 4人 P1-separate | 47 | 52 | なし |
| 4人 P2-anchor | 91 | 108 | なし |
| 4人 P3 | 155 | 179 | なし |
| 4人 P3-order-reversed | 159 | 184 | なし |
| 2人 kurara+kanachan Lv0 | 27 | 29 | なし |
| 2人 kurara+kanachan Lv3 | 96 | 109 | なし |
| koharu+keichan 身長文なし | 85 | 96 | なし |
| koharu+keichan 身長文あり | 88 | 100 | なし |
全プロンプトが512トークンを大きく下回っており、どのプロンプトでもtruncationは発生していない。短いプロンプトが失敗するのはtruncationのせいではない。
トリガー語が何トークンに割れるかは、4人で揃っていない。kurara・keichan・kanachan・koharuはどれもトークナイザーの語彙にない造語なので、既存のサブワードの組み合わせに分解される。その分け方と個数がキャラごとに違う。
| トリガー | Qwen分割 | T5分割 |
|---|---|---|
| kurara | kur / ara(2トークン) | kur / ara(2トークン) |
| keichan | ke / ich / an(3トークン) | ke / ich / an(3トークン) |
| kanachan | kan / ach / an(3トークン) | kan / a / chan(3トークン、Qwenと分割位置が違う) |
| koharu | k / oh / aru(3トークン) | k / o / har / u(4トークン、最も細かく割れる) |
kuraraだけ2トークンで、他の3人は3〜4トークンに割れる。トリガーのトークン分割の細かさと崩れやすさの間に単純な相関はなかった(koharuが最も細かく割れるが、崩れがkoharuに寄ることはkuraraほど多くない)。分割の粗さより、学習データでの出現数の多さ(kurara 312件)の方が、崩れたときにkuraraへ寄る理由になりそうだ。
人物順を入れ替えたP3-order-reversedとP3を比較すると、Qwen側のトークン数は155→159、T5側は179→184と、わずかに増えている。これは意味が完全に同じ入れ替えではなく、身長差の言い回し(「is second from the left, the same height as kurara」→「is third from the left」)を語順に合わせて書き直したため。このトークナイズ結果だけでは、人物順の因果関係までは判定できない。
前の文脈だけで決まるというこの制約は、後述のテンソル比較でも数値として確認できた。トリガー語がプロンプトの先頭付近にある限り、後ろにどれだけ識別文を足しても、トリガー語自身のQwen hidden stateはほぼ変化しない。
トークン分割・truncation・maskの差だけでは、成功と失敗が何で決まっているのかがわからなかった。全プロンプトがtruncationなしで収まっており、トリガー語の分割粒度と崩れやすさの間にも単純な相関はない。トークンの段階で差がつかないので、その先のconditioningを比較した。
hidden stateのコサイン類似度では描き分けの成否を測れなかった
同じプロンプトから、Qwenの埋め込み出力と全層のhidden state、LLMAdapterの6ブロックそれぞれの出力、DiTへ渡す直前の最終conditioningを保存した。保存形式はfloat32へ変換したNPZとし、別のJSONへprompt、トークン対応、shape、dtype、モデルhashを記録した。
短文と長文では系列長が違うため、テンソル全体を平坦化したコサイン類似度やMSEは出さなかった。比較の単位にしたのは、プロンプトの中で1人のキャラクターを指定している部分になる。P3ならkanachan, with a brown side ponytail and an ahoge, is third from the left, half a head shorter.がそれで、トリガー語とそれに続く識別文が連続したトークン列を占めている。以降ではこれを人物の記述部分と呼ぶ。
比較対象はこれ。
- 人物の記述部分のトークンをまとめたベクトル
- 同一prompt内での記述部分どうしのコサイン類似度
- 同じ文字列が残っているトークンだけを対応付けた層をまたいだ比較
- QwenとLLMAdapter通過後で、人物ごとのベクトルがどれだけ似ているか
Qwen側とT5側はトークナイズ位置が一致するとは限らないので、両者のトークン位置は混ぜず、元の文字列の上での位置を介して別々に対応付けた。
実装はcomfy.sd.load_clipでCLIPTextEncode相当を、anima-base-v1.0.safetensorsからnet.llm_adapter.*の118テンソルだけを抜き出してcomfy.ldm.anima.model.LLMAdapterへload_state_dictすることでLLMAdapter相当を、それぞれ本番と同じ重みで再現した(missing=[], unexpected=[]でロード確認済み)。DiT本体(4.18GB)は読み込んでいない。両方ともCPU固定で実行した。
clip.encode_from_tokensにforward hookを入れて、Qwenの28層それぞれの出力とLLMAdapterの6ブロックの出力を一度に拾って比較した。
テンソル比較
| prompt | 観測地点 | shape | norm平均(トークン方向) |
|---|---|---|---|
| 4人 P0 | Qwen最終層(全トークン) | (1, 38, 1024) | 110.67 |
| 4人 P0 | LLMAdapter出力(全トークン、DiT直前・padding前) | (1, 43, 1024) | 5.59 |
| 4人 P3 | Qwen最終層(全トークン) | (1, 155, 1024) | 126.20 |
| 4人 P3 | LLMAdapter出力(全トークン、DiT直前・padding前) | (1, 179, 1024) | 4.13 |
Qwen最終層のnormはP0→P3で増えるが、LLMAdapter出力のnormはP0→P3で減っている。DiTへ渡る直前のconditioningは512トークンまでゼロpaddingされるため、有効トークン数が増えるほど「情報を持つトークンの割合」自体は必ずしも増えない。
人物の記述部分のプーリングは2通り試した。方法1はトリガー語そのもの(初出のみ、2〜3トークン)だけをプールする。方法2はトリガー語から、その人物の識別文の終わりまで(次の人物のtrigger開始か.のどちらか手前まで)をひとまとまりとしてプールする(後方参照だけの短い再出現は除外し、識別文が付いた出現を選ぶ)。
方法1(トリガー語のみ)の結果、kurara・keichan・kanachanの3人はP0とP3で完全に同じコサイン類似度になった。
| ペア | P0(トリガーのみ) | P3(トリガーのみ) |
|---|---|---|
| kurara-keichan | 0.8941 | 0.8941(完全一致) |
| kurara-kanachan | 0.8856 | 0.8856(完全一致) |
| keichan-kanachan | 0.9531 | 0.9531(完全一致) |
| kurara-koharu | 0.8501 | 0.8617 |
| keichan-koharu | 0.9087 | 0.9152 |
| kanachan-koharu | 0.9173 | 0.9212 |
P0とP3はプロンプト前半が同じ文字列(kurara, keichan, kanachanまで)で、koharuの前だけP0は,、P3はandと違う(Lv3プロンプトのkanachan and koharuという書き方のため)。前の文脈だけで決まるので、P0とP3で直前の文脈が文字通り同一のkurara・keichan・kanachanは完全に同じベクトルになり、直前の語が違うkoharuだけ値がずれた。これは「トリガー語の後ろに識別文をどれだけ足しても、トリガー語自身のQwen表現はほぼ変わらない」ことを実測で裏付けた。人物分離の情報は、トリガー語自身にではなく、識別文が乗っているトークン位置の側にあると分かる。
方法2(識別文まで含めた記述部分)で比較すると、Qwen最終層のコサイン類似度はP0→P3で下がるどころか上がった。
| prompt | Qwen最終層 人物ベクトル間の平均コサイン類似度 | LLMAdapter出力 人物ベクトル間の平均コサイン類似度 |
|---|---|---|
| P0(トリガーのみ、識別文なし) | 0.9332 | 0.3201 |
| P1-separate(トリガーを別文に分けるだけ) | 0.9528 | 0.4524 |
| P2-anchor(識別アンカー付き) | 0.9697 | 0.5002 |
| P3(識別アンカー+位置文+服装文) | 0.9814 | 0.4805 |
Qwen最終層は識別文を足すほど記述部分どうしのコサイン類似度が一貫して上がる(P0の0.9332→P3の0.9814)。LLMAdapter出力はP0→P2-anchorまでは上がる(0.3201→0.5002)が、P2-anchor→P3では下がる(0.5002→0.4805)。全体としては足すほど似てくる結果で、当初考えていた「長い成功プロンプトほど人物ごとのベクトルが離れる」という予想とは逆になった。
理由として考えられるのは、識別文の多くが同じ文法テンプレート(「Xは〜色の髪」「Xは〜色の瞳」のような構造)を共有しており、平均プーリングだと「女の子を説明する文」という共通成分の方が、個別の色や形の違いより強く出てしまうこと。単純な平均プーリング+コサイン類似度は、この共通成分に引きずられて「識別文を書くほど人物のベクトルが似てくる」という、実際の画像結果(識別文を書くほど描き分けられる)とは逆の値を出す。コサイン類似度は、描き分けができているかどうかの根拠にならない。
Qwenの28層それぞれでトリガー語だけのコサイン類似度を出すと、全体として上昇していた。P3のトリガー語(識別文を含まない、最初に出てくるトリガー語だけ)を28層すべてで比較すると、0層目の0.59から27層目の0.94まで、途中14層目の0.83から20層目の0.77へ下がる箇所を挟みつつ、全体としては上昇した(step2_layersweep.json)。単調増加ではないが、深い層に行くほど「どのトークンも似た方向を向く」異方性の影響を受けた可能性がある。このコサイン類似度だけでは大型Qwenの効果を否定できないが、上位Qwenを試す場合に最終層だけでなく中間層も比較する理由にはなる。
conditioningはQwen最終層でもLLMAdapter出力でも数値としては取れたが、識別文を足すとコサイン類似度が上がるか下がるかが直感と一致せず、テンソルの比較だけでは「描き分けられている」とも「いない」とも判定できなかった。
DiT直前のconditioningを消すと人物が置き換わった
attention mapは参照先を示すだけで、その情報が画像を変えた証明にはならない。固定noise、固定seedのまま、人物の記述部分へ介入した。
- 1人分の記述部分をゼロへ置き換える
- 2人分の記述部分を入れ替える
- Qwen出力で介入し、LLMAdapter以降をそのまま流す
- LLMAdapter出力で同じ介入を行う
- トークンを削除せず、系列長と位置を保ったまま値だけ変える
例えばkanachanの記述部分を消した時にkanachanだけが消える、または外見だけが崩れるなら、その部分が画像へ寄与した根拠になる。何も変わらない場合は、記述部分の割り出しが間違っている可能性もある。
実装はnodes.pyのノードクラス(UNETLoader・CLIPLoader・LoraLoader・CLIPTextEncode・KSampler・VAEDecode)をgenserverと同じ順序・同じstrengthで直接呼び出す形にした。まずconditioningを一切いじらない状態でP3・seed42を生成し、再現画像と比較したところ、構図・人物・服装は完全に一致した(--bf16-vae起動フラグの違いで平均絶対差14.8/255のわずかな差は出たが、生成内容は同一)。この手動パイプラインをもとに、positiveのconditioningだけを差し替えて生成した。
介入はA〜Dの4件で、いずれも4人P3・seed 42のまま行った。A・B・CはQwen最終層側の記述部分を操作し、DだけがLLMAdapter出力側(DiT直前)を操作する。
介入なしのベースラインはこうなった。

A・B・Cは、いずれもこのベースラインとほぼ変わらなかった。
| 介入 | 操作 | 画像の変化 |
|---|---|---|
| A | kanachanの記述部分をzero | 4人ともベースラインと同じ人物・特徴で出力。kanachanのサイドポニー・アホ毛も残る |
| B | koharuの記述部分をzero | 4人ともベースラインと同じ人物・特徴で出力。koharuの短い黒髪・赤い瞳も残る |
| C | kanachan⇔koharuの記述部分をswap(平均プーリング値を交換) | 入れ替わらず、4人ともベースラインの並びのまま |



最後の介入Dは、操作する場所をQwen最終層からLLMAdapter出力側へ移し、Aと同じkanachanの記述部分をzeroにする。ここだけ、はっきり画像が変わった。
| 介入 | 操作 | 画像の変化 |
|---|---|---|
| D | LLMAdapter出力(DiT直前、512padding前)のkanachanの記述部分をzero | kanachan(3番目)の識別特徴が消え、keichanとほぼ同じ金髪+青リボンの人物に置き換わる |

置き換わったのはkanachanだけで、消えたのはサイドポニー・アホ毛・茶髪という識別特徴になる。他3人はベースラインのままで、koharu(4番目)にも影響がない。
ベースラインとのピクセル差分(平均絶対差、0〜255)も出した。
| 介入 | 平均絶対差(0-255) | 変化>10の画素割合 | 目視判定 |
|---|---|---|---|
| A(Qwen側、kanachan zero) | 18.1 | 23.6% | 人物同一、線画レベルの違いのみ |
| B(Qwen側、koharu zero) | 12.8 | 18.3% | 人物同一、線画レベルの違いのみ |
| C(Qwen側、kanachan⇔koharu swap) | 19.2 | 26.1% | 人物同一、入れ替わりなし |
| D(LLMAdapter側、kanachan zero) | 32.5 | 39.0% | kanachanが消え、keichan複製に置き換わる |
Qwen最終層で記述部分をゼロにしても画像はほぼ変わらないのに、LLMAdapter出力でゼロにすると画像が変わった。ただし、この比較だけではLLMAdapterがQwenの残りトークンから再構成したのか、独立して入力されるT5トークンIDを使ったのかを分けられない。そこで後述の交差実験を追加した。
介入Dはseed 1234・9999でも同じ壊れ方で再現した。3seedとも、kanachanの識別特徴(サイドポニー・アホ毛・茶髪)が消え、keichanとほぼ同じ金髪+青リボンの人物が2人並ぶ結果になった。位置(3番目)・服装は変わらないが、識別特徴だけがkeichanのものに置き換わる。


置き換わり先が毎回keichanだったのも一貫していた。kanachanの識別信号が消えた時のDiT側の既定値(fallback)が、keichanへ偏っている可能性がある。前回記事ではLv0の崩れの多くにkuraraが関わっていた(学習データのtrigger出現数が4人中最多)が、今回のLLMAdapter出力介入ではkeichanの特徴が出た。崩れた先は前回と今回で違っている。
ここまでの介入A・B・Cは「Qwenの最終hidden stateだけを操作し、LLMAdapterへ渡るT5トークンIDはそのまま」という条件だった。これでは「Qwen側の情報だけを消しても画像は変わらない」ことしか示せていない。「LLMAdapterが描き分けを左右している」とまでは言えない。LLMAdapterはQwen hidden stateとT5トークンIDの両方を独立した入力として受け取り、T5トークンID側はLLMAdapter自身が持つ学習済み埋め込み(nn.Embedding(32128, 1024))経由でトリガー名や識別文をそのままベクトル化している。Qwen側だけゼロにしても、T5側にkanachanの名前・識別文がそのまま残っていれば、そこから画像が再構成されている可能性がある。
QwenとT5を独立に交差させた
上の懸念を切り分けるため、CLIPTextEncodeが返す「Qwen hidden state(cross-attentionのcontext)」と「T5トークンID・重み(cross-attentionのquery)」を別々のプロンプトから取って組み合わせ、4通り+1条件をseed42で生成した。
| 条件 | Qwen hidden state | T5トークンID・重み |
|---|---|---|
| Qwen=P0 / T5=P0 | P0(トリガーのみ) | P0 |
| Qwen=P3 / T5=P0 | P3(識別アンカー+位置文+服装文) | P0 |
| Qwen=P0 / T5=P3 | P0 | P3 |
| Qwen=P3 / T5=P3 | P3 | P3 |
| Qwen=全ゼロ / T5=P3 | 全トークンをゼロ | P3 |

Qwen=P0/T5=P0は両方ともP0なので、P0をそのまま入れた場合と同じ出力になる。kanachanが出ず、kuraraが2人になる。

Qwen=P3/T5=P0は、Qwen側だけをP3へ差し替えた条件になる。出力はQwen=P0/T5=P0とほぼ変わらない。T5側がP0(トリガーのみ、実トークン数43)のままだと、Qwen側にP3の識別文を入れてもkanachanは出ず、kuraraが2人のままだった。

Qwen=P0/T5=P3は逆に、T5側だけをP3(実トークン数179)へ差し替えた条件になる。Qwen側がP0のままでも、kanachanとkeichanは識別特徴が出た。ただしkoharuが出ず、代わりにkuraraが2人になるので、4人全員の描き分けには届いていない。

Qwen=P3/T5=P3は両方ともP3で、通常のP3生成にあたる。4人とも描き分けられる。

Qwen=全ゼロ/T5=P3は、Qwenのcross-attention入力を全トークンぶん断った条件になる。それでも中央のkanachanと右のkeichanは本人と分かる特徴で出た。左はkurara寄りの人物にkanachanのサイドポニーが乗っており、koharuは出ないまま3人になる。
T5=P0のままQwen側だけをP3にしても変わらなかったのは、短いT5系列ではquery位置が少なく、Qwen側の情報を反映する経路が乏しいためかもしれない。ただしcross-attentionを観測していないので、機序は未確認になる。
T5側(LLMAdapterのquery、Qwen側とは独立にLLMAdapter自身の埋め込みを持つ)を差し替えたときの変化は大きい。ただしP0とP3はトークン数だけでなく識別文・位置文・服装文の内容も異なるため、トークン数だけの効果や閾値はこの比較から決められない。
この5条件のseed 42では、Qwen=P3/T5=P3(通常条件)だけが4人全員を描き分けた。Qwenを全ゼロにすると人数と人物構成が変わったためQwen経路も出力へ寄与しているが、どのキャラクターの再現に必須なのかまでは断定できない。
「4人の描き分けを左右しているのはQwen3-0.6BではなくLLMAdapterの処理」という当初の判定は、Qwen側だけを操作した介入A・B・Cだけでは確定できなかった。seed 42の交差実験で確認できたのはこれ。
(1) T5側をP0からP3へ変えると画像が大きく変わる
(2) T5=P0のままQwen側だけP3へ変えてもkanachanは出ない
(3) Qwenを全ゼロにするとQwen=P3/T5=P3の4人全員の描き分けを再現できない
T5側の系列内容が強く影響し、Qwen経路にも寄与があることは分かったが、両者の寄与の大きさ、トークン数の閾値、Qwen3-0.6Bの容量がボトルネックかどうかまでは決められない。
固定辞書だけでseed 42の4人が本人の見た目になった
短いトリガーから長い成功プロンプトを作るだけなら、Anima内部のtext encoderを交換しなくても、生成サーバー側で展開できる。同じseedで、トリガー語だけをそのまま入力する条件1、キャラごとの固定辞書から決定的に識別文を補う条件2、大型Qwenへキャラ辞書とトリガーを与えて人物別の文へ展開してから現行Animaへ入力する条件3を比較した。
大型Qwenにはキャラ辞書を与えており、独自トリガーだけから設定を推測させてはいない。大型Qwenによる書き換えでは、入力順の変更や属性の書き忘れも確認した。
条件2の「固定辞書」は、genserverがキャラプリセットに持っている4人ぶんの識別アンカーで、位置文も服装文も含まない。最小限のシーン説明(full body, white background, simple background)だけ入力してキャラプリセットを選んだ状態を再現している。条件3の「大型Qwen」は、M4 Mac mini上のOllamaで動かしたローカルモデルqwen3.6:35b(量子化、23GB)。genserverが持っている4人それぞれの特徴リストをそのまま与え、P3と同じ構造(位置文+人物ごとの一文+服装文)で出力するよう指示した。
プロンプト展開の結果
3条件ともseed 42で生成した。
| 条件 | 4人の本人一致 | 特徴の移り方 | 位置 |
|---|---|---|---|
| トリガーのみ(P0) | ×。kanachanが出ず、kuraraが2人になった | kanachanが丸ごとkuraraに置き換わった | 指定していない学校制服になった |
| 固定辞書 | ○。4人とも識別特徴(髪型・瞳の色)が出た | 他キャラへ移った特徴はない | 左からkurara→koharu→kanachan→keichan。位置文がないためトリガー順と一致しない |
| 大型Qwenで展開 | △。kuraraとkeichanは一致。kanachanは出ず、keichanが2人になった | kanachanのサイドポニーと青シュシュが、keichanとkoharuの両方へ移った | 左からkurara・keichan・keichan寄りの人物・koharu。3番目がkanachanになっていない |



固定辞書(識別アンカーのみ、位置文・服装文なし)だけで、4人の識別特徴はこのseedでは全部出た。前回記事の境界テストでは4人Lv1(識別アンカーのみ)を実測していない。ただし位置文がないため並び順は制御できない。実運用でキャラの並び順を指定したい場合は位置文が必要だが、「誰が誰の見た目で出るか」という本人一致だけなら、識別アンカーの追加だけでLv0からLv3に近い水準まで改善する可能性がある。
大型Qwenによる展開では、P3と同じ構造のプロンプトを作ったにもかかわらずkanachanが出なかった。3番目は金髪のままサイドポニーが付いたkeichan寄りの人物で、koharuにも同じサイドポニーとアホ毛が付いている。原因をプロンプト文字列で確認すると、大型Qwenへ与えたkanachanの特徴リストにはside ponytail, ahoge, double parted bangs, medium hair, blue scrunchieとあるだけで、髪の色を示す単語(brown等)が実際に含まれていない。一方、前回記事の境界テスト用プロンプト(今回のP3)はwith a brown side ponytail and an ahogeと手動で”brown”を補って書かれていた。大型Qwenは与えられた特徴リストを展開したが、辞書にない色情報までは補わなかった。色を持たないkanachanは、サイドポニーと青シュシュとアホ毛という髪型の指定だけになり、その指定がkeichanとkoharuへ乗った。大型化そのものの精度以前に、与える辞書へ色情報が入っていなかった。
今回の実測から言える範囲
| 実測 | 今回の判断 |
|---|---|
| 全条件が512トークン未満で、truncationなし | 短文が失敗する理由はtruncationではない |
| Qwen最終層で人物の記述部分を操作しても画像はほぼ変わらず、DiT直前で同じ部分をzeroにすると3seedで人物が置き換わった | DiT直前の記述部分が画像の人物を決めている |
| seed 42でQwen=P3/T5=P0は失敗側のまま、Qwen=P0/T5=P3では一部の人物が本人の特徴で出た | この条件ではT5側をP3へ変えた影響が大きかった |
| Qwen=全ゼロ/T5=P3では4人全員の描き分けを再現できなかった | Qwen経路も出力へ寄与している |
| 固定辞書の識別アンカーでseed 42の4人全員が一致した | プロンプト展開だけで対照が取れる |
トークン数そのものの効果、LLMAdapterだけが描き分けを左右するのか、T5トークン数の閾値と他seedでの一般性、Qwen3-0.6Bの容量が足りているか、固定辞書が複数seedでも安定するかは、今回の実測では決められていない。
短い4人プロンプトが失敗する理由は、Qwen3-0.6Bの表現力不足だけではわからなかった。seed 42の交差実験では、T5側をP0からP3へ変えた時の方が、Qwen側だけをP0からP3へ変えた時より画像が大きく変わった。P0とP3ではトークン数と文章内容が同時に変わっているため、画像を変えたのが長さなのか、識別文なのか、両方なのかはまだ分からない。
一方で、Qwenを全ゼロにすると通常のP3とは人数も人物構成も変わった。Qwen経路には出力への寄与があり、上位モデルを試す余地も残っている。同じ0.6BへP0とP3を入れた比較から、上位モデルのhidden stateが作る差までは判断できない。
実用面では、完全な人物辞書から識別アンカーを補う方法なら、Anima側を触らず生成サーバーだけで済む。ただし成功を確認したのはseed 42の1回で、並び順も制御できていない。固定辞書だけで本人の見た目になったことは、次の内部実験が本当に必要かを測る対照条件として使える。