西川和久の不定期コラム

ハイエンドGPUで実行可能なマルチモーダルAI「BAGEL」と、その専用チャットUIをバイブコーディング「Claude Opus 4」で作る!

 今回は画像生成にも対応するマルチモーダルなBAGELのご紹介と、後半は専用のChatUIを先日出たばかりのClaude Opus 4を使いバイブコーディングで作ってみたいと思う。

BAGELとは?

 ByteDanceは今年2025年5月20日にオープンなユニファイドマルチモーダルモデル、「BAGEL」をリリースした。アーキテクチャ的にはMixture-of-Transformer-Experts(MoT)の7Bアクティブパラメータ(14B total)となる。最近流行?の“<think></think>”モードも搭載する。

 性能について、Huggingfaceの資料によると、

1. Visual Understanding
ModelMMEMMBenchMMMUMM-VetMathVista
Janus-Pro-7B-79.241.050.0
Qwen2.5-VL-7B234783.558.667.168.2
BAGEL238885.055.367.273.1
2. Text-to-Image Generation · GenEval
ModelOverall
FLUX-1-dev0.82
SD3-Medium0.74
Janus-Pro-7B0.80
BAGEL0.88
3. Image Editing
ModelGEdit-Bench-EN (SC)GEdit-Bench-EN (PQ)GEdit-Bench-EN (O)IntelligentBench
Step1X-Edit7.096.766.7014.9
Gemini-2-exp.6.736.616.3257.6
BAGEL7.366.836.5244.0
BAGEL+CoT55.3

となっている。イメージ認識が「Qwen2.5-VL-7B」より上、txt2imgが「FLUX-1-dev」より上……と本当なのか!?と疑いの目で見てしまうものの(笑)、少なくとも同じ土俵に上がれる程度の実力はありそうだ。それがオープンでかつ、ディスクリートGPU搭載PCで動くのだから嬉しい限り。

 同じこと(画像生成/認識/編集)したいのであれば、ChatGPTを使うのが一般的だが、(性能はともかくとして)それがローカルPCでできるというのが筆者の目を引いた部分だ。

オンラインデモのChatUI

 ローカルPCで環境を作る前に、どの程度の実力か?オンラインデモを試してみた。

 まずイメージ認識。渋谷のスクランブル交差点で撮った写真を入れて、“Where is this”と聞いてみた。答えは……。

This is Shibuya Crossing in Tokyo, Japan. Shibuya Crossing is one of the busiest intersections in the world, known for its large number of pedestrians and its iconic status as a major tourist attraction. The image shows the bustling atmosphere and the numerous advertisements and billboards that are characteristic of this area.

これは東京の渋谷スクランブル交差点です。世界有数の混雑度を誇る交差点で、歩行者が多く、主要な観光名所として知られています。この画像では、このエリア特有の賑やかな雰囲気と、数多くの広告や看板が写っています。

※ Google翻訳

イメージ認識。写真は渋谷のスクランブル交差点だが、それなりの答えが返ってくる

 正解!ただし日本語のプロンプト「ここは何処ですか」と聞くと、「これは日本語の「新宿」(Shinjuku)の街中です。」と、日本語は認識しているものの、ちょっと妙な結果に。従ってプロンプトは英語にした方が良さそうだ。

 次はtxt2img。Promptは“Beautiful Japanese woman working in the office”。結果は以下の通り。

txt2imgとParameters設定。“Beautiful Japanese woman working in the office”からの画像生成。検閲かなり厳し目のようなので、ほどほどに(笑)

ちょっと中国っぽいがそれらしい実写が表示される。ダウンロードしてみたところ、解像度は768×1,024の3:4のようだ。この縦横比はParametersで変更可能。

GPU搭載PCで実行可能なGradio版WebUI

 デモのChatUIがそれなりに良かったので、ローカルPCで環境を作ることにした。リポジトリは「ansmom/BagelGradio」を使用。これはオリジナル、「ByteDance-Seed/Bagel」のフォーク版で、メインのブランチはオリジナルのままだが、もう1つ「gradio-feat」というブランチがあり、こちらでPython/LLMでお馴染みGradioを使ったWebUIが用意されている。

 今回はUbuntu 22.04+GeForce RTX 5090(32GB)の環境で動かすことにした。セットアップはこの手のものとしては簡単な方だろうか。まず、メインブランチを参考にして、

git clone https://github.com/ansmom/BagelGradio.git
cd BagelGradio
git checkout gradio-feat
conda create -n bagel python=3.10 -y
conda activate bagel
pip install -r requirements.txt
pip install gradio
pip install -U torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128

