Qwen2.5-VL-7B-instructをローカルPCのvllm版で試す

Qwen2.5-VL-7B-instructとは、Qwenチームが開発したVisionタイプのLLMです。性能が高そうなので気になって動かしていましたが、やはり動作速度が気になってきます。

WEBで使用できるサービスが、Alibaba Cloudしか見つからなかったため、購入してあまり使っていないRTX 4090を有効活用しようと、昨日(2025/02/06)にvllmでQwen2.5-VL-7Bを対応させたマージを見つけたので実施してみました。

環境構築


環境構築にはwsl2でのuvを使用し、下記のコマンドで構築しました。

uv venv --python 3.12.8
source .venv/bin/activate
uv pip install "git+https://github.com/ywang96/vllm@qwen2_5_vl"
uv pip install "git+https://github.com/huggingface/transformers"
uv pip install flash-attn --no-build-isolation

** uv pip install "git+https://github.com/ywang96/vllm@qwen2_5_vl" **
環境によりますが、上記のbuild部分で数時間近くかかります。

環境構築がうまくいっていれば、下記のコマンドでさらに加速させることができます。(?) 対応してないモデルの場合は0に設定しなおしてください。

export $VLLM_USE_V1=1

vllm server 起動


下記コマンドで、vllmを起動します。
GPUを2枚使用するため、tensor_parallel_sizeを2に指定しています。
GPUを1枚だけで動かす場合は不要です。

uv run vllm serve Qwen/Qwen2.5-VL-7B-Instruct \
    --port 8000 \
    --host 0.0.0.0 \
    --tensor_parallel_size 2 \
    --dtype bfloat16
nvidia-smi
Fri Feb  7 04:04:58 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 566.36                 Driver Version: 566.36         CUDA Version: 12.7     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                  Driver-Model | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 3090      WDDM  |   00000000:01:00.0  On |                  N/A |
| 30%   42C    P8             34W /  350W |   20866MiB /  24576MiB |      3%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   1  NVIDIA GeForce RTX 4090      WDDM  |   00000000:02:00.0 Off |                  Off |
|  0%   31C    P8             16W /  450W |   19723MiB /  24564MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

RTX3090とRTX4090構成ですが、メモリ使用量が凄いです。
※ 他のソフトも動いているため、Qwenだけのせいではないです。
4090 1枚ではOut of memoryとなりました。
また、モデルのロードだけでもかなりの時間がかかります。(軽く数十分
できるならクラウドサービスなどでA100 80VRAMを借りた方がいいでしょう。(モデルロードも1,2分で済みましたし、トークン長も長くできます。)

PDFのOCR処理

首相官邸の過去ポスターで実験してみます。
https://www.kantei.go.jp/jp/headline/kansensho/pastflyers.html

from openai import OpenAI
from PIL import Image
from io import BytesIO
import base64

api_key = "dummy_key"
client = OpenAI(
    base_url="http://localhost:8000/v1/",
    api_key=api_key,
)

def get_image_completion(image_path: str, question: str, temperature: float = 0.7, top_p: float = 0.9):
    """
    画像をvLLMサーバーにリクエストし、質問に対する回答を得る。
    Args:
        image_path: 画像パス
        question: 質問
        temperature: (optional) 0から2の間の浮動小数点数。数値が大きいほど出力がランダムになる。デフォルトは0.7
        top_p: (optional) 0から1の間の浮動小数点数。temperatureとともに使用され、確率がtop_pを超えるトークンのみを考慮する。
    """
    try:
        # 画像をBase64エンコード
        image = Image.open(image_path)
        buffered = BytesIO()
        image.save(buffered, format="PNG")
        img_byte = buffered.getvalue()
        img_base64 = base64.b64encode(img_byte).decode('utf-8')

        # メッセージの作成 (OpenAIの形式に合わせる)
        messages = [
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": question},
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/png;base64,{img_base64}",
                            "detail": "high"
                        },
                    },
                ],
            }
        ]

        # APIリクエストの送信
        completion = client.chat.completions.create(
            model="Qwen/Qwen2.5-VL-7B-Instruct",
            messages=messages,
            max_tokens=518,
            temperature=temperature,  # 温度パラメータを設定
            top_p=top_p, # top_pパラメータを設定
        )

        return completion.choices[0].message.content

    except FileNotFoundError:
        return f"Error: Image file not found at {image_path}"
    except Exception as e:
        return f"Error: {e}"

if __name__ == "__main__":
    image_path = "./poster.png"
    question = """
    OCR処理してください
    """

    # temperatureとtop_pの値を指定して関数を呼び出す
    result = get_image_completion(image_path, question, temperature=0, top_p=0.8)
    print(result)

ご使用のipアドレスや、対象の画像パスに合わせて修正します。

結果

新型コロナウイルス
感染拡大防止へのご協力をお願いします
ワクチン接種後も、「マスクの着用」や
「手洗い」、「3密(密接・密集・密閉)回避」
などを徹底してください。

正しく使おうマスク!
①鼻の形に合わせ
すき間をふさぐ
②あご下まで伸ばし顔にす
き間なくフィットさせる
ポイント
会話時は必ず着用!
・鼻出しマスク× あごマスク×
・着けたら外側は触らない
・ひもを持って着脱
・品質の確かな、できれば不織布を

こまめにしよう
手洗い・手指消毒!
こんなタイミングでは必ず!
・共用物に触った後
・食事の前後
・公共交通機関の利用後 など
ポイント
指先・爪の間・指の間や手首も
忘れずに洗いましょう!

目指そうゼロ密!
一つの密でも避けましょう!!
密接
マスクなし× 大声×
密集
大人数× 近距離×
密閉
換気が悪い× 窄い所×

体調不良時の出勤・登校・移動はお控えください。
ワクチン未接種の方は接種をお願いします。

2022年版
首相官邸
Prime Minister's Office of Japan
厚生労働省
内閣官房
新型コロナウイルス等
感染症対策推進室
新型コロナウイルス
感染予防のために
(厚生労働省HP)

上記のようになりました。
3列構成やフォントサイズの大小、色などもありますが、無料で高速でここまでいけるのは衝撃です。
もっと複雑なレイアウトやプロンプトで試してみるのも有りですね。
Qwenモデルであるため、どうしても中国語が混ざってしまう事がありますが、vllmを使用すれば高速でプロンプトの試行錯誤ができるため、非常に助かります。

プロンプトによって大幅に結果が変わったりしてきますが、vllmのおかげで高速で・ローカルで・無料で(電気代や設備台を除く)OCRを試せる良い時代になりました。

注意点


uvを使うときに、uv pip install とuv syncを混ぜると大変な事になります。
conda と pip を混ぜて使うような感覚でやると数時間無駄にすることになるのでお気を付けを。



いいなと思ったら応援しよう!