mcpField
B
blip-2-vision-language

blip-2-vision-language

github.com/kalarislabsその他7343 回インストール4 日前に更新
リポジトリ

blip-2-vision-language について

BLIP-2 は、画像キャプション、視覚質問応答、画像と言語の理解に使うビジョン・ランゲージモデルのスキルです。マルチモーダルアプリを開発する人向けで、Q-Former により凍結された画像エンコーダーと LLM を接続します。

主な機能

  1. 01自然な画像キャプションの生成
  2. 02画像に関する質問への回答
  3. 03ゼロショットの画像・テキスト理解
  4. 04照合用の画像・テキスト特徴の抽出
  5. 05OPT または FlanT5 の言語モデルバックエンド
  6. 06HuggingFace Transformers または LAVIS で実行

活用シーン

  1. 01画像コレクションのキャプション作成
  2. 02視覚質問応答システムの構築
  3. 03テキストまたは画像特徴による画像検索
  4. 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.md
advanced-usage.md
troubleshooting.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.7bOPT-2.7B~4GB一般的なキャプション生成、VQA
blip2-opt-6.7bOPT-6.7B~8GBより優れた推論
blip2-flan-t5-xlFlanT5-XL~5GB指示追従
blip2-flan-t5-xxlFlanT5-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 VRAMINT8 VRAMINT4 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 OOMINT8/INT4 量子化を使用するか、より小さいモデルを使用します
生成が遅い貪欲デコードを使用し、max_new_tokens を減らします
キャプションの品質が低いFlanT5 のバリエーションを試し、プロンプトを使用します
ハルシネーション温度を下げ、ビームサーチを使用します
回答が誤っている質問を言い換えるか、コンテキストを提示します

参考資料

リソース

エージェントの運用手順

  1. 環境を確認します。 GPU メモリ、モデルのチェックポイントとライセンス、フレームワークのバージョン、入力形式を確認します。
  2. 入力を明確にします。 データまたはユーザーから、形式、識別子、パラメーターを確認します。結果に影響する値は推測せず、質問してください。
  3. まず小規模に実行します。 最初に、低解像度または短い長さで単一サンプルの推論を実行します。
  4. 上記の手順と参考資料を使って、タスク全体を実行します。
  5. 結果を検証します。 出力を定性的に確認し、タスクの指標でも評価します。生成コンテンツに関するライセンス制限も確認してください。
  6. 報告します。 実行した内容(バージョン、コマンド、パラメーター)、確認した内容、未確認の点を伝えます。
これが起きた場合対応
大きな入力でメモリ不足になる解像度またはシーケンス長を下げるか、半精度を使用するか、入力をタイル分割します。
この手順に記載された関数、フラグ、エンドポイントがインストール済みバージョンにないインストール済みバージョンのドキュメント(help()、--help、公式ドキュメント)を確認し、適宜対応してユーザーに伝えます。API を決して捏造しないでください。
必須の入力、識別子、パラメーターが曖昧であるユーザーに質問するか、実行前に仮定を明示します。

誠実さに関するルール

  • 結果、パラメーター、識別子、引用、統計を決して捏造しないでください。実行または検証できない場合は、その旨を明確に伝えてください。
  • 商用利用または公開利用の前に、モデルとデータセットのライセンスを確認してください。
  • ここに記載されたバージョン固有の情報は古くなっている可能性があるため、インストール済みバージョンの公式ドキュメントと照らし合わせて確認してください。
  • 費用が発生する操作、共有 GPU やクラウドのクォータを消費する操作、個人データや患者データを扱う操作、元に戻せない操作の前には確認を取ってください。

関連スキル

  • clip:OpenAI の、ビジョンと言語をつなぐモデルです。
  • llava:Large Language and Vision Assistant です。
  • quantizing-models-bitsandbytes:LLM を 8 ビットまたは 4 ビットに量子化し、精度の損失を最小限に抑えながらメモリ使用量を 50~75% 削減します。

コメント