Microsoftから公開されたPhi-3-visionをTransformers + MacのGPUを使って動かしました。
Phi-3-visionとは
Microsoftが公開してる小規模言語モデルの中でマルチモーダル対応されたモデルです。他のPhi-3のモデル同様、パラメータ数4.2Bという一般的に公開されているモデルと比べると少ないパラメータでありながら、高い精度で動作するモデルです。
準備
モデルのダウンロード
以下からモデルのダウンロードを行います。
flash-attentionの無効化
Macやwindowsではflash-attentionを利用することができないため、以下のrunning-on-windows-or-without-flash-attentionの内容に従ってファイルを編集します。
modeling_phi3_v.pyの以下の内容をコメントアウトします。
# if is_flash_attn_2_available(): # from flash_attn import flash_attn_func, flash_attn_varlen_func # from flash_attn.bert_padding import index_first_axis, pad_input, unpad_input # noqa # _flash_supports_window_size = "window_size" in list(inspect.signature(flash_attn_func).parameters)
実行用コードの準備
実行のためにPhi-3-visionのモデルがあるディレクトリに以下のコードをmain.pyとして保存します。 実行にはGradioが必要です。
import gradio as gr import numpy as np from PIL import Image import torch from transformers import AutoModelForCausalLM from transformers import AutoProcessor device = torch.device('mps') model_name = "./" processor = AutoProcessor.from_pretrained(model_name, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True, torch_dtype="auto", _attn_implementation="eager").to(device) user_prompt = '<|user|>\n' assistant_prompt = '<|assistant|>\n' prompt_suffix = "<|end|>\n" def generate_response(input_text, input_image): prompt = f"{user_prompt}" images = None if isinstance(input_image, np.ndarray): prompt += f"<|image_1|>\n" images = [Image.fromarray(input_image)] elif isinstance(input_image, Image.Image): prompt += f"<|image_1|>\n" images = [input_image] if input_text != "": prompt += f"{input_text}" prompt += f"{prompt_suffix}{assistant_prompt}" print(f">>> Prompt\n{prompt}") inputs = processor(prompt, images=images, return_tensors="pt").to(device) generate_ids = model.generate(**inputs, max_new_tokens=1000, eos_token_id=processor.tokenizer.eos_token_id, ) generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:] response = processor.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0] print(f'>>> Response\n{response}') return response def main(): with gr.Blocks() as page: image = gr.Image(type="pil") input_text = gr.Textbox() output_text = gr.TextArea(label="decoded text") gr.Interface(fn=generate_response, inputs=[input_text, image], outputs=output_text) page.launch(inbrowser=True) if __name__=="__main__": main()
cudaを利用できる環境の場合は以下のように書き換えてください。
device = torch.device('cuda')
実行環境
- OS:MacOS Sonoma
- SoC:M3 Pro (CPU 12C GPU 18C)
- RAM:18GB
- Python:3.11.9
- Torch:2.4.0dev
- Transformers:4.40.0
実行結果
テキストのみを入力するケースとテキストと画像を入力するケースを試しました。
テキストのみの実行では以下のレスポンスの生成に270秒かかりました。
また、画像を含めた生成の場合も以下のレスポンス生成に250秒かかりました。
Macで実行した場合は生成にかなり時間を要するため実用するのは難しいと感じました。
windows + CUDAの環境では、Flash-Attentionが無効の状態でも30秒ほどで以下のような出力を得ることができました。
終わりに
Phi-3-visionは小型軽量でありながら精度の高いマルチモーダルモデルだと感じました。画像を入力できるようになったことでより幅広いタスクへの利用が可能になりました。 WIndowsでの動作やLinuxでFlash-Attentionの利用を有効にした状態での動作も確認していきたいです。