日本語特化の視覚言語モデル「sarashina2.2-vision-3b」を動かす

初めに

以下の記事にある「Sarashina2.2-Vision-3B」を動かしていきます

www.sbintuitions.co.jp

開発環境

環境構築

uvを使って環境構築をします。pyproject.tomlを作成します

[project]
name = "sarashina2-2-vision-3b"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "accelerate>=1.12.0",
    "pillow>=12.0.0",
    "protobuf>=6.33.2",
    "requests>=2.32.5",
    "sentencepiece>=0.2.1",
    "torch>=2.5.0",
    "transformers>=4.57.3",
]

[[tool.uv.index]]
name = "pytorch-cu124"
url = "https://download.pytorch.org/whl/cu124"
explicit = true

[tool.uv.sources]
torch = { index = "pytorch-cu124" }

次には依存関係をインストールします

uv sync

実行

次に推論をするコード (main.py) を作成します

"""
Sarashina2.2-Vision-3B サンプル実装
SB Intuitionsの日本語特化視覚言語モデル(VLM)を動かすためのスクリプト
"""

import requests
from PIL import Image
from transformers import AutoModelForCausalLM, AutoProcessor, set_seed


def load_model(model_name: str = "sbintuitions/sarashina2.2-vision-3b"):
    """モデルとプロセッサを読み込む"""
    processor = AutoProcessor.from_pretrained(
        model_name,
        trust_remote_code=True,
    )
    model = AutoModelForCausalLM.from_pretrained(
        model_name,
        torch_dtype="auto",
        device_map="cuda",
        trust_remote_code=True,
    )
    return model, processor


def load_image_from_url(url: str) -> Image.Image:
    """URLから画像を読み込む"""
    from io import BytesIO
    response = requests.get(url, headers={"User-Agent": "Mozilla/5.0"})
    return Image.open(BytesIO(response.content))


def load_image_from_file(path: str) -> Image.Image:
    """ファイルパスから画像を読み込む"""
    return Image.open(path)


def generate_response(
    model,
    processor,
    image: Image.Image,
    prompt: str,
    max_new_tokens: int = 512,
    temperature: float = 0.7,
    seed: int = 42,
) -> str:
    """画像とプロンプトからモデルの応答を生成する"""
    set_seed(seed)

    # チャットメッセージ形式でプロンプトを構築
    messages = [
        {
            "role": "user",
            "content": [
                {"type": "image", "image": image},
                {"type": "text", "text": prompt},
            ],
        }
    ]

    # プロセッサでテキストと画像を処理
    inputs = processor.apply_chat_template(
        messages,
        add_generation_prompt=True,
        tokenize=True,
        return_dict=True,
        return_tensors="pt",
    ).to(model.device)

    # 推論実行
    output_ids = model.generate(
        **inputs,
        max_new_tokens=max_new_tokens,
        temperature=temperature,
        do_sample=True,
    )

    # 入力トークンを除いて出力をデコード
    generated_ids = output_ids[:, inputs["input_ids"].shape[1] :]
    response = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]

    return response


def main():
    """メイン処理"""
    print("Sarashina2.2-Vision-3B を読み込んでいます...")
    model, processor = load_model()
    print("モデルの読み込みが完了しました")

    # サンプル画像(インターネットから取得)
    sample_image_url = "https://raw.githubusercontent.com/huggingface/transformers/main/tests/fixtures/tests_samples/COCO/000000039769.png"

    print(f"画像を読み込んでいます: {sample_image_url}")
    image = load_image_from_url(sample_image_url)

    prompt = "この画像に何が写っていますか?詳しく説明してください。"
    print(f"プロンプト: {prompt}")

    print("応答を生成しています...")
    response = generate_response(model, processor, image, prompt)

    print("\n=== モデルの応答 ===")
    print(response)


if __name__ == "__main__":
    main()

以下を実行します

uv run python main.py

以下の画像を使って実行しています

結果は以下になります

この画像には、2匹の猫がピンクのソファの上に横になって眠っている様子が写っています。

  - 2匹の猫(タビー柄)がソファでリラックスして寝ている
  - ソファは柔らかいピンク色のベルベットまたはアクリル毛布のような素材
  - 2本のリモコン(Sonyのロゴ)がソファの上に置かれている
  - 穏やかで温かみのある家庭のシーン