Transformers 文档
图像-文本到文本
并获得增强的文档体验
开始使用
图像-文本到文本
图像-文本到文本模型,也称为视觉语言模型(VLM),是接受图像输入的语言模型。这些模型可以处理各种任务,从视觉问答到图像分割。此任务与图像到文本任务有许多相似之处,但也有一些重叠的用例,如图像字幕。图像到文本模型只接受图像输入,通常完成特定任务,而 VLM 接受开放式文本和图像输入,并且是更通用的模型。
在本指南中,我们将简要概述 VLM,并展示如何使用 Transformers 进行推理。
首先,VLM 有多种类型
- 用于微调的基础模型
- 用于对话的聊天微调模型
- 指令微调模型
本指南重点介绍使用指令微调模型进行推理。
我们先安装依赖项。
pip install -q transformers accelerate flash_attn
让我们初始化模型和处理器。
from transformers import AutoProcessor, AutoModelForImageTextToText
import torch
device = torch.device("cuda")
model = AutoModelForImageTextToText.from_pretrained(
"HuggingFaceM4/idefics2-8b",
torch_dtype=torch.bfloat16,
attn_implementation="flash_attention_2",
).to(device)
processor = AutoProcessor.from_pretrained("HuggingFaceM4/idefics2-8b")
此模型有一个聊天模板,可帮助用户解析聊天输出。此外,该模型还可以在单个对话或消息中接受多张图像作为输入。现在我们将准备输入。
图像输入如下所示。


