技術約16分で読めます

SeFi-ImageをM1 MaxのMPSで試す

いけさん目次

Civitaiで見かけたKrea 2ベースのアニメ寄りマージ(AniMD-Krea2Turbo)を調べていたところ、新着チェックポイントの上位がほぼKrea 2派生マージで埋まっていた。
Muse by Stable Yogi、Amazing Reality、Project Chimera、Moody Krea 2 Mixあたりはどれも同じKrea 2の亜種で、過去記事(Krea 2をM1 MaxのComfyUIで試す)から目新しい技術はない。

そこでHugging Faceの新着を辿ると、SeFi-Image(arXiv:2606.22568)を発見した。
セマンティックとテクスチャの潜在表現を分離して非同期にデノイズする方式で、VAEとDiTバックボーンにはFlux.2系(ファインチューンしたFlux.2 VAEとFlux.2 [klein]系DiT)を流用しつつ、デノイズの設計自体は過去記事で扱ったどのモデルとも違うもののようだ。
パラメータ数は最大の5BでもBoogu(10B)の半分。M1 Max 64GBでロードできるかを確かめてみた。

SeFi-Imageとは

SeFi-Imageは「Semantic-First Diffusion」という手法を採用したテキスト画像生成の基盤モデルで、デノイズ過程をセマンティック(構造)とテクスチャ(質感)の2ストリームに分け、セマンティック側を先行させて非同期に進める。
テクスチャ潜在はFlux.2 VAEをファインチューンして抽出し、セマンティック潜在はフリーズしたDINOv2の特徴を専用のSemVAEで圧縮して作る。
両者を結合した潜在空間に対してDiTがベロシティをまとめて予測し、損失計算時にまた2つへ分割する。
タイムステップ埋め込みも単一ではなく、2ストリームの非同期なノイズレベルをそれぞれ条件付けするデュアルタイムステップ方式になっている。

1B/2B/5Bの3サイズがあり、1Bと2BはBase/Turbo、5BだけBase/Turbo/RLが用意されている。
BaseはCFG込みの50step、Turboは4stepの蒸留版。
推論コードはMITライセンスで公開されているが、重み自体はCC BY-NC 4.0(非商用)。

検証環境

項目内容
マシンMacBook Pro M1 Max 64GB
OSmacOS 26.5
Python3.12.12
PyTorch2.13.0(MPS)
diffusers0.39.0
transformers5.14.1
accelerate1.14.0
対象モデルSeFi-Image-1B-turbo(4step)

テスト方針

過去のローカルモデル検証(Boogu-ImageKrea 2)と同じ枠組みで進める。

  1. アーキテクチャの事前確認。CUDA専用の実装が混ざっていないかをコードから確認しておく
  2. ロード確認。1B turboが一番軽いので、まずこれが通るかを確かめてみる
  3. 速度計測。コールド/ウォームを分けて測る
  4. メモリ常駐量
  5. 出力品質

結果

1. アーキテクチャの事前確認

DiTのバックボーンはGitHub上のラッパーコード(sefi/modeling/flux2_sefi_transformer.py)を見る限り、diffusersのFlux2Transformer2DModelを構成部品として使い、デュアルタイムステップ埋め込みとモジュレーション係数の計算のためにforward経路を組み直している。
ラッパー側に.cuda()やflash_attn/xformers/tritonのようなCUDA専用の記述は見当たらなかった。

sefi/runner.pydevice引数はデフォルトが"cuda"だが、SEFIInferencePipeline.from_pretrained(..., device="mps")のように呼び出し側で上書きできる作りになっている。
過去記事のKrea 2で詰まったのはfp8量子化テンソル(Float8_e4m3fn)がMPSでハード非対応という点だったが、SeFi-ImageのBase/Turbo版はbf16ベースなので同じ問題は起きない見込み。

2. ロード確認

python inference.py --checkpoint SeFi-Image/SeFi-Image-1B-turbo --device mps --dtype bf16 ...を実行したところ、重みのダウンロード中に403で止まった。

huggingface_hub.errors.GatedRepoError: 403 Client Error.
Access to model SeFi-Image/SeFi-Image-1B-turbo is restricted
and you are not in the authorized list.

