blip-2-vision-language について
BLIP-2 は、画像キャプション、視覚質問応答、画像と言語の理解に使うビジョン・ランゲージモデルのスキルです。マルチモーダルアプリを開発する人向けで、Q-Former により凍結された画像エンコーダーと LLM を接続します。
主な機能
- 01自然な画像キャプションの生成
- 02画像に関する質問への回答
- 03ゼロショットの画像・テキスト理解
- 04照合用の画像・テキスト特徴の抽出
- 05OPT または FlanT5 の言語モデルバックエンド
- 06HuggingFace Transformers または LAVIS で実行
活用シーン
- 01画像コレクションのキャプション作成
- 02視覚質問応答システムの構築
- 03テキストまたは画像特徴による画像検索
- 04マルチモーダルアプリへの視覚理解の追加
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ kalarislabs/ research-agent-skills --skill blip-2-vision-languageインストール後、Claude Code で/blip-2-vision-languageを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/advanced-usage-2.mdadvanced-usage.mdtroubleshooting.md詳細
BLIP-2:視覚と言語の事前学習
凍結された画像エンコーダーと大規模言語モデルを使用した視覚と言語のタスクで、Salesforce の BLIP-2 を利用するための包括的なガイドです。
BLIP-2 を使用する場面
次のような場合は BLIP-2 を使用してください:
- 自然な説明による高品質な画像キャプション生成が必要な場合
- 視覚的質問応答(VQA)システムを構築する場合
- タスク固有の学習なしで、ゼロショットの画像とテキストの理解が必要な場合
- 視覚タスクで LLM の推論能力を活用したい場合
- マルチモーダルな会話型 AI を構築する場合
- 画像とテキストの検索やマッチングが必要な場合
主な機能:
- Q-Former アーキテクチャ:軽量なクエリトランスフォーマーが視覚と言語を橋渡しします
- 凍結バックボーンによる効率性:大規模な視覚モデルや言語モデルをファインチューニングする必要はありません
- 複数の LLM バックエンド:OPT(2.7B、6.7B)および FlanT5(XL、XXL)
- ゼロショット機能:タスク固有の学習なしでも高い性能を発揮します
- 効率的な学習:学習対象は Q-Former のみです(約 188M パラメーター)
- 最先端の結果:VQA ベンチマークで、より大規模なモデルを上回ります
代わりに次のものを使用してください:
- LLaVA:指示追従型のマルチモーダルチャット向け
- InstructBLIP:指示追従性能の向上が必要な場合(BLIP-2 の後継)
- GPT-4V/Claude 3:本番環境向けのマルチモーダルチャット(プロプライエタリ)
- CLIP:生成を伴わないシンプルな画像とテキストの類似度判定向け
- Flamingo:少数ショットの視覚学習向け
クイックスタート
インストール
# HuggingFace Transformers (recommended)
pip install transformers accelerate torch Pillow
# Or LAVIS library (Salesforce official)
pip install salesforce-lavis
基本的な画像キャプション生成
import torch
from PIL import Image
from transformers import Blip2Processor, Blip2ForConditionalGeneration
# Load model and processor
processor = Blip2Processor.from_pretrained("Salesforce/blip2-opt-2.7b")
model = Blip2ForConditionalGeneration.from_pretrained(
"Salesforce/blip2-opt-2.7b",
torch_dtype=torch.float16,
device_map="auto"
)
# Load image
image = Image.open("photo.jpg").convert("RGB")
# Generate caption
inputs = processor(images=image, return_tensors="pt").to("cuda", torch.float16)
generated_ids = model.generate(**inputs, max_new_tokens=50)
caption = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(caption)
視覚的質問応答
# Ask a question about the image
question = "What color is the car in this image?"
inputs = processor(images=image, text=question, return_tensors="pt").to("cuda", torch.float16)
generated_ids = model.generate(**inputs, max_new_tokens=50)
answer = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(answer)
LAVIS ライブラリの使用
import torch
from lavis.models import load_model_and_preprocess
from PIL import Image
# Load model
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model, vis_processors, txt_processors = load_model_and_preprocess(
name="blip2_opt",
model_type="pretrain_opt2.7b",
is_eval=True,
device=device
)
# Process image
image = Image.open("photo.jpg").convert("RGB")
image = vis_processors["eval"](image).unsqueeze(0).to(device)
# Caption
caption = model.generate({"image": image})
print(caption)
# VQA
question = txt_processors["eval"]("What is in this image?")
answer = model.generate({"image": image, "prompt": question})
print(answer)
基本概念
アーキテクチャの概要
BLIP-2 Architecture:
┌─────────────────────────────────────────────────────────────┐
│ Q-Former │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Learned Queries (32 queries × 768 dim) │ │
│ └────────────────────────┬────────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼────────────────────────────┐ │
│ │ Cross-Attention with Image Features │ │
│ └────────────────────────┬────────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼────────────────────────────┐ │
│ │ Self-Attention Layers (Transformer) │ │
│ └────────────────────────┬────────────────────────────┘ │
└───────────────────────────┼─────────────────────────────────┘
│
┌───────────────────────────▼─────────────────────────────────┐
│ Frozen Vision Encoder │ Frozen LLM │
│ (ViT-G/14 from EVA-CLIP) │ (OPT or FlanT5) │
└─────────────────────────────────────────────────────────────┘
モデルのバリエーション
| モデル | LLM バックエンド | サイズ | 用途 |
|---|---|---|---|
blip2-opt-2.7b | OPT-2.7B | ~4GB | 一般的なキャプション生成、VQA |
blip2-opt-6.7b | OPT-6.7B | ~8GB | より優れた推論 |
blip2-flan-t5-xl | FlanT5-XL | ~5GB | 指示追従 |
blip2-flan-t5-xxl | FlanT5-XXL | ~13GB | 最高品質 |
Q-Former の構成要素
| 構成要素 | 説明 | パラメーター |
|---|---|---|
| 学習可能なクエリ | 学習可能な埋め込みの固定セット | 32 × 768 |
| 画像トランスフォーマー | 視覚特徴へのクロスアテンション | 約 108M |
| テキストトランスフォーマー | テキスト用のセルフアテンション | 約 108M |
| 線形射影 | LLM の次元にマッピング | 変動 |
応用的な使い方
詳細、コード例、パラメーター表については、references/advanced-usage-2.md を参照してください。この手順が該当する場合に確認してください。
一般的なワークフロー
ワークフロー 1:画像キャプション生成パイプライン
import torch
from PIL import Image
from transformers import Blip2Processor, Blip2ForConditionalGeneration
from pathlib import Path
class ImageCaptioner:
def __init__(self, model_name="Salesforce/blip2-opt-2.7b"):
self.processor = Blip2Processor.from_pretrained(model_name)
self.model = Blip2ForConditionalGeneration.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto"
)
def caption(self, image_path: str, prompt: str = None) -> str:
image = Image.open(image_path).convert("RGB")
if prompt:
inputs = self.processor(images=image, text=prompt, return_tensors="pt")
else:
inputs = self.processor(images=image, return_tensors="pt")
inputs = inputs.to("cuda", torch.float16)
generated_ids = self.model.generate(
**inputs,
max_new_tokens=50,
num_beams=5
)
return self.processor.decode(generated_ids[0], skip_special_tokens=True)
def caption_batch(self, image_paths: list, prompt: str = None) -> list:
images = [Image.open(p).convert("RGB") for p in image_paths]
if prompt:
inputs = self.processor(
images=images,
text=[prompt] * len(images),
return_tensors="pt",
padding=True
)
else:
inputs = self.processor(images=images, return_tensors="pt", padding=True)
inputs = inputs.to("cuda", torch.float16)
generated_ids = self.model.generate(**inputs, max_new_tokens=50)
return self.processor.batch_decode(generated_ids, skip_special_tokens=True)
# Usage
captioner = ImageCaptioner()
# Single image
caption = captioner.caption("photo.jpg")
print(f"Caption: {caption}")
# With prompt for style
caption = captioner.caption("photo.jpg", "a detailed description of")
print(f"Detailed: {caption}")
# Batch processing
captions = captioner.caption_batch(["img1.jpg", "img2.jpg", "img3.jpg"])
for i, cap in enumerate(captions):
print(f"Image {i+1}: {cap}")
ワークフロー 2:視覚的な Q&A システム
class VisualQA:
def __init__(self, model_name="Salesforce/blip2-flan-t5-xl"):
self.processor = Blip2Processor.from_pretrained(model_name)
self.model = Blip2ForConditionalGeneration.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto"
)
self.current_image = None
self.current_inputs = None
def set_image(self, image_path: str):
"""Load image for multiple questions."""
self.current_image = Image.open(image_path).convert("RGB")
def ask(self, question: str) -> str:
"""Ask a question about the current image."""
if self.current_image is None:
raise ValueError("No image set. Call set_image() first.")
# Format question for FlanT5
prompt = f"Question: {question} Answer:"
inputs = self.processor(
images=self.current_image,
text=prompt,
return_tensors="pt"
).to("cuda", torch.float16)
generated_ids = self.model.generate(
**inputs,
max_new_tokens=50,
num_beams=5
)
return self.processor.decode(generated_ids[0], skip_special_tokens=True)
def ask_multiple(self, questions: list) -> dict:
"""Ask multiple questions about current image."""
return {q: self.ask(q) for q in questions}
# Usage
vqa = VisualQA()
vqa.set_image("scene.jpg")
# Ask questions
print(vqa.ask("What objects are in this image?"))
print(vqa.ask("What is the weather like?"))
print(vqa.ask("How many people are there?"))
# Batch questions
results = vqa.ask_multiple([
"What is the main subject?",
"What colors are dominant?",
"Is this indoors or outdoors?"
])
ワークフロー 3:画像検索/検索取得
import torch
import numpy as np
from PIL import Image
from lavis.models import load_model_and_preprocess
class ImageSearchEngine:
def __init__(self):
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.model, self.vis_processors, self.txt_processors = load_model_and_preprocess(
name="blip2_feature_extractor",
model_type="pretrain",
is_eval=True,
device=self.device
)
self.image_features = []
self.image_paths = []
def index_images(self, image_paths: list):
"""Build index from images."""
self.image_paths = image_paths
for path in image_paths:
image = Image.open(path).convert("RGB")
image = self.vis_processors["eval"](image).unsqueeze(0).to(self.device)
with torch.no_grad():
features = self.model.extract_features({"image": image}, mode="image")
# Use projected features for matching
self.image_features.append(
features.image_embeds_proj.mean(dim=1).cpu().numpy()
)
self.image_features = np.vstack(self.image_features)
def search(self, query: str, top_k: int = 5) -> list:
"""Search images by text query."""
# Get text features
text = self.txt_processors["eval"](query)
text_input = {"text_input": [text]}
with torch.no_grad():
text_features = self.model.extract_features(text_input, mode="text")
text_embeds = text_features.text_embeds_proj[:, 0].cpu().numpy()
# Compute similarities
similarities = np.dot(self.image_features, text_embeds.T).squeeze()
top_indices = np.argsort(similarities)[::-1][:top_k]
return [(self.image_paths[i], similarities[i]) for i in top_indices]
# Usage
engine = ImageSearchEngine()
engine.index_images(["img1.jpg", "img2.jpg", "img3.jpg", ...])
# Search
results = engine.search("a sunset over the ocean", top_k=5)
for path, score in results:
print(f"{path}: {score:.3f}")
出力形式
生成出力
# Direct generation returns token IDs
generated_ids = model.generate(**inputs, max_new_tokens=50)
# Shape: [batch_size, sequence_length]
# Decode to text
text = processor.batch_decode(generated_ids, skip_special_tokens=True)
# Returns: list of strings
特徴抽出出力
# Q-Former outputs
features = model.extract_features({"image": image}, mode="image")
features.image_embeds # [B, 32, 768] - Q-Former outputs
features.image_embeds_proj # [B, 32, 256] - Projected for matching
features.text_embeds # [B, seq_len, 768] - Text features
features.text_embeds_proj # [B, 256] - Projected text (CLS)
パフォーマンスの最適化
GPU メモリ要件
| モデル | FP16 VRAM | INT8 VRAM | INT4 VRAM |
|---|---|---|---|
| blip2-opt-2.7b | ~8GB | ~5GB | ~3GB |
| blip2-opt-6.7b | ~16GB | ~9GB | ~5GB |
| blip2-flan-t5-xl | ~10GB | ~6GB | ~4GB |
| blip2-flan-t5-xxl | ~26GB | ~14GB | ~8GB |
速度の最適化
# Use Flash Attention if available
model = Blip2ForConditionalGeneration.from_pretrained(
"Salesforce/blip2-opt-2.7b",
torch_dtype=torch.float16,
attn_implementation="flash_attention_2", # Requires flash-attn
device_map="auto"
)
# Compile model (PyTorch 2.0+)
model = torch.compile(model)
# Use smaller images (if quality allows)
processor = Blip2Processor.from_pretrained("Salesforce/blip2-opt-2.7b")
# Default is 224x224, which is optimal
よくある問題
| 問題 | 解決策 |
|---|---|
| CUDA OOM | INT8/INT4 量子化を使用するか、より小さいモデルを使用します |
| 生成が遅い | 貪欲デコードを使用し、max_new_tokens を減らします |
| キャプションの品質が低い | FlanT5 のバリエーションを試し、プロンプトを使用します |
| ハルシネーション | 温度を下げ、ビームサーチを使用します |
| 回答が誤っている | 質問を言い換えるか、コンテキストを提示します |
参考資料
- 応用的な使い方 - ファインチューニング、統合、デプロイ
- トラブルシューティング - よくある問題と解決策
リソース
- 論文: https://arxiv.org/abs/2301.12597
- GitHub(LAVIS): https://github.com/salesforce/LAVIS
- HuggingFace: https://huggingface.co/Salesforce/blip2-opt-2.7b
- デモ: https://huggingface.co/spaces/Salesforce/BLIP2
- InstructBLIP: https://arxiv.org/abs/2305.06500(後継)
エージェントの運用手順
- 環境を確認します。 GPU メモリ、モデルのチェックポイントとライセンス、フレームワークのバージョン、入力形式を確認します。
- 入力を明確にします。 データまたはユーザーから、形式、識別子、パラメーターを確認します。結果に影響する値は推測せず、質問してください。
- まず小規模に実行します。 最初に、低解像度または短い長さで単一サンプルの推論を実行します。
- 上記の手順と参考資料を使って、タスク全体を実行します。
- 結果を検証します。 出力を定性的に確認し、タスクの指標でも評価します。生成コンテンツに関するライセンス制限も確認してください。
- 報告します。 実行した内容(バージョン、コマンド、パラメーター)、確認した内容、未確認の点を伝えます。
| これが起きた場合 | 対応 |
|---|---|
| 大きな入力でメモリ不足になる | 解像度またはシーケンス長を下げるか、半精度を使用するか、入力をタイル分割します。 |
| この手順に記載された関数、フラグ、エンドポイントがインストール済みバージョンにない | インストール済みバージョンのドキュメント(help()、--help、公式ドキュメント)を確認し、適宜対応してユーザーに伝えます。API を決して捏造しないでください。 |
| 必須の入力、識別子、パラメーターが曖昧である | ユーザーに質問するか、実行前に仮定を明示します。 |
誠実さに関するルール
- 結果、パラメーター、識別子、引用、統計を決して捏造しないでください。実行または検証できない場合は、その旨を明確に伝えてください。
- 商用利用または公開利用の前に、モデルとデータセットのライセンスを確認してください。
- ここに記載されたバージョン固有の情報は古くなっている可能性があるため、インストール済みバージョンの公式ドキュメントと照らし合わせて確認してください。
- 費用が発生する操作、共有 GPU やクラウドのクォータを消費する操作、個人データや患者データを扱う操作、元に戻せない操作の前には確認を取ってください。
関連スキル
clip:OpenAI の、ビジョンと言語をつなぐモデルです。llava:Large Language and Vision Assistant です。quantizing-models-bitsandbytes:LLM を 8 ビットまたは 4 ビットに量子化し、精度の損失を最小限に抑えながらメモリ使用量を 50~75% 削減します。
コメント
Markdown 対応