これでOKだ。次に必要なモデルなどのダウンロードと、そのPATHを合わせる。

down.py
save_dir = "D:/AI/BAGEL/models/BAGEL-7B-MoT"
※ 環境に合わせる。この時、フォルダ(フォルダ/cacheも)を作っておく

app.py
def load_model(offload_folder="./offload_data"):
    model_path = "D:/AI/BAGEL/models/BAGEL-7B-MoT"
※ 上記の環境に合わせる

これからも分かるように、開発者の環境はWindowsのようだ。修正が終わったら、

python down.py

これでモデルなどのダウンロードを開始するので、終了後、

python ui.py

でWebUIが起動する。筆者の場合、ほかのPCからもアクセスできるよう、

demo.launch()

demo.launch(server_name="0.0.0.0", server_port=8888)

と変更した程度となる。起動すると

undefined symbol: _ZN2at4_ops5zeros4callEN3c108ArrayRefINS2_6SymIntEEENS2_8optionalINS2_10ScalarTypeEEENS6_INS2_6LayoutEEENS6_INS2_6DeviceEEENS6_IbEE

とエラーになったので、調べてみたところ、

# flash-attn 2.5.8 → flash_attn 2.7.4.post1
pip install -U flash_attn==2.7.4.post1

へ。これで無事動作した。

BagelGradio起動
イメージ認識(お題は上記のChatUIと同じ)。約40秒

This is a picture of Shibuya Crossing in Tokyo, Japan. Shibuya Crossing is one of the busiest intersections in the world, known for its large number of pedestrians and its iconic status as a major tourist attraction.

txt2img(お題は上記のChatUIと同じ)。約220秒。ただあまり綺麗ではない

 このように動くのは動いたものの、パラメータ設定に縦横ピクセル指定がなかったので、気になり調べてみた。すると、inferencer.pyの中の254行目のdef interleave_inference()、279行目にimage_shapes = (1024, 1024)とあり、1,024×1,024ピクセルに決め打ちしているのが判明した。

パラメータ設定に縦横ピクセル指定がない

 これでは面白くないので、ui.pyに幅と高さを入力できるよう、項目を追加した。

with gr.Accordion("Parameters", open=False):
    with gr.Row(): # 追加
        img_width = gr.Number(label="幅", value=672)  # 追加
        img_height = gr.Number(label="高さ", value=1024) # 追加

 次に、run_inference_step_by_step()へこの2つのパラメータを追加、最終的にinferencer.pyのinterleave_inference()を呼んでるので、こちらへも追加。

    def interleave_inference(
        self,
        input_lists: List[Union[str, Image.Image]],
.
.
.
        output_dir: str = "./generated_images",
        img_shapes: Tuple[int, int] = (1024, 1024),  # 追加。デフォルト1024x1024
    ) -> Tuple[List[Union[str, Image.Image, None]], Any, Optional[str]]:

        output_list = []
        saved_image_path = None # To store the path if an image is saved

        gen_context = self.init_gen_context()
        image_shapes = img_shapes # (1024, 1024)から変更

 これで無事縦横ピクセルをWebUIで指定できるようになった。ただし長辺が1,024ピクセルを超えるとOOM(Out Of Memory)になりやすいので要注意。VRAM 32GBなのだが……(笑)。

無事WebUIで縦横ピクセル指定可能に。お題は先と同じ。768×1,024ピクセルで出力されている。約200秒
768×1,024ピクセルでのVRAM使用状況は22~23GB。GeForce RTX 4090(24GB)だとギリギリ

 これらの結果から分かるように、イメージ認識はともかくとして、txt2imgは画質、生成速度共にイマイチという感じか。

 原稿をほぼ書き終えたタイミングで本家、ByteDance-Seed/BagelのリポジトリでGradioを使ったWebUIが公開されたので動かしたのが以下の画面キャプチャとなる。

 修正箇所はapp.pyの22行目のmodel_path = 。ここは先のdown.pyに設定したフォルダにしておくと二重にモデルなどをダウンロードせずに済む。

 もう1カ所、これはバグだと思うが、89行のmodel = load_checkpoint_and_dispatch()、offload_buffers=Trueなのに、offload_folderの指定がなくエラーで落ちる。そこで以下の1行を追加。これで無事起動する。