SeFi-ImageのHugging FaceリポジトリはCC BY-NC 4.0ライセンスへの同意を求めるゲート付きで、Webページ上で「Agree and access repository」をクリックする必要がある。

WaveCutのSpaceでの生成

DLの準備中に、WaveCutが公開しているHugging Face Space(WaveCut/SeFi-Image、ZeroGPU上で稼働)で1B turboの生成だけ先に試した。
M1 Maxの実測ではなくZeroGPU側の数値なので速度の参考にはならないが、出力品質がどんなもんかだけ確認しておくためだ。

プロンプトはA blue ceramic mug on a white desk.、4step、guidance 1.0、seed 523199491。青いマグカップが指定通りプロンプトに沿って生成され、素材の光沢や背景のボケも破綻なく出た。

バックエンド側の内訳はこんな感じ。

フェーズ時間
モデルのダウンロード/ロード/切り替え12秒
プロンプト・latent準備0.5秒
デノイズ本体(4step)0.5秒(7.88 steps/s)
デコード・出力0.4秒

デノイズ自体は4stepで0.5秒。
ただしZeroGPU側はデータセンター級のGPU(現行仕様ではRTX Pro 6000 Blackwellの半分または全体が割り当てられる)なので、M1 MaxのMPSでどのくらいの速度になるかはこの数字からは分からない。

ModelScopeミラーの確認

一方で同じ開発元がModelScopeにも同じラインナップ(1B/2B/5B、RLは5Bのみ)をミラーしているのを発見した。
ModelScope側はHugging Faceのようなライセンス同意クリックはいらなくて、未ログインの状態でmodelscopeパッケージのsnapshot_downloadがそのまま通った。

ただし手元の回線からモデルスコープへの実効速度は73KB/s程度しか出ず、1B turboだけで6.80GBあるダウンロードに2時間21分かかった。

3. ロード確認とMPS実行(ModelScope経由)

ダウンロードが終わったローカルパスを--checkpointに渡して--device mps --dtype bf16で実行したところ、そのまま通った。

python inference.py \
  --checkpoint ./ms_cache/models/SeFi-Image--SeFi-Image-1B-turbo/snapshots/master \
  --prompt "A blue ceramic mug on a white desk." \
  --steps 4 --guidance-scale 1.0 \
  --device mps --dtype bf16 --seed 42

エラーなく000000.pngが出力された。事前確認のとおり、fp8のような壁には当たらなかった。すんなり通るとそれはそれで拍子抜け。

4. 速度計測

inference.pyはCLI実行のたびにプロセスを新規起動してモデルを読み込む作りで、ComfyUIのように常駐させて2回目以降を高速化する仕組みがない。
そのため素のCLIでは「ロード+生成」の合計の速度計測になる。
そこで、ロードと生成本体を分けて測るために、Python APIで同一プロセス内に2回目以降の生成もさせて計測し直すことで時間を出した。

