Transformers documentation

Modelos de chat multimodais

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Modelos de chat multimodais

Modelos de chat multimodais aceitam entradas como imagens, áudio ou vídeo, além de texto. A chave content em um histórico de chat multimodal é uma lista contendo vários itens de diferentes tipos. Isso difere dos modelos de chat apenas com texto, cuja chave content é uma única string.

Da mesma forma que a classe Tokenizer trata modelos de chat e tokenização para modelos apenas de texto, a classe Processor trata pré-processamento, tokenização e modelos de chat para modelos multimodais. Seus métodos apply_chat_template() são quase idênticos.

Este guia mostrará como conversar com modelos multimodais usando o ImageTextToTextPipeline de alto nível e, em um nível mais baixo, utilizando os métodos apply_chat_template() e generate().

ImageTextToTextPipeline

ImageTextToTextPipeline é uma classe de alto nível para geração de imagem e texto com um “modo de chat”. O modo de chat é ativado quando um modelo conversacional é detectado e o prompt de chat está corretamente formatado.

Adicione blocos de imagem e texto à chave content no histórico do 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?"},
        ],
    },
]

Crie um ImageTextToTextPipeline e passe o chat para ele. Para modelos grandes, definir device_map=“auto” ajuda a carregar o modelo mais rapidamente e o posiciona automaticamente no dispositivo mais rápido disponível. Definir o tipo de dados como auto também ajuda a economizar memória e a melhorar a velocidade.

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?

Além da transição gradual do jargão de piratas para o inglês americano moderno (é apenas um modelo de 3B, afinal), isso está correto!

Usando apply_chat_template

Assim como nos modelos apenas de texto, use o método apply_chat_template() para preparar as mensagens de chat para modelos multimodais. Este método trata da tokenização e formatação das mensagens de chat, incluindo imagens e outros tipos de mídia. Os resultantes são passados ao modelo para geração.

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?"},
        ],
    },
]

Passe messages para apply_chat_template() para tokenizar o conteúdo de entrada. Diferentemente dos modelos de texto, a saída de apply_chat_template contém uma chave pixel_values com os dados de imagem pré-processados, além do 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']

Passe estas entradas para generate().

out = model.generate(**processed_chat.to(model.device), max_new_tokens=128)
print(processor.decode(out[0]))

A saída decodificada contém a conversa completa até o momento, incluindo a mensagem do usuário e os tokens de espaço reservado que contêm as informações da imagem. Você pode precisar remover a conversa anterior da saída antes de exibi-la para o usuário.

Entradas de vídeo

Alguns modelos de visão também suportam entradas de vídeo. O formato da mensagem é muito semelhante ao formato para entradas de imagem descrito na seção anterior.

  • O conteúdo "type" deve ser "video" para indicar que o conteúdo é um vídeo.
  • Para vídeos, pode ser um link para o vídeo ("url") ou um caminho de arquivo ("path"). Os vídeos são decodificados com torchcodec. Se o torchcodec não estiver disponível e você estiver usando uma versão mais antiga do torchvision, a decodificação usa o torchvision como alternativa.
  • Além de carregar vídeos a partir de uma URL ou caminho de arquivo, você também pode passar diretamente os dados do vídeo decodificados. Isso é útil se você já pré-processou ou decodificou os quadros do vídeo em outro lugar na memória. Não é necessário salvar em arquivos nem armazenar em uma URL.

PyAV e Decord estão disponíveis, mas apenas se você decodificar o vídeo por conta própria e solicitar o backend explicitamente com 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?"},
        ],
    },
]

Exemplo: Passando objetos de vídeo 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?"}
        ],
    },
]

Você também pode usar a função existente ("load_video()") para carregar um vídeo, editá-lo em memória e passá-lo nas mensagens.


# 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?"}
        ],
    },
]

Passe messages para apply_chat_template() para tokenizar o conteúdo de entrada. Há alguns parâmetros extras a incluir em apply_chat_template() que controlam o processo de amostragem.

número fixo de quadros
fps
lista de quadros de imagem

O parâmetro num_frames controla quantos quadros devem ser amostrados uniformemente do vídeo. Cada checkpoint possui um número máximo de quadros com o qual foi pré-treinado, e exceder esse limite pode reduzir significativamente a qualidade da geração. É importante escolher um número de quadros que se adeque tanto à capacidade do modelo quanto aos recursos de hardware disponíveis. Se num_frames não for especificado, o vídeo inteiro será carregado sem qualquer amostragem de quadros.

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())

Essas entradas estão agora prontas para serem usadas em generate().

Update on GitHub