model = load_checkpoint_and_dispatch(
    model,
    checkpoint=os.path.join(model_path, "ema.safetensors"),
    device_map=device_map,
    offload_buffers=True,
    dtype=torch.bfloat16,
    force_hooks=True,
    offload_folder="./offload_data", # 追加
).eval()

 見るとtxt2imgが2種類あり、1つは普通のtxt2img、もう1つはthinkした後にtxt2img。つまり後者は処理的にプロンプト拡張と同じとなる。image editはimg2img。

本家ByteDance-Seed/BagelのWebUI。明示的にthinkの有無と、image editモードがある。これはthinkありのtxt2img。Promptと画像の間にあるのが<think></think>の結果。これをtxt2imgに渡している

 画面キャプチャはthinkした後にtxt2imgを行なったものだが、着物を着ているのが分かる。確認したところ、<think></think>の中には“wearing traditional Japanese attire such as a kimono or a modern business suit”という記述があった。海外生成AIあるあるなのだが、日本人=着物と決めつけるのは、勘弁してほしいところ。

Gradio版UIを参照しつつバイブコーディングでChatUIを作る

 BAGELはイメージ認識、txt2imgだけでなく、画像の編集機能もある。ただ上記のWebUIだとイマイチやりにくい(本家ByteDance-Seed/BagelのWebUIが出る前の話)のでChatUIを作りたい。と言って真面目にコーディングするのも面倒なので、AIお任せのバイブコーディングにチャレンジしてみた。

 1月は「VSCode+Roo Code(旧Roo-Cline)」としたが 、今回は先日出たばかりの「Claude Opus 4」をClaude Desktop上でui.pyをペースト、結果をchat.pyへペーストして実行してみた。つまり筆者は1文字もコーディングしていない。

  • 以下のコード(ui.py)、chat形式にしてください

もともと指示はこれだけ。実行して確認、さらに指示を出す感じだ。仕事の場合は、始めに仕様をそれなりに入れるのだが、今回は、反応を見たかったこともあり、五月雨式でやりとりした。これはこれで「そう来たか!」と面白い(笑)。

Claude Desktop/Claude Opus 4でいろいろ指示しているところ
  • 画像出ましたが縦横比が変わってます。維持してください
  • chatエリアの高さを1.5倍へ。画像をuploadするエリアももう少し縦に長く
  • chatでの画像はダウンロード可能なボタンを。この時、フォーマットはjpgで、名前も重複しないように
  • 画像生成の処理速度が遅いのですが、stepを変える以外、速くする方法ないですか?
  • 「前の出力の直接編集」に対応できますか?
  • output側に推論時間をいれてください

上記の指示を徐々に加え、最終的なバージョンは以下の通り(というよりプロプランの利用制限超えたのでいったんここまで)。

イメージ認識(1/3)
画像生成。512×768ピクセルに解像度落としても約1分半(2/3)
直近の画像を引き継いでプロンプトに対応するかのテスト“夜へ”(3/3)
オリジナル画像
若干変わっているものの、一貫性を保ったまま夜になった

 画像のダウンロードもうまく動き、“bagel_assistant_20250524_135642_122.jpg”といった重複しないファイル名になっている。

 軽くテスト的に作った割にはそれなりの感じだろうか。今回chat.pyは単一ファイルで500行未満のため、安直にClaude Desktopを使ったが、もう少しいろいろファイルが関係するプログラムの場合は、やはりVSCode+Roo Codeの方が使い勝手は良い。


 以上のようにオープンなマルチモーダル、BAGELのご紹介と、Gradioで書かれたWebUIをバイブコーディングでChatUIに変身させてみた。BAGELは、ローカルPCで動くという意味では興味深いのだが、とにかくGeForce RTX 5090を使っても処理が遅いのは残念なところ。

 一方、バイブコーディングに関しては今回かなり簡単(雑)な例。個人的にはClaude Sonnet 3.7とClaude Opus 4、コーディングに関してはそこまで大きな差はないように思えた(ほかの開発でも試用している)。

 現在、開発系の仕事でもAIを使い出しており、B2Bや業務系のシステムなど大きめの案件もやればできるレベルになってきた。コツは“とにかくコードは見ず(笑)、指示に徹すること”だろうか。雰囲気的に、筆者:仕様を作って→部下:コーディング→筆者:レビューしてダメ出し……に似てて面白い(笑)。

 AI(バイブ)コーディングは、人によっていろいろ見方はあるだろうが、筆者の場合、優秀なアシスタント君が1人いる感じ。とにかく自分が楽できるのならこれほど便利なツールはない!といったところだろうか。