フェーズ時間
モデルロード(from_pretrained7.30秒
生成1回目(1024×1024、4step)13.23秒
生成2回目(同一プロセス、ウォーム)13.14秒
生成3回目(同一プロセス、ウォーム)13.09秒

ウォーム状態でも生成は1枚13秒前後で頭打ちになり、4stepなので1stepあたり約3.3秒。
WaveCutのSpace(ZeroGPU)の0.13秒/stepと比べると25倍ほど遅かった。
この差がメモリ帯域なのかアテンション実装なのかは、この測定からでは判別できない。

CLI経由の1回通しの実行(ロード+生成)は21.2〜21.3秒で安定していて、ここは複数回試しても大きくぶれなかった。

5. メモリ

/usr/bin/time -lでCLI実行を1回計測した結果、ピークメモリフットプリントは約15.8GB(maximum resident set sizeは約4.95GBだが、MPSの統合メモリでは判別できないためpeak memory footprintの値を採用)。
64GBの実機ではメモリ上に普通に乗った。
1B DiT+Qwen3-VL-2Bテキストエンコーダという構成の軽さがそのまま出た数字で、Krea 2 Turbo(bf16拡散26GB+fp8テキストエンコーダ、ウォーム時約31GB常駐)と比べると約半分。

6. 出力品質

A blue ceramic mug on a white desk.A red apple on a wooden table.(README記載のデフォルト例文)の2種類で試した。
どちらも指定通りの被写体が生成され、素材の質感、光の反射、背景のボケも自然だった。
写実系の単純な静物プロンプトでは、1B turboでも破綻は見当たらない。

SeFi-Image 1B turboで生成した青いセラミックマグカップ。白い机の上、取っ手のハイライトや背景のボケも自然

SeFi-Image 1B turboで生成した赤いりんご。木製テーブルの上、へたの質感や果皮の反射も破綻なし

2B turboでも確認

1B turboと同じ手順で2B turbo(ModelScope経由、8.80GB)も試した。ロードもMPS実行も同様に通った。

フェーズ1B turbo2B turbo
モデルロード7.30秒12.09秒
生成(ウォーム、4step)13.1秒前後22.1〜22.6秒
1stepあたり約3.3秒約5.6秒
ピークメモリフットプリント約15.8GB約17.3GB

パラメータ数は1B→2Bで倍近くになったのに対し、生成時間は1.7倍程度で収まった。
ピークメモリフットプリントも15.8GBから17.3GBへ、増えたのは+1.5GBだけだった。

出力品質も1Bと同水準で、A blue ceramic mug on a white desk.のマグカップに破綻は見当たらなかった。

SeFi-Image 2B turboで生成した青いセラミックマグカップ。1Bと同一プロンプト・同一seedで質感の破綻なし

人物・アニメプロンプトでの挙動

静物系プロンプトは綺麗に出たので、2B turboで人物を含むプロンプトも試した。写実系はprofessional photography portrait系の品質語、アニメ系はcel shadingを指定した。

SeFi-Image 2B turboで生成した写実系の人物ポートレート。制服姿の人物自体は破綻していないが、背景と服の上に意味のない英字ラベルが複数浮いている

人物自体(髪型、制服、光の質感)に目に見える破綻はなさそう。ただし特に何も指定していないのに、背景や服の上にLE5mmBnnlyのような意味のない英字ラベルが複数浮いて出た。

SeFi-Image 2B turboで生成したアニメ系の人物イラスト。キャラクター自体はセルシェーディングで破綻していないが、背景の看板部分に読めない偽の漢字・仮名が大量に敷き詰められている

アニメ系はキャラクター自体(セルシェーディング、ポニーテール、制服)は破綻していないが、背景の看板のような部分に読めない偽の漢字・仮名が大量に敷き詰められた。
SeFi-Imageはモデルカードで、2言語で文字を書ける(bilingual-text-rendering)ことを特徴として掲げている。

この偽テキストがプロンプト次第でどこまで抑えられるかを確かめるため、条件を変えて4枚追加で試した。

プロンプトの変更点結果
85mm f1.4などカメラ仕様語を削り、背景を「plain room」に指定(写実、seed違い2枚)偽テキストなし
85mm f1.4だけ削り、professional photography portraitcinematicは残す(写実)偽テキストなし
背景を「plain background」に指定(アニメ)大部分は解消。左上に小さな偽ロゴ風の透かしと、胸の校章に読めない文字が1つ残る

SeFi-Image 2B turboで生成した写実系の人物ポートレート。カメラ仕様語を削っても偽テキストは出ず、髪や光の質感も自然

SeFi-Image 2B turboで生成したアニメ系の人物イラスト。背景をプレーンに指定すると看板状のテキスト羅列は消えるが、左上の透かしと校章の文字だけ残った

この時点では85mm f1.4のようなカメラのレンズ仕様表記がトリガーに見えていて、実際これを削って背景をシンプルにするだけで写実系は3枚とも偽テキストが消えた。
アニメ系は完全には消えないものの、看板を埋め尽くすレベルから小さな透かし1つまで消えた。
ただし4stepのturbo蒸留版での結果なので、50stepのBase/RL版でどこまで違うかは後述する。
sefi/pipeline.pysefi/cli.pysefi/runner.pyをgrepしてもnegativeという文字列は1件もヒットせず、ネガティブプロンプトを指定する引数がそもそもないので、狙って抑えることはできないようだ。

WaveCutのSpace(WaveCut/SeFi-Image)のExamplesもapp.pyのソースで確認した。人物ポートレート例では85mm lens lookmedium-format fashion photographyのような自然文でのレンズ描写は使われていて、85mm f1.4のような数値+f値の技術表記は見当たらない。
ただしこれらの例は5B RL・50step・guidance 4.0で生成されていて、今回試した2B turbo(4step・guidance 1.0)とは条件が違う。

そこでAnime cinematic portrait例のプロンプトを一字一句そのまま、2B turboの正規設定(4step・guidance 1.0・同一seed 7401)に入れて試した。

SeFi-Image 2B turboでSpaceのExamplesのプロンプトをそのまま生成した雨のTokyo路地のアニメ調ポートレート。色彩や雨・ネオンの雰囲気は出ているが、目の輪郭が頬に溶け込み口元の線も滲んでいて、左上と左下に偽のロゴ・文字が浮いている

色彩や雨・ネオンの雰囲気は出ているが、人物の輪郭は崩れている。
プロンプトのpainterly anime realismを汲んでも、絵画的タッチというより破綻に近い。
85mm f1.4を使っていないSpaceのExamplesそのままのプロンプトでもこの崩れと偽テキストの両方が出た。
これで「数値+f値の表記が引き金」という推測は外れた。
turbo版はTurboモデル側の制約でnum_inference_stepsが4/8/10しか受け付けず(50を渡すとValueErrorで弾かれる)、公式条件の50step・guidance 4.0では検証できていない。
turbo側の何か(4stepの蒸留か、guidance 1.0の推論設定か)に起因する疑いがあるが現状でははっきりわからない。

5B turboでも確認

5B turbo(HF経由、19GB弱)も試してみた。

フェーズ1B turbo2B turbo5B turbo
モデルロード7.30秒12.09秒31.83秒
生成(ウォーム、4step)13.1秒前後22.1〜22.6秒46.0〜47.7秒
1stepあたり約3.3秒約5.6秒約11.6秒
ピークメモリフットプリント約15.8GB約17.3GB約33.7GB

5Bになるとメモリの使用量が増えた。1B→2Bでは+1.5GBだったのに対し、2B→5Bでは+16.4GBとほぼ倍増した。

SeFi-Image 5B turboで生成した青いセラミックマグカップ。1B/2Bと同一プロンプト・同一seedで、質感のディテールがさらに上がっている

1B/2Bと比べると、マグカップの質感やハイライトの解像感がさらに増した。

3サイズ同一条件でのキャラクター比較

静物と偽テキストの検証に加えて、過去記事(Krea 2)でも使った「うちのキャラのフル指定」に相当するプロンプトを、1B/2B/5B turboの3サイズに同一プロンプト・同一seed(42)・同一step数(4)で投げてみた。
プロンプトはA high school girl with brown hair in a side ponytail on the right side, wearing a blue scrunchie, in a school uniform, standing in a plain room, soft natural lighting

SeFi-Image 1B turboで生成したサイドポニー・青スクランチーの女子高生キャラクター。指定通りの外見で偽テキストなし

SeFi-Image 2B turboで生成した同キャラクター。アニメ寄りの塗りで、髪型・スクランチーの色も指定通り

SeFi-Image 5B turboで生成した同キャラクター。写実寄りで解像感が高く、制服の校章も破綻なく描かれている

3サイズとも青スクランチー・制服という指定を守り、偽テキストも出なかった。
1Bは写実寄り、2Bはアニメ塗り寄り、5Bはより写実的で解像感の高い仕上がりで、同じプロンプトでもサイズごとに解釈が割れた。
85mm f1.4のような撮影技術語も看板が写り込むような情景も含まない今回のプロンプトでは、この規模のキャラクター指定はどのサイズでも安定して通った。

ただし3枚とも顔が左を向いた横顔になっていて、これはside ponytail on the right sideの解釈違いと思われる。
「頭のどちら側でポニーテールを結んでいるか」ではなく「ポニーテールが向いている方向」として読まれ、右向きのポニーテールを満たすために顔が左を向くプロフィール構図がどのサイズでも選ばれていた可能性が高い。

正面向き指定での再生成

プロンプトにfacing the camera, front viewを足して2B turboで生成し直した。

SeFi-Image 2B turboで正面向き指定を足して生成したキャラクター。斜め向きのままで、ポニーテールの結び目も頭頂〜やや左寄りに見え、右目の形や頬の陰影に不自然さが残る

SeFi-Image 2B turboで正面向き指定・別seedで生成したキャラクター。同様に斜め向きで、虹彩が過大で視線が微妙に合っていない

見直すと、期待したほど直っていない。
角度は斜め向きのままで、facing the cameraはほぼ効いていない。
ポニーテールの結び目も頭頂からやや左寄りの位置で、「サイド」という指定はほぼ無視され、ただの高い位置のポニーテールが右肩に流れているだけに見える。
さらに顔そのものにも粗が出た。
右目の目頭付近の形が歪で、頬に不自然な陰影が乗り、虹彩が異様に大きく視線がわずかに合っていない。
制服も襟元のリボンや胸ポケット周りの境界が溶けたように滲んでいて、布の折り目として成立していない。
facing the cameraを足してもside ponytail on the right sideの解釈違いは残り、顔と衣服の破綻も加わった。

5B RLを公式条件で検証

5B RL(HF経由、19GB弱、ダウンロード63分53秒)も取得した。
まず1B/2B/5B turboと同じ条件(mug、4step・guidance 1.0)で試したところ、ピントの甘いソフトな仕上がりになった。
公式Model Zooが示す5B RLの推奨推論設定は50step・guidance 4.0で、4stepは推奨設定から外れているためと思われる。

続けて公式のModel Zooどおり50step・guidance 4.0で同じmugプロンプトを生成し直した。

SeFi-Image 5B RLを50step・guidance4.0で生成した青いセラミックマグカップ。ピントは4stepより格段に合っているが、表面にランダムなブロッチ状のノイズが乗っている

4stepのソフトフォーカスは解消され、ピント自体は合っている。
ただし表面には斑点状のノイズが乗っていて、均一な釉薬の質感というよりざらついたノイズに近い。

フェーズ5B turbo(4step)5B RL(50step・guidance 4.0)
モデルロード31.83秒35.74秒
生成(ウォーム)46.0〜47.7秒1066〜1117秒(約17分46秒〜18分37秒)
1stepあたり約11.6秒約21.3〜22.3秒
ピークメモリフットプリント約33.7GB約33.7GB

今回の測定ではstep数やguidance scaleを変えてもピークメモリはturboと同水準で、生成時間だけが段違いに伸びた。
1stepあたりの時間はturboの約2倍で、これはCFG(guidance 4.0)だと条件付き・無条件の2回分の順伝播が走るため。
step数も50÷4で12.5倍、その積でturboの約22〜24倍の時間がかかる計算になり、実測の約23倍(1116秒÷47.7秒)とほぼ一致した。

Anime cinematic portrait例文も5B RLで再生成

本題のAnime cinematic portrait例文を、SpaceのExamplesと完全に同じ条件(5B RL・50step・guidance 4.0・seed 7401)で生成し直した。

SeFi-Image 5B RLをSpaceのExamplesと同条件で生成した雨のTokyo路地のアニメ調ポートレート。顔は破綻なく、髪や上着のカモ柄の質感も自然で、看板もそれらしいビジュアルに収まっている

2B turboで出ていた顔の崩れ(目頭の歪み、頬の不自然な陰影、視線のズレ)は見当たらない。
制服編と同様に指摘されていた「偽テキスト」も、看板部分にそれらしいネオン看板の絵として収まっていて、2B turboで出ていたような読めない文字の羅列や画面の隅に浮く偽ロゴは出なかった。
雨に濡れた髪、上着のカモ柄の布の質感、そばかすまで描き分けられていて、破綻箇所は見当たらなかった。

偽テキストや顔の崩れは、85mm f1.4のようなプロンプトの書き方の問題ではないようだ。
しかし比較できたのは2B turboと5B RLでサイズも学習方式も違うため、turbo蒸留だけが原因とまでは言い切れない。
一応5B RL(50step・guidance 4.0)ならどちらも出なくなったが、生成1枚に約18分かかった。