Ollama: マルチモーダルモデル

マルチモーダルモデルはAIに目を与える——画像を見て言葉で記述、一目瞭然。

💡 ヒント: マルチモーダルモデル(llava、minicpm-vなど)はテキストのみのモデルより2〜3倍大きく、画像処理には追加のビジョンエンコーダー計算が必要なため、GPU高速化を強く推奨。CPUのみの環境では、マルチモーダルモデルの推論速度が実用にならないほど遅い場合がある(1-3 tok/s)。8GB以上のVRAMを持つGPUが、マルチモーダルモデルをスムーズに実行するための基本要件。

📋 前提条件: まず以下を習得していること

1. 学べること


2. SaaS創業者のリアルな事例

ℹ️ 情報: 現在Ollamaがサポートするマルチモーダルモデルは主にLLaVAシリーズ(llava、llava-llama3、minicpm-vなど)。視覚理解能力はGPT-4Vには及ばないが、UIスクリーンショット分析、OCR支援、商品記述のシナリオではすでに実用レベル。

💡 ヒント: マルチモーダルモデルではllava:7bよりllava:13bを推奨——13B版の視覚理解は大幅に改善されており、特に詳細記述が必要なシナリオ(UI要素の位置、チャートデータなど)で優位。7Bは単純分類向け、13Bは記述と分析向け。

(1) ペインポイント:ユーザーフィードバックのスクリーンショットが多すぎる

AliceのGlobalShop ECチームは毎日50件以上のユーザーフィードバックを受け取り、それぞれにUIスクリーンショットが付いている。手動でスクリーンショットを分析してフィードバックレポートを作成するのは時間がかかりすぎる。Aliceはこのプロセスを自動化したい。

(2) ソリューション:視覚モデルでスクリーンショットを自動分析

LLaVAモデルを使ってUIスクリーンショットを自動分析し、構造化フィードバックレポートを生成:

BASH
ollama run llava "What UI issues do you see in this image?" /path/to/screenshot.png

3. マルチモーダルモデルアーキテクチャ

⚠️ 警告: マルチモーダルモデル(llavaなど)はテキストのみのモデルより2〜3倍大きく、画像処理がより多くのVRAMを消費する。8GB VRAMのGPUでは低解像度画像しか処理できない場合がある;高解像度画像はOOM(メモリ不足)を引き起こす可能性。まず小さい画像でテストすること。

(1) 視覚言語モデル(VLM)の原理

100%
flowchart TD
    A[画像入力] --> B[ビジョンエンコーダー<br/>CLIP/ViT]
    B --> C[画像埋め込み]
    D[テキスト入力] --> E[テキストトークナイザー]
    E --> F[テキスト埋め込み]
    C --> G[射影レイヤー]
    F --> G
    G --> H[言語モデル<br/>LLaMA/Mistral]
    H --> I[テキスト出力]
コンポーネント 機能 モデル例
ビジョンエンコーダー 画像特徴量を抽出 CLIP ViT-L/14
射影レイヤー 視覚と言語の空間を整合 MLPアダプター
言語モデル テキスト記述を生成 LLaMA 2 / Mistral

(2) 利用可能なマルチモーダルモデル比較

モデル パラメータ サイズ 強み 画像タイプ
llava 7B 4.7 GB 汎用画像記述 写真/スクリーンショット/文書
llava-llama3 8B 5.5 GB より強力な推論+視覚 複雑なシーン理解
llava:13b 13B 7.4 GB 高精度 詳細認識
minicpm-v 8B 5.2 GB OCR+中国語 文書/表
bakllava 7B 4.7 GB 軽量・高速 単純画像

(3) ▶ サンプル:LLaVAのプルと実行

BASH
# Pull the multimodal model
ollama pull llava

# Basic image description (CLI with file path)
ollama run llava "Describe this image in detail" /path/to/photo.jpg

# Without image: text-only mode
ollama run llava "What is machine learning?"

出力:

TEXT
I'm a helpful AI assistant running locally on your machine...

4. CLI画像入力方式

(1) 2つの画像入力方式

⚠️ : 画像はモデルがサポートする最大解像度(通常336×336または448×448ピクセル)に自動的にスケーリングされてからモデルに入力される。非常に高解像度の元画像の細部はこの過程で失われる可能性。画像内の小さな文字や細部をモデルに認識させたい場合、画像全体を送るのではなく、重要な領域を切り抜いてから送信すること。

方式 構文 ユースケース
ファイルパス ollama run llava "prompt" /path/to/image.jpg ローカル画像、最もシンプル
インタラクティブ 対話内で.imageコマンドを使用 動的画像入力

(2) 対応画像フォーマット

