Transformers documentation
Plantillas de chat multimodales
Plantillas de chat multimodales
Los modelos de chat multimodales aceptan entradas como imágenes, audio o video, además de texto. La clave content en un historial de chat multimodal es una lista que contiene varios elementos de diferentes tipos. Esto difiere de los modelos de chat solo de texto, cuya clave content es una sola cadena.
De la misma manera que la clase Tokenizer gestiona las plantillas de chat y la tokenización para modelos solo de texto, la clase Processor gestiona el preprocesamiento, la tokenización y las plantillas de chat para modelos multimodales. Sus métodos apply_chat_template() son casi idénticos.
Esta guía le mostrará cómo chatear con modelos multimodales a alto nivel con ImageTextToTextPipeline y a un nivel más bajo utilizando los métodos apply_chat_template() y generate().
ImageTextToTextPipeline
ImageTextToTextPipeline es una clase de alto nivel para la generación de imágenes y texto con un “modo de chat”. El modo de chat se activa cuando se detecta un modelo conversacional y el prompt de chat está correctamente formateado.
Agregue bloques de imagen y texto a la clave content en el historial de chat.
messages = [
{
"role": "system",
"content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
},
{
"role": "user",
"content": [
{"type": "image", "url": "http://images.cocodataset.org/val2017/000000039769.jpg"},
{"type": "text", "text": "What are these?"},
],
},
]Crea un ImageTextToTextPipeline y pásale el chat. Para modelos grandes, establecer device_map=“auto” ayuda a cargar el modelo más rápido y lo coloca automáticamente en el dispositivo más rápido disponible. Establecer el tipo de datos en auto también ayuda a ahorrar memoria y mejorar la velocidad.
import torch
from transformers import pipeline
pipe = pipeline("image-text-to-text", model="Qwen/Qwen2.5-VL-3B-Instruct", device_map="auto", dtype="auto")
out = pipe(text=messages, max_new_tokens=128)
print(out[0]['generated_text'][-1]['content'])Ahoy, me hearty! These be two feline friends, likely some tabby cats, taking a siesta on a cozy pink blanket. They're resting near remote controls, perhaps after watching some TV or just enjoying some quiet time together. Cats sure know how to find comfort and relaxation, don't they?
Además del descenso gradual del lenguaje pirata al inglés americano moderno (al fin y al cabo, es solo un modelo de 3B), ¡esto es correcto!
Usando apply_chat_template
Al igual que con los modelos solo de texto, utiliza el método apply_chat_template() para preparar los mensajes de chat para los modelos multimodales. Este método se encarga de la tokenización y el formato de los mensajes de chat, incluidas las imágenes y otros tipos de medios. Las entradas resultantes se pasan al modelo para la generación.
from transformers import AutoProcessor, AutoModelForImageTextToText
model = AutoModelForImageTextToText.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct", device_map="auto", torch_dtype="auto")
processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct")
messages = [
{
"role": "system",
"content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
},
{
"role": "user",
"content": [
{"type": "image", "url": "http://images.cocodataset.org/val2017/000000039769.jpg"},
{"type": "text", "text": "What are these?"},
],
},
]Pasa messages a apply_chat_template() para tokenizar el contenido de entrada. A diferencia de los modelos de texto, la salida de apply_chat_template contiene una clave pixel_values con los datos de imagen preprocesados, además del texto tokenizado.
processed_chat = processor.apply_chat_template(messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt")
print(list(processed_chat.keys()))['input_ids', 'attention_mask', 'pixel_values', 'image_grid_thw']
Pase estas entradas a generate().
out = model.generate(**processed_chat.to(model.device), max_new_tokens=128)
print(processor.decode(out[0]))La salida decodificada contiene la conversación completa hasta el momento, incluido el mensaje del usuario y los tokens de marcador de posición que contienen la información de la imagen. Es posible que debas recortar la conversación anterior de la salida antes de mostrarla al usuario.
Entradas de video
Algunos modelos de visión también admiten entradas de video. El formato de mensaje es muy similar al formato para entradas de imagen descrito en la sección anterior.
- El contenido
"type"debe ser"video"para indicar que el contenido es un video. - Para los vídeos, puede ser un enlace al vídeo (
"url") o una ruta de archivo ("path"). Los vídeos se decodifican con torchcodec. Si torchcodec no está disponible y se utiliza una versión anterior de torchvision, la decodificación se realiza con torchvision. - Además de cargar videos desde una URL o ruta de archivo, también puede pasar directamente los datos de video decodificados. Esto es útil si ya ha preprocesado o decodificado los fotogramas del video en otro lugar de la memoria. No necesita guardarlos en archivos ni almacenarlos en una URL.
PyAV y Decord están disponibles, pero solo si decodificas el video tú mismo y solicitas el backend explícitamente con
load_video(backend=...).
from transformers import AutoProcessor, LlavaOnevisionForConditionalGeneration
model_id = "llava-hf/llava-onevision-qwen2-0.5b-ov-hf"
model = LlavaOnevisionForConditionalGeneration.from_pretrained(model_id)
processor = AutoProcessor.from_pretrained(model_id)
messages = [
{
"role": "system",
"content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
},
{
"role": "user",
"content": [
{"type": "video", "url": "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_10MB.mp4"},
{"type": "text", "text": "What do you see in this video?"},
],
},
]Ejemplo: Pasar objetos de video decodificados
import numpy as np
video_object1 = np.random.randint(0, 255, size=(16, 224, 224, 3), dtype=np.uint8),
messages = [
{
"role": "system",
"content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
},
{
"role": "user",
"content": [
{"type": "video", "video": video_object1},
{"type": "text", "text": "What do you see in this video?"}
],
},
]También puede usar la función existente ("load_video()") para cargar un video, editarlo en memoria y pasarlo en los mensajes.
# Make sure a video backend library (torchcodec, pyav, or decord) is available.
from transformers.video_utils import load_video
# load a video file in memory for testing
video_object2, _ = load_video(
"https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_10MB.mp4"
)
messages = [
{
"role": "system",
"content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
},
{
"role": "user",
"content": [
{"type": "video", "video": video_object2},
{"type": "text", "text": "What do you see in this video?"}
],
},
]Pase messages a apply_chat_template() para tokenizar el contenido de entrada. Hay algunos parámetros adicionales para incluir en apply_chat_template() que controlan el proceso de muestreo.
El parámetro num_frames controla cuántos fotogramas se muestrean uniformemente del video. Cada punto de control tiene un número máximo de fotogramas con el que se preentrenó y superar este recuento puede reducir significativamente la calidad de la generación. Es importante elegir un recuento de fotogramas que se ajuste tanto a la capacidad del modelo como a los recursos de hardware. Si no se especifica num_frames, se carga el video completo sin ningún muestreo de fotogramas.
processed_chat = processor.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=True,
return_dict=True,
return_tensors="pt",
num_frames=32,
)
print(processed_chat.keys())Estas entradas ya están listas para usarse en generate().
Para videos más largos, puede ser mejor muestrear más fotogramas para una mejor representación con el parámetro fps. Esto determina cuántos fotogramas por segundo se deben extraer. Como ejemplo, si un video dura 10 segundos y fps=2, el modelo muestrea 20 fotogramas. En otras palabras, se muestrean uniformemente 2 fotogramas cada 10 segundos.
processed_chat = processor.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=True,
return_dict=True,
fps=16,
)
print(processed_chat.keys())Los videos también pueden existir como un conjunto de fotogramas muestreados almacenados como imágenes, en lugar del archivo de video completo.
En este caso, pase una lista de rutas de archivos de imagen y el procesador las concatenará automáticamente en un video. Asegúrese de que todas las imágenes tengan el mismo tamaño, ya que se asume que provienen del mismo video.
frames_paths = ["/path/to/frame0.png", "/path/to/frame5.png", "/path/to/frame10.png"]
messages = [
{
"role": "system",
"content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
},
{
"role": "user",
"content": [
{"type": "video", "path": frames_paths},
{"type": "text", "text": "What do you see in this video?"},
],
},
]
processed_chat = processor.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=True,
return_dict=True,
)
print(processed_chat.keys())