视频-视觉多模态理解模型 (VLM with video-input, Video-text-to-text)¶
视频文本到文本模型,也称为视频语言模型或带视频输入的视觉语言模型,是一种接受视频输入的语言模型。这些模型可以处理各种任务,从视频问答到视频字幕生成。
这些模型的架构与图像文本到文本模型几乎相同,只是进行了一些修改以接受视频数据,因为视频数据本质上是带有时间依赖性的图像帧。一些图像文本到文本模型可以接受多张图像,但仅凭这一点还不足以让模型接受视频。此外,视频文本到文本模型通常使用所有视觉模态进行训练。每个示例可能包含视频、多个视频、图像和多个图像。有些模型还可以接受交错输入。
例如,你可以在文本中通过添加视频标记来引用特定视频,如:“这个视频里发生了什么?<video>”。
在本指南中,我们简要介绍了视频语言模型,并展示了如何使用 Transformers 进行推理。
首先,视频语言模型有多种类型:
- 用于微调的基模型
- 用于对话的微调模型
- 用于指令的微调模型
本指南重点介绍使用指令微调模型 llava-hf/llava-interleave-qwen-7b-hf 进行推理,该模型可以接受交错数据。如果你的硬件不支持运行 7B 模型,你也可以尝试 llava-interleave-qwen-0.5b-hf。
让我们开始安装依赖项。
pip install -q transformers accelerate flash_attn
接下来,初始化模型和处理器。
from transformers import LlavaProcessor, LlavaForConditionalGeneration
import torch
model_id = "llava-hf/llava-interleave-qwen-0.5b-hf"
processor = LlavaProcessor.from_pretrained(model_id)
model = LlavaForConditionalGeneration.from_pretrained(model_id, torch_dtype=torch.float16)
model.to("cuda")
有些模型直接处理 <video> 标记,而其他模型接受与采样帧数相等的 <image> 标记。这个模型采用后一种方式处理视频。我们将编写一个简单的工具来处理图像标记,另一个工具来从 URL 获取视频并从中采样帧。
import uuid
import requests
import cv2
from PIL import Image
def replace_video_with_images(text, frames):
return text.replace("<video>", "<image>" * frames)
def sample_frames(url, num_frames):
response = requests.get(url)
path_id = str(uuid.uuid4())
path = f"./{path_id}.mp4"
with open(path, "wb") as f:
f.write(response.content)
video = cv2.VideoCapture(path)
total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
interval = total_frames // num_frames
frames = []
for i in range(total_frames):
ret, frame = video.read()
pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
if not ret:
continue
if i % interval == 0:
frames.append(pil_img)
video.release()
return frames
获取输入数据。我们将采样帧并将它们连接起来。
video_1 = "https://huggingface.co/spaces/merve/llava-interleave/resolve/main/cats_1.mp4"
video_2 = "https://huggingface.co/spaces/merve/llava-interleave/resolve/main/cats_2.mp4"
video_1 = sample_frames(video_1, 6)
video_2 = sample_frames(video_2, 6)
videos = video_1 + video_2
videos
两个视频都包含猫。
现在我们可以预处理输入数据。
这个模型有一个如下所示的提示模板。首先,我们将所有采样帧放入一个列表中。由于每个视频有八帧,我们将在提示中插入 12 个 <image> 标记。在提示末尾添加 assistant 以触发模型给出答案。然后我们可以进行预处理。
user_prompt = "这两个视频中的猫在做同样的事情吗?"
toks = "<image>" * 12
prompt = "<|im_start|>user" + toks + f"\n{user_prompt}<|im_end|><|im_start|>assistant"
inputs = processor(prompt, images=videos).to(model.device, model.dtype)
现在我们可以调用 generate() 进行推理。模型输出我们输入的问题和答案,所以我们只取模型输出中提示和 assistant 部分之后的文本。
output = model.generate(**inputs, max_new_tokens=100, do_sample=False)
print(processor.decode(output[0][2:], skip_special_tokens=True)[len(user_prompt)+10:])
输出结果:
第一个猫处于放松状态,眼睛 closed,表情 content,而第二个猫处于更活跃的状态,嘴巴 wide open,可能是打哈欠或发声。
要了解更多关于视频文本到文本模型的聊天模板和标记流的信息,请参考图像文本到文本任务指南,因为这些模型的工作方式类似。