【ローカルVLM】Qwen2.5-VLをPythonで動かす!オープンソース最高峰の視覚言語モデルによる画像・動画解析実践ガイド
AIによる画像認識の技術は、単に「何が写っているか」を判定するレベルから、画像や動画の「文脈やストーリーを言葉で理解し、複雑な問いに答える」マルチモーダルなアプローチへと急激に進化しています。
その中心に位置するのが、Alibaba Cloudが開発・公開しているオープンソースの視覚言語モデル(VLM: Vision-Language Model)「Qwen2.5-VL」です。前モデルのQwen2-VLからさらに大幅なアップデートを遂げ、高精度なOCR、複数画像の同時比較、さらには数分に及ぶ動画の時系列解析まで、商用クローズドモデルに匹敵する性能をローカル環境で実現できるようになりました。
本記事では、この注目のオープンソースVLM「Qwen2.5-VL-7B-Instruct」を、Pythonを用いてローカル環境で動かすための具体的な実装手順と実用的なコード、そして誰もが直面しやすいVRAM不足対策などのトラブルシューティングを詳しく解説します。
1. Qwen2.5-VLがもたらす革新と主な特徴
Qwen2.5-VLは、現在のオープンソースVLM界隈で最も注目されているモデルの一つです。その主な強みは以下の3点にあります。
- 超高精度なOCRとドキュメント解析: 手書きの文字や、複雑な図表、Webサイトのスクリーンショット、数式や複雑なレイアウトのPDFでも高い精度でテキストを抽出し構造化します。
- 動画の時間的文脈の理解: 動画(数分〜数十分規模)を入力し、「何分何秒の時点で何が起きたか」や「全体を通してどのような変化があったか」を正確に説明できます。
- バウンディングボックスの出力(グラウンディング): 指定した物体が画像内のどこにあるかを「
[ymin, xmin, ymax, xmax]」の座標値として正確に特定でき、GUIエージェント(画面自動操作AI)の基盤としても活用されています。
これらの能力の背景には、入力解像度を動的に調整してアスペクト比を損なわずに特徴を捉える「Naive Dynamic Resolution」などの独自技術があります。最新の開発状況については、公式の Qwen2.5-VL GitHubリポジトリ で詳細なソースコードやロードマップが公開されています。
2. 環境構築と前提条件
Qwen2.5-VL(特に7Bモデル)をローカル環境で動作させるには、GPU(NVIDIA製、VRAM 16GB以上推奨)を搭載した環境が理想的です。本ガイドでは、CUDA 12.1以上の環境を前提とします。
まず、必要な依存ライブラリをインストールします。Qwen2.5-VLを動かすには、最新の transformers ライブラリと、画像処理のヘルパーライブラリである qwen-vl-utils が必須です。
# PyTorchと関連パッケージのインストール(環境に応じて選択してください)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
# Qwen2.5-VLに必要なライブラリ群のインストール
pip install "transformers>=4.49.0" qwen-vl-utils accelerate flash-attn --no-build-isolation
注意: Qwen2.5-VLを正常に動作させるには、
transformersライブラリのバージョンが 4.49.0以上 である必要があります。古いバージョンではモデルをロードできないため、必ず最新版に更新してください。
各モデルの重みファイルは、QwenのHugging Faceリポジトリ から初回実行時に自動でダウンロードされます。
3. Pythonによる実践!画像・動画解析の実装手順
それでは、実際にQwen2.5-VLをPythonで動かすコードを見ていきましょう。ここでは「Qwen2.5-VL-7B-Instruct」を使い、ローカル上の画像を解析する方法と、動画ファイルを解析する方法の2種類を紹介します。
3.1 画像の文字起こしと詳細解析
まずは、ローカルにある画像、あるいはウェブ上の画像URLを指定して詳細に解析するスクリプトです。
import torch
from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
from qwen_vl_utils import process_vision_info
# 1. モデルとプロセッサのロード
model_id = "Qwen/Qwen2.5-VL-7B-Instruct"
# VRAM消費を抑えるため、bfloat16精度でロード
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
model_id,
torch_dtype=torch.bfloat16,
attn_implementation="flash_attention_2",
device_map="auto"
)
processor = AutoProcessor.from_pretrained(model_id)
# 2. プロンプトと画像情報の準備
# ローカルパス(例: "./sample.jpg")またはインターネット上のURLを指定可能
messages = [
{
"role": "user",
"content": [
{
"type": "image",
"image": "https://images.unsplash.com/photo-1543269865-cbf427effbad?w=800"
},
{
"type": "text",
"text": "この画像に写っている人々の様子や場所の雰囲気を日本語で詳しく説明してください。"
}
]
}
]
# 3. 入力データの前処理
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(
text=[text],
images=image_inputs,
videos=video_inputs,
padding=True,
return_tensors="pt"
).to("cuda")
# 4. 回答の生成
with torch.no_grad():
generated_ids = model.generate(**inputs, max_new_tokens=512)
# 入力トークンを除外してデコード
generated_ids_trimmed = [
out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
]
output_text = processor.batch_decode(
generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
)
print("=== Qwen2.5-VLの回答 ===")
print(output_text[0])
3.2 動画ファイルの時系列解析
次に、動画ファイルを読み込ませて「何が起きたか」を分析する高度なユースケースです。Qwen2.5-VLは、動画内の複数フレームを効率的にエンコードする仕組みを備えています。
# 動画解析用のメッセージ構造
# ローカルに保存された mp4 等のファイルを指定できます
video_messages = [
{
"role": "user",
"content": [
{
"type": "video",
"video": "./sample_video.mp4",
"fps": 1.0, # 1秒あたりに抽出するフレーム数。負荷低減のため調整推奨
},
{
"type": "text",
"text": "動画全体の要約と、何秒あたりに特筆すべき動きがあるかをタイムスタンプ付きで日本語で教えてください。"
}
]
}
]
# 画像の時と同様に前処理を行って生成(手順は画像と同様)
text_video = processor.apply_chat_template(video_messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(video_messages)
inputs_video = processor(
text=[text_video],
images=image_inputs,
videos=video_inputs,
padding=True,
return_tensors="pt"
).to("cuda")
with torch.no_grad():
generated_ids = model.generate(**inputs_video, max_new_tokens=512)
generated_ids_trimmed = [
out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs_video.input_ids, generated_ids)
]
output_video_text = processor.batch_decode(
generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
)
print("=== 動画解析の回答 ===")
print(output_video_text[0])
4. トラブルシューティング:よく遭遇するエラーと解決策
ローカルで大型のVLMモデルを動作させる際、特に初心者が直面しやすい問題とその対処法をまとめました。
① CUDA Out of Memory (OOM) でクラッシュする
原因: Qwen2.5-VLは入力画像の解像度を動的に調整するため、4Kなどの高解像度画像や、長時間の動画を入力すると内部トークン数が急増し、GPUのメモリ(VRAM)をすべて消費してしまいます。
解決策:
- 最大解像度の制限:
qwen-vl-utilsを使用する際、モデルに送る画像の解像度を制限できます。環境変数やコード内で画像サイズ(ピクセル数)の上限を指定してください。# 入力画像ピクセル数の最大・最小を明示的に指定してVRAMを保護する # (メッセージ定義の内部で設定可能です) { "type": "image", "image": "https://example.com/large.jpg", "max_pixels": 512 * 512 # 例として解像度を抑える } - 4-bit / 8-bit 量子化の適用:
bitsandbytesライブラリを使用してモデルを量子化してロードすることで、VRAMの消費量を劇的に抑えられます(16GB VRAMでも7Bモデルが安定して動作します)。from transformers import BitsAndBytesConfig quantization_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16 ) model = Qwen2_5_VLForConditionalGeneration.from_pretrained( model_id, quantization_config=quantization_config, device_map="auto" )
② ValueError: Unrecognized model class が出力される
原因:
ご使用の transformers ライブラリのバージョンが古く、Qwen2_5_VL クラスを認識できていません。
解決策: ライブラリを最新のバージョンにアップデートします。
pip install -U transformers
また、キャッシュされた古いコードとの競合を防ぐため、Python環境の再起動(またはJupyter Notebookのカーネル再起動)を行ってください。詳細なAPIの仕様については、Qwen公式ドキュメントサイト も併せてご確認ください。
5. まとめ
Qwen2.5-VLは、オープンソースのマルチモーダルAIがまた一つ大きな進化を遂げたことを証明する強力なモデルです。商用の高額なAPIを利用することなく、完全にセキュアなローカル環境で高度な画像解析や動画認識、そして精密なOCRパイプラインをPythonから簡単に構築できるメリットは計り知れません。
完全ローカル環境でAIを動かす手段としては、以前紹介した Transformers.js v3を用いてブラウザ上でローカルAIを動かす方法 などのアプローチもありますが、今回のQwen2.5-VLはより高度かつプロフェッショナルな視覚タスクにおいて圧倒的なアドバンテージを持っています。
また、Macのローカル環境(Apple Silicon)においてLLMの動作速度を極限まで引き出したい方は、MLXを用いたMacローカルでのLLM実行・ファインチューニング手順 も大いに参考になるはずです。
ビジネスドキュメントの自動整理や、動画監視データの解析、GUI操作の自動化など、Qwen2.5-VLの強力なビジョン機能をぜひあなたの開発プロジェクトに取り入れてみてください!