フォーマット 拡張子 最大サイズ 備考
JPEG .jpg/.jpeg 制限内 写真に最適
PNG .png 制限内 スクリーンショット/テキスト内容
WebP .webp 制限内 Web画像
GIF .gif 最初のフレームのみ アニメーション非対応
⚠️ 注: 画像はモデルがサポートする解像度(通常336×336または448×448ピクセル)にスケーリングされる。非常に高解像度の画像の細部は失われる可能性がある。

(3) ▶ サンプル:CLIマルチモーダルインタラクション

BASH
# Start interactive session with image
ollama run llava

>>> .image /path/to/product-photo.jpg
>>> What product is shown and what are its key features?

# Output: The image shows a pair of premium wireless headphones...
# Key features include:
# 1. Over-ear design with memory foam cushions
# 2. Active noise cancellation
# 3. USB-C charging port visible on the left ear cup

>>> .image /path/to/chart.png
>>> Summarize the data trends shown in this chart

# Output: The chart displays quarterly revenue from 2023-2024...

出力:

TEXT
I'm a helpful AI assistant running locally on your machine...

5. REST APIマルチモーダル呼び出し

(1) APIリクエストフォーマット

/api/chat/api/generateの両方がimagesフィールドをサポートし、Base64エンコード画像を渡す:

フィールド 説明
images list[string] Base64エンコード画像リスト
各画像 string data:image/...プレフィックスなし

(2) ▶ サンプル:REST API Base64画像呼び出し

BASH
# Convert image to Base64 and call API
IMAGE_BASE64=$(base64 -w 0 /path/to/photo.jpg)

curl http://localhost:11434/api/chat -d "{
  \"model\": \"llava\",
  \"messages\": [{
    \"role\": \"user\",
    \"content\": \"Describe this image\",
    \"images\": [\"$IMAGE_BASE64\"]
  }],
  \"stream\": false
}"

出力:

TEXT
{"status":"ok","data":{}}

(3) ▶ サンプル:Python SDKマルチモーダル呼び出し

PYTHON
import ollama
import base64
from pathlib import Path

def analyze_image(image_path: str, prompt: str, model: str = "llava") -> str:
    """Analyze an image using a multimodal model."""
    # Read and encode image
    image_data = base64.b64encode(
        Path(image_path).read_bytes()
    ).decode("utf-8")

    response = ollama.chat(
        model=model,
        messages=[{
            "role": "user",
            "content": prompt,
            "images": [image_data]
        }],
        stream=False
    )
    return response["message"]["content"]

# Usage
result = analyze_image(
    "/path/to/screenshot.png",
    "List all UI issues you can identify in this screenshot"
)
print(result)

出力:

TEXT
# Function defined successfully

6. 実践シナリオ

(1) シナリオ比較

シナリオ 入力 推奨モデル プロンプト例
商品記述 商品写真 llava "Describe this product for an e-commerce listing"
バグ分析 UIスクリーンショット llava-llama3 "What UI bugs are visible in this screenshot?"
OCR支援 文書スキャン minicpm-v "Extract all text from this document image"
チャート解釈 データチャート llava "Summarize the trends in this data chart"
安全レビュー コンテンツ画像 llava "Does this image contain any unsafe content?"

(2) ▶ サンプル:AliceのUIスクリーンショット分析

PYTHON
import ollama
import base64
from pathlib import Path
import json

def analyze_ui_screenshot(image_path: str) -> dict:
    """Analyze a UI screenshot and return structured feedback."""
    image_data = base64.b64encode(
        Path(image_path).read_bytes()
    ).decode("utf-8")

    system_prompt = """You are a UI/UX expert reviewing application screenshots.
Analyze the screenshot and provide feedback in this JSON format:
{
  "issues": [{"type": "layout|color|text|accessibility", "description": "...", "severity": "high|medium|low"}],
  "summary": "Brief overall assessment"
}"""

    response = ollama.chat(
        model="llava-llama3",
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": "Review this UI screenshot for issues",
             "images": [image_data]}
        ],
        stream=False,
        format="json",
        options={"temperature": 0.3}
    )

    try:
        return json.loads(response["message"]["content"])
    except json.JSONDecodeError:
        return {"raw": response["message"]["content"]}

# Usage
feedback = analyze_ui_screenshot("/path/to/app-screenshot.png")
print(json.dumps(feedback, indent=2))

出力:

TEXT
# Function defined successfully

7. 総合サンプル:マルチモーダルカスタマーサービスアシスタントシステム

PYTHON
# ============================================
# Comprehensive: Multimodal customer service
# Image analysis + text chat for e-commerce
# ============================================

import ollama
import base64
from pathlib import Path
from dataclasses import dataclass
from typing import Optional

