rinnaの画像対話モデルをUIで試す。あとGradioの練習。

おうちで日本語で画像を使った会話ができるようになりましたよ、ということで、試してみます。

rinna 画像対話モデル

おとといrinnaから日英バイリンガルモデルが発表されました。
rinna、日英バイリンガル大規模言語モデルをオープンソースで公開|rinna株式会社

このモデルには画像対話モデルも含まれています。つまり、画像についてrinnaとチャットができるようになっています。
https://huggingface.co/rinna/bilingual-gpt-neox-4b-minigpt4

この画像対話モデルは、MiniGPT-4をベースにしています。
https://github.com/Vision-CAIR/MiniGPT-4

MiniGPT-4のVicuna + BLIP-2をrinna 3.6b + BLIP-2にした感じ。
Japanese MiniGPT-4: rinna 3.6bとBLIP-2を組み合わせてマルチモーダルチャットのモデルを作る

動かすとこんな感じ。大きく外れてはないな、という返答です。あと、簡潔。

メモリは11.4GBくらい使うので、12GB GPUだときつそう。

導入

導入として公式で書いてある手順はこんな感じ。MiniGPT-4をGitHubからcloneして22d8888ブランチを使う、と。

git clone https://github.com/Vision-CAIR/MiniGPT-4.git
cd ./MiniGPT-4
git checkout 22d8888 # latest version as of July 31, 2023.

そして、rinna用にカスタマイズしたMiniGPT-4のスクリプトとBLIP2-LLMのcheckpoint.pthをダウンロード。

wget https://huggingface.co/rinna/bilingual-gpt-neox-4b-minigpt4/resolve/main/customized_mini_gpt4.py
wget https://huggingface.co/rinna/bilingual-gpt-neox-4b-minigpt4/resolve/main/checkpoint.pth

Windowsの場合はwgetを使うにはPowerShellを使うのだけど、オプションなしだと単にネットからデータを読むだけになってしまうので-OutFileを付けて保存先を指定する。
そうすると「書き込んでいます」が出る。「読み込んでいます」だと読み込むだけになる。

あとはCUDAとかPyTorchとかTransformersとかsentencepieceとか、rinna 3.6bが動く状態を作っておく。

bitsandbytesを使っているのだけど、Windowsの場合はpipからインストールしても使えないので、こちらを。
https://github.com/jllllll/bitsandbytes-windows-webui

0.39.1を使っていますが、新しいものでも大丈夫だと思う。

python -m pip install bitsandbytes==0.39.1 --prefer-binary --extra-index-url=https://jllllll.github.io/bitsandbytes-windows-webui

あと、いままで使ってなかったものとして、omegaconf、iopath、timm、webdataset、decordのインストールが必要だった。

動かす

そしたらHow to use the model のところのコードが動かせるはず。
No module named 'decord'のようなエラーが出たらpip installしていく。

7.74GBのモデルのダウンロードなどがあったあと、こんな感じで表示される。

Loading VIT
freeze vision encoder
Loading VIT Done
Loading Q-Former
freeze Qformer
Loading Q-Former Done
Loading LLM
Loading LLM Done
Load BLIP2-LLM Checkpoint: ./checkpoint.pth
ユーザー: <Img><ImageHere></Img> What can you see?
システム: a cat on a table with a laptop
ユーザー: 猫はどんな体勢をしていますか?
システム:
寝ています

コードを見る

モデルをCustomizedMiniGPT4として定義してますね。

model = CustomizedMiniGPT4(gpt_neox_model="rinna/bilingual-gpt-neox-4b")
tokenizer = model.gpt_neox_tokenizer

そしてBIP2-LLMを読み込み

ckpt = torch.load(ckpt_path, map_location="cpu")
model.load_state_dict(ckpt['model'], strict=False)

会話に使う画像を読み込み。

image_url = "https://huggingface.co/rinna/bilingual-gpt-neox-4b-minigpt4/resolve/main/sample.jpg"
raw_image = Image.open(requests.get(image_url, stream=True).raw).convert('RGB')

そしてBLIP2-LLMを使って埋め込みベクトルに変換

vis_processor = Blip2ImageEvalProcessor()
image = vis_processor(raw_image).unsqueeze(0).to(model.device)
image_emb = model.encode_img(image)

プロンプトと画像埋め込みを結合した埋め込みベクトルを取得

embs = model.get_context_emb(prompt, [image_emb])

で、生成

output_ids = model.gpt_neox_model.generate(
    inputs_embeds=embs,
    max_new_tokens=512,
    do_sample=True,
    temperature=1.0,
    top_p=0.85,
    pad_token_id=tokenizer.pad_token_id,
    bos_token_id=tokenizer.bos_token_id,
    eos_token_id=tokenizer.eos_token_id
)

output = tokenizer.decode(output_ids.tolist()[0], skip_special_tokens=True)

UIをつける

いろいろ試したいのでGradioでUIを作る

with gr.Blocks() as demo:
  gr.Markdown("## multi modal rinna")
  imgIn = gr.Image(lambda: raw_image, type="pil")
  with gr.Row():
    upload = gr.Button("Upload", variant="primary")
    def_img = gr.Button("Default")
    upload.click(load_image, inputs=imgIn)
    def_img.click(init_image, outputs=imgIn)
  with gr.Row():
    with gr.Column():
      question = gr.Textbox(lines=3, placeholder="質問を")
      submit = gr.Button("Submit", variant="primary")
      with gr.Row():
        default = gr.Button("Default")
        clear = gr.Button("Clear")
        default.click(lambda: "画像を説明して", outputs=question)
        clear.click(lambda: "", outputs=question)
    answer = gr.Textbox(lines=3)
    submit.click(generate, inputs=question, outputs=answer)

demo.launch()

そしたら冒頭のUIができる。画面を横分割して画像を左側でもよかったな。

ソース全体はこちら。動かすとき、画像をD&DしただけではLLMに送られていないので気をつけてください。Uploadボタンを押す必要があります。
https://gist.github.com/kishida/ee107e002546ce2ab26c5d9a6eac33b1