from PIL import Image
import requests
img_urls =["https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/cats.png",
"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/bee.jpg"]
images = [Image.open(requests.get(img_urls[0], stream=True).raw),
Image.open(requests.get(img_urls[1], stream=True).raw)]
下面是聊天模板的示例。我们可以将对话轮次和最后一条消息作为输入,通过将其附加到模板末尾。
messages = [
{
"role": "user",
"content": [
{"type": "image"},
{"type": "text", "text": "What do we see in this image?"},
]
},
{
"role": "assistant",
"content": [
{"type": "text", "text": "In this image we can see two cats on the nets."},
]
},
{
"role": "user",
"content": [
{"type": "image"},
{"type": "text", "text": "And how about this image?"},
]
},
]
现在我们将调用处理器的 `apply_chat_template()` 方法,以预处理其输出以及图像输入。
prompt = processor.apply_chat_template(messages, add_generation_prompt=True)
inputs = processor(text=prompt, images=[images[0], images[1]], return_tensors="pt").to(device)
我们现在可以将预处理的输入传递给模型。
with torch.no_grad():
generated_ids = model.generate(**inputs, max_new_tokens=500)
generated_texts = processor.batch_decode(generated_ids, skip_special_tokens=True)
print(generated_texts)
## ['User: What do we see in this image? \nAssistant: In this image we can see two cats on the nets. \nUser: And how about this image? \nAssistant: In this image we can see flowers, plants and insect.']
Pipeline
最快入门的方法是使用 Pipeline API。指定 `“image-text-to-text”` 任务和要使用的模型。
from transformers import pipeline
pipe = pipeline("image-text-to-text", model="llava-hf/llava-interleave-qwen-0.5b-hf")
以下示例使用聊天模板格式化文本输入。
messages = [
{
"role": "user",
"content": [
{
"type": "image",
"image": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/bee.jpg",
},
{"type": "text", "text": "Describe this image."},
],
},
{
"role": "assistant",
"content": [
{"type": "text", "text": "There's a pink flower"},
],
},
]
将聊天模板格式化的文本和图像传递给 Pipeline,并将 `return_full_text=False` 设置为从生成输出中移除输入。
outputs = pipe(text=messages, max_new_tokens=20, return_full_text=False)
outputs[0]["generated_text"]
# with a yellow center in the foreground. The flower is surrounded by red and white flowers with green stems
如果愿意,您也可以单独加载图像并将其传递给流水线,如下所示
pipe = pipeline("image-text-to-text", model="HuggingFaceTB/SmolVLM-256M-Instruct")
img_urls = [
"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/cats.png",
"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/bee.jpg",
]
images = [
Image.open(requests.get(img_urls[0], stream=True).raw),
Image.open(requests.get(img_urls[1], stream=True).raw),
]
messages = [
{
"role": "user",
"content": [
{"type": "image"},
{"type": "image"},
{"type": "text", "text": "What do you see in these images?"},
],
}
]
outputs = pipe(text=messages, images=images, max_new_tokens=50, return_full_text=False)
outputs[0]["generated_text"]
" In the first image, there are two cats sitting on a plant. In the second image, there are flowers with a pinkish hue."
图像仍将包含在输出的 `“input_text”` 字段中
outputs[0]['input_text']
"""
[{'role': 'user',
'content': [{'type': 'image',
'image': <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=622x412>},
{'type': 'image',
'image': <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=5184x3456>},
{'type': 'text', 'text': 'What do you see in these images?'}]}]## Streaming
"""
我们可以使用文本流来获得更好的生成体验。Transformers 支持使用 TextStreamer 或 TextIteratorStreamer 类进行流式传输。我们将使用 TextIteratorStreamer 与 IDEFICS-8B。
假设我们有一个应用程序,它保存聊天历史记录并接收新的用户输入。我们将像往常一样预处理输入,并初始化 TextIteratorStreamer 以在单独的线程中处理生成。这允许您实时流式传输生成的文本标记。任何生成参数都可以传递给 TextIteratorStreamer。
import time
from transformers import TextIteratorStreamer
from threading import Thread
def model_inference(
user_prompt,
chat_history,
max_new_tokens,
images
):
user_prompt = {
"role": "user",
"content": [
{"type": "image"},
{"type": "text", "text": user_prompt},
]
}
chat_history.append(user_prompt)
streamer = TextIteratorStreamer(
processor.tokenizer,
skip_prompt=True,
timeout=5.0,
)
generation_args = {
"max_new_tokens": max_new_tokens,
"streamer": streamer,
"do_sample": False
}
# add_generation_prompt=True makes model generate bot response
prompt = processor.apply_chat_template(chat_history, add_generation_prompt=True)
inputs = processor(
text=prompt,
images=images,
return_tensors="pt",
).to(device)
generation_args.update(inputs)
thread = Thread(
target=model.generate,
kwargs=generation_args,
)
thread.start()
acc_text = ""
for text_token in streamer:
time.sleep(0.04)
acc_text += text_token
if acc_text.endswith("<end_of_utterance>"):
acc_text = acc_text[:-18]
yield acc_text
thread.join()
现在让我们调用我们创建的 `model_inference` 函数并流式传输值。
generator = model_inference(
user_prompt="And what is in this image?",
chat_history=messages[:2],
max_new_tokens=100,
images=images
)
for value in generator:
print(value)
# In
# In this
# In this image ...
在较小硬件中运行模型
VLM 通常很大,需要优化才能适应较小的硬件。Transformers 支持许多模型量化库,这里我们只展示使用 Quanto 进行 int8 量化。int8 量化可将内存改进高达 75%(如果所有权重都已量化)。然而,这并非没有代价,因为 8 位不是 CUDA 原生精度,权重会在运行时来回量化,这会增加延迟。
首先,安装依赖项。
pip install -U quanto bitsandbytes
要在加载过程中量化模型,我们首先需要创建 QuantoConfig。然后像往常一样加载模型,但在模型初始化期间传递 `quantization_config`。
from transformers import AutoModelForImageTextToText, QuantoConfig
model_id = "HuggingFaceM4/idefics2-8b"
quantization_config = QuantoConfig(weights="int8")
quantized_model = AutoModelForImageTextToText.from_pretrained(
model_id, device_map="cuda", quantization_config=quantization_config
)
就是这样,我们可以以相同的方式使用模型,无需任何更改。
进一步阅读
以下是关于图像-文本到文本任务的更多资源。
- 图像-文本到文本任务页面涵盖模型类型、用例、数据集等。
- 视觉语言模型解释是一篇博客文章,涵盖了视觉语言模型以及使用 TRL 进行监督微调的所有内容。