mcpField
B
blip-2-vision-language

blip-2-vision-language

github.com/kalarislabs开发7744 次安装4 天前更新
代码仓库

关于 blip-2-vision-language

BLIP-2 是一项视觉语言模型技能,用于图像描述、视觉问答和图文理解,面向构建多模态应用的开发者。它通过 Q-Former 将冻结的图像编码器与语言模型连接起来。

主要功能

  1. 01生成自然语言图像描述
  2. 02回答有关图像的问题
  3. 03执行零样本图文理解
  4. 04提取图像和文本特征用于匹配
  5. 05采用 OPT 或 FlanT5 语言模型后端
  6. 06通过 HuggingFace 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 架构:轻量级查询 Transformer 连接视觉与语言
  • 冻结骨干网络,效率更高:无需微调大型视觉或语言模型
  • 多种 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
图像 Transformer对视觉特征进行交叉注意力约 108M
文本 Transformer用于文本的自注意力约 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:视觉问答系统
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 显存INT8 显存INT4 显存
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 显存不足使用 INT8/INT4 量化或更小的模型
生成速度慢使用贪心解码,减少 max_new_tokens
字幕质量差尝试 FlanT5 变体,使用提示词
幻觉降低温度,使用束搜索
答案错误改写问题,提供上下文

参考资料

资源

Agent 操作流程

  1. 检查环境。 确认 GPU 内存、模型检查点及许可证、框架版本和输入格式。
  2. 明确输入。 根据数据或用户确认格式、标识符和参数。任何会影响结果的值都应询问,不要猜测。
  3. 先运行小规模版本。 首先以低分辨率或较短长度对单个样本运行推理。
  4. 按照上述说明和参考资料执行完整任务。
  5. 验证结果。 通过定性检查和任务指标检查输出;确认生成内容符合许可证限制。
  6. 汇报。 说明运行了什么(版本、命令、参数)、检查了什么,以及哪些事项仍不确定。
如果发生这种情况请这样做
大型输入导致内存不足降低分辨率或序列长度、使用半精度,或对输入进行分块。
这些说明中提到的函数、标志或端点在已安装版本中不存在查看已安装版本自己的文档(help()、--help、官方文档),调整做法,并告知用户。绝不编造 API。
必需的输入、标识符或参数不明确询问用户,或在运行前明确说明所采用的假设。

诚信规则

  • 绝不捏造结果、参数、标识符、引文或统计数据。如果无法运行或验证某项内容,请直言说明。
  • 用于商业用途或发布前,检查模型和数据集的许可证。
  • 请将此处与特定版本相关的细节视为可能已过时:根据已安装版本的官方文档进行确认。
  • 对于需要付费、占用共享 GPU 或云配额、涉及个人或患者数据,或无法撤销的操作,先征求同意。

相关技能

  • clip:连接视觉与语言的 OpenAI 模型。
  • llava:大语言与视觉助手。
  • quantizing-models-bitsandbytes:将 LLM 量化为 8 位或 4 位,在准确率损失极小的情况下减少 50-75% 的内存占用。

评论

支持 Markdown