LLaVA-VL/LLaVA-NeXT多模态模型使用教程:从图像到视频的视觉理解
LLaVA-NeXT 项目地址: https://gitcode.com/gh_mirrors/ll/LLaVA-NeXT
前言
LLaVA-VL/LLaVA-NeXT是一个强大的多模态模型系列,能够处理图像、文本、图文混合以及视频输入。本教程将详细介绍如何使用这个模型进行各种视觉理解任务,即使是计算资源有限的设备也能运行其轻量级版本。
模型简介
LLaVA-VL/LLaVA-NeXT模型系列有几个显著特点:
- 统一接口:使用相同的代码接口处理不同类型输入(图像、视频、图文混合)
- 轻量高效:0.5B版本可在4GB显存的GPU上运行
- 强大性能:尽管模型体积小,但在各种视觉理解任务上表现优异
环境准备
在开始前,请确保已安装必要的Python包:
pip install torch transformers pillow requests decord
图像理解
基础图像理解
以下代码展示了如何使用LLaVA模型理解单张图像内容:
from llava.model.builder import load_pretrained_model
from llava.mm_utils import process_images, tokenizer_image_token
from llava.constants import IMAGE_TOKEN_INDEX, DEFAULT_IMAGE_TOKEN
from llava.conversation import conv_templates
from PIL import Image
import requests
import torch
# 加载模型
model_path = "lmms-lab/llava-onevision-qwen2-0.5b-si"
tokenizer, model, image_processor, _ = load_pretrained_model(
model_path,
None,
"llava_qwen",
device_map="auto",
multimodal=True,
attn_implementation="sdpa"
)
# 准备图像
image_url = "https://example.com/sample_image.jpg" # 替换为实际图像URL
image = Image.open(requests.get(image_url, stream=True).raw)
image_tensor = process_images([image], image_processor, model.config)
image_tensor = image_tensor.to(dtype=torch.float16, device="cuda")
# 构建对话
conv = conv_templates["qwen_1_5"].copy()
question = f"{DEFAULT_IMAGE_TOKEN}\n这张图片展示了什么内容?"
conv.append_message(conv.roles[0], question)
conv.append_message(conv.roles[1], None)
prompt = conv.get_prompt()
# 生成回答
input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors="pt").unsqueeze(0).to("cuda")
output = model.generate(
input_ids,
images=[image_tensor],
image_sizes=[image.size],
do_sample=False,
temperature=0,
max_new_tokens=512,
)
print(tokenizer.decode(output[0], skip_special_tokens=True))
流式输出实现
对于交互式应用,可以使用流式输出:
from threading import Thread
from transformers import TextIteratorStreamer
# ... (前面的模型加载和图像处理代码相同)
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
gen_kwargs = {
"inputs": input_ids,
"images": [image_tensor],
"image_sizes": [image.size],
"streamer": streamer,
"do_sample": False,
"temperature": 0,
"max_new_tokens": 512,
}
thread = Thread(target=model.generate, kwargs=gen_kwargs)
thread.start()
for new_text in streamer:
print(new_text, end="", flush=True)
图文混合理解
LLaVA-OneVision模型特别擅长处理图文混合内容。以下是处理多张图像和文本交替输入的示例:
# 加载OneVision专用模型
model_path = "lmms-lab/llava-onevision-qwen2-0.5b-ov"
tokenizer, model, image_processor, _ = load_pretrained_model(
model_path,
None,
"llava_qwen",
device_map="auto",
multimodal=True,
overwrite_config={"image_aspect_ratio": "pad"}
)
# 准备多张图像
image_urls = [
"https://example.com/image1.jpg",
"https://example.com/image2.jpg"
]
images = [Image.open(requests.get(url, stream=True).raw) for url in image_urls]
image_tensors = process_images(images, image_processor, model.config)
image_tensors = [tensor.to(dtype=torch.float16, device="cuda") for tensor in image_tensors]
# 构建图文混合问题
conv = conv_templates["qwen_1_5"].copy()
question = f"{DEFAULT_IMAGE_TOKEN} 这是第一张图片,请描述你看到的内容。\n\n现在看第二张图片: {DEFAULT_IMAGE_TOKEN}\n这两张图片有什么区别?"
conv.append_message(conv.roles[0], question)
conv.append_message(conv.roles[1], None)
# 生成回答 (代码与前面类似)
视频理解
LLaVA-OneVision同样能处理视频输入,它会自动从视频中提取关键帧进行分析:
import cv2
import numpy as np
from decord import VideoReader, cpu
# 视频帧提取函数
def extract_frames(video_path, num_frames=16):
vr = VideoReader(video_path, ctx=cpu(0))
total_frames = len(vr)
frame_indices = np.linspace(0, total_frames-1, num_frames, dtype=int)
return vr.get_batch(frame_indices).asnumpy() # (帧数, 高, 宽, 通道)
# 加载和处理视频
video_frames = extract_frames("sample_video.mp4")
frame_tensors = image_processor.preprocess(video_frames, return_tensors="pt")["pixel_values"].half().cuda()
# 构建视频问题
conv = conv_templates["qwen_1_5"].copy()
question = f"{DEFAULT_IMAGE_TOKEN}\n描述这个视频中发生了什么。"
conv.append_message(conv.roles[0], question)
conv.append_message(conv.roles[1], None)
# 生成回答
output = model.generate(
input_ids,
images=[frame_tensors],
image_sizes=[frame.shape[:2] for frame in video_frames],
do_sample=False,
temperature=0,
max_new_tokens=1024,
modalities=["video"],
)
print(tokenizer.decode(output[0], skip_special_tokens=True))
最佳实践建议
-
模型选择:
- 对于简单图像任务:使用
llava-onevision-qwen2-0.5b-si
- 对于复杂任务和视频:使用
llava-onevision-qwen2-0.5b-ov
- 对于简单图像任务:使用
-
性能优化:
- 使用
flash-attn
可以显著提升推理速度 - 对于长视频,适当减少提取的帧数(如8-16帧)
- 使用
-
提示工程:
- 确保图像标记
<image>
在提示中只出现一次 - 对于视频,明确说明"这个视频"而非"这张图片"
- 确保图像标记
-
错误处理:
- 监控token长度,避免超过模型限制
- 处理网络请求时添加超时和重试机制
结语
LLaVA-VL/LLaVA-NeXT系列模型为多模态理解提供了强大而灵活的工具。通过本教程,您应该已经掌握了处理图像、图文混合内容和视频的基本方法。无论是构建智能客服、内容审核系统还是多媒体分析工具,这些技术都能提供坚实的基础。
LLaVA-NeXT 项目地址: https://gitcode.com/gh_mirrors/ll/LLaVA-NeXT
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考