Ollama: マルチモーダルモデル
マルチモーダルモデルはAIに目を与える——画像を見て言葉で記述、一目瞭然。
💡 ヒント: マルチモーダルモデル(llava、minicpm-vなど)はテキストのみのモデルより2〜3倍大きく、画像処理には追加のビジョンエンコーダー計算が必要なため、GPU高速化を強く推奨。CPUのみの環境では、マルチモーダルモデルの推論速度が実用にならないほど遅い場合がある(1-3 tok/s)。8GB以上のVRAMを持つGPUが、マルチモーダルモデルをスムーズに実行するための基本要件。
📋 前提条件: まず以下を習得していること
- レッスン4: モデル管理
1. 学べること
- マルチモーダルモデルのアーキテクチャ:ビジョンエンコーダー + 言語デコーダー
- CLI画像入力方式
- REST APIマルチモーダル呼び出し:imagesフィールド
- 実践シナリオ:商品記述、バグ分析、OCR支援
- AliceのUIスクリーンショット分析シナリオ
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)の原理
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以上の元画像は送信を避ける。
📖 まとめ
- マルチモーダルモデル = ビジョンエンコーダー + 射影レイヤー + 言語モデル、画像テキスト理解を実現
- llavaシリーズはOllamaの主要な視覚モデル、写真/スクリーンショット/文書に対応
- CLIはファイルパスで画像入力、APIはBase64エンコードのimagesフィールドを使用
- 実践シナリオ:商品記述、バグ分析、OCR支援、チャート解釈
- Python SDKはimagesリストでBase64画像データを渡す
- AliceはllavaでUIスクリーンショット分析を自動化、1件あたり10分から5秒に短縮
📝 練習問題
- 基本(難易度 ⭐):llavaモデルをプルし、CLIで商品写真を分析して特徴を記述する。
- 中級(難易度 ⭐⭐):Python SDKで画像+テキストのマルチターン対話を実装——まず画像内容を分析し、その分析に基づいて追加質問を行う。
- 上級(難易度 ⭐⭐⭐):Alice向けの自動UIスクリーンショットレビューツールを構築:スクリーンショットを入力し、構造化JSONバグレポート(タイプ、説明、重大度)を出力し、自動分類・アーカイブする。