@dataclass
class MultimodalSupport:
    chat_model: str = "qwen2.5"
    vision_model: str = "llava"
    temperature: float = 0.3

    def handle_product_query(
        self, image_path: str, question: str
    ) -> str:
        """Answer product questions using image + text."""
        image_data = base64.b64encode(
            Path(image_path).read_bytes()
        ).decode("utf-8")

        response = ollama.chat(
            model=self.vision_model,
            messages=[{
                "role": "user",
                "content": f"Answer this question about the product shown: {question}",
                "images": [image_data]
            }],
            stream=False,
            options={"temperature": self.temperature}
        )
        return response["message"]["content"]

    def handle_damage_report(
        self, image_path: str, order_id: str
    ) -> str:
        """Process a damage report with photo evidence."""
        image_data = base64.b64encode(
            Path(image_path).read_bytes()
        ).decode("utf-8")

        # Step 1: Analyze damage from image
        damage_desc = ollama.chat(
            model=self.vision_model,
            messages=[{
                "role": "user",
                "content": "Describe the damage visible in this product photo. Be specific about the type and severity.",
                "images": [image_data]
            }],
            stream=False,
            options={"temperature": 0.2}
        )["message"]["content"]

        # Step 2: Generate response using chat model
        response = ollama.chat(
            model=self.chat_model,
            messages=[
                {"role": "system", "content": "You are an e-commerce customer service agent handling damage reports."},
                {"role": "user", "content": f"Order {order_id} has damage: {damage_desc}. Generate a polite response acknowledging the damage and explaining the refund/replacement process."}
            ],
            stream=False,
            options={"temperature": self.temperature}
        )
        return response["message"]["content"]

    def extract_text_from_image(
        self, image_path: str
    ) -> str:
        """OCR-like text extraction from document images."""
        image_data = base64.b64encode(
            Path(image_path).read_bytes()
        ).decode("utf-8")

        response = ollama.chat(
            model="minicpm-v",
            messages=[{
                "role": "user",
                "content": "Extract all visible text from this image. Preserve the original layout and formatting.",
                "images": [image_data]
            }],
            stream=False,
            options={"temperature": 0.1}
        )
        return response["message"]["content"]

# Usage
if __name__ == "__main__":
    service = MultimodalSupport()

    print("=== Damage Report ===")
    # print(service.handle_damage_report("damaged_item.jpg", "#12345"))

    print("=== Product Query ===")
    # print(service.handle_product_query("headphones.jpg", "Does this have noise cancellation?"))

    print("=== OCR Extraction ===")
    # print(service.extract_text_from_image("receipt.png"))

❓ よくある質問

Q マルチモーダルモデルとテキストのみのモデルは互換的に使える?
A いいえ。マルチモーダルモデルは画像+テキストを処理;テキストのみのモデルはテキストのみ処理。マルチモーダルモデルは画像なしのテキストのみ入力にも対応するが、テキストのみのモデルは画像を処理できない。
Q 画像解像度は推論速度に影響する?
A はい。高解像度画像はより多くのトークンをエンコードし、推論時間が増加する。Ollamaは自動的にモデルの最大サポート解像度にスケーリング——手動調整は不要。
Q 1枚の画像に複数の質問をできる?
A はい。プロンプトに複数の質問を列挙すると、モデルが順に回答する。ただし、1回の呼び出しで1〜2質問に絞る方が正確なレスポンスが得られる。
Q llavaの中国語能力はどう?
A llavaは主に英語向け。中国語の画像記述にはminicpm-vまたはqwen2.5-vl(利用可能な場合)を推奨。中国語プロンプトを使用すれば中国語で応答する。
Q 動画は処理できる?
A 現在Ollamaマルチモーダルは静止画像のみ対応。動画はキーフレームを画像として抽出し、フレームごとに分析する必要がある。GIFは最初のフレームのみ処理。
Q Base64エンコード画像が大きすぎる場合は?
A まず適切な解像度に圧縮(例:1024px以内)。JPEG品質80で通常十分。10MB以上の元画像は送信を避ける。

📖 まとめ


📝 練習問題

  1. 基本(難易度 ⭐):llavaモデルをプルし、CLIで商品写真を分析して特徴を記述する。
  2. 中級(難易度 ⭐⭐):Python SDKで画像+テキストのマルチターン対話を実装——まず画像内容を分析し、その分析に基づいて追加質問を行う。
  3. 上級(難易度 ⭐⭐⭐):Alice向けの自動UIスクリーンショットレビューツールを構築:スクリーンショットを入力し、構造化JSONバグレポート(タイプ、説明、重大度)を出力し、自動分類・アーカイブする。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%