Transformers documentation
멀티모달 채팅 템플릿
멀티모달 채팅 템플릿
멀티모달 채팅 모델은 텍스트 외에도 이미지, 오디오 또는 비디오와 같은 입력을 받습니다. 멀티모달 채팅 히스토리의 content 키는 서로 다른 유형의 여러 항목을 포함하는 목록입니다. 이는 content 키가 단일 문자열인 텍스트 전용 채팅 모델과 다릅니다.
Tokenizer 클래스가 텍스트 전용 모델의 채팅 템플릿과 토큰화를 처리하는 것과 마찬가지로, Processor 클래스는 멀티모달 모델의 전처리, 토큰화 및 채팅 템플릿을 처리합니다. 두 클래스의 apply_chat_template() 메서드는 거의 동일합니다.
이 가이드에서는 고수준의 ImageTextToTextPipeline을 사용하여 멀티모달 모델과 대화하는 방법과, apply_chat_template() 및 generate() 메서드를 사용하여 더 낮은 수준에서 대화하는 방법을 보여줍니다.
ImageTextToTextPipeline
ImageTextToTextPipeline는 “채팅 모드”를 지원하는 고수준의 이미지 및 텍스트 생성 클래스입니다. 대화형 모델이 감지되고 채팅 프롬프트가 적절하게 포맷되어 있을 때 채팅 모드가 활성화됩니다.
채팅 기록의 content 키에 이미지와 텍스트 블록을 추가합니다.
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?"},
],
},
]ImageTextToTextPipeline를 생성하고 채팅을 전달합니다. 대규모 모델의 경우 device_map=“auto”를 설정하면 모델 로딩 속도가 빨라지고, 사용 가능한 가장 빠른 장치에 자동으로 배치됩니다. 데이터 유형을 auto로 설정하면 메모리 절약과 속도 향상에도 도움이 됩니다.
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?
해적 용어에서 현대 미국 영어로 점진적으로 넘어가는 점을 제외하면(결국 is 3B 모델이니까), 이 내용은 정확합니다!
apply_chat_template 사용
텍스트 전용 모델과 마찬가지로, 멀티모달 모델의 채팅 메시지를 준비하려면 apply_chat_template() 메서드를 사용합니다. 이 메서드는 이미지 및 기타 미디어 유형을 포함한 채팅 메시지의 토큰화 및 포맷팅을 처리합니다. 생성된 입력은 모델에 전달되어 생성을 수행합니다.
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?"},
],
},
]messages를 apply_chat_template()에 전달하여 입력 내용을 토큰화합니다. 텍스트 모델과 달리, apply_chat_template의 출력에는 토큰화된 텍스트 외에도 전처리된 이미지 데이터를 포함하는 pixel_values 키가 있습니다.
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']
이 입력을 generate()에 전달합니다.
out = model.generate(**processed_chat.to(model.device), max_new_tokens=128)
print(processor.decode(out[0]))디코딩된 출력에는 이미지 정보를 포함하는 플레이스홀더 토큰과 사용자 메시지를 포함한 지금까지의 전체 대화 내용이 포함됩니다. 사용자에게 표시하기 전에 출력에서 이전 대화 내용을 잘라낼 수 있습니다.
비디오 입력
일부 비전 모델은 비디오 입력도 지원합니다. 메시지 형식은 이전 섹션에서 설명한 이미지 입력 형식과 매우 유사합니다.
- 콘텐츠의
"type"값은 콘텐츠가 비디오임을 나타내기 위해"video"여야 합니다. - 비디오의 경우, 비디오 링크(
"url") 또는 파일 경로("path")일 수 있습니다. 비디오는 torchcodec로 디코딩됩니다. torchcodec이 사용 불가능하고 구버전의 torchvision을 사용하는 경우, 디코딩은 torchvision으로 대체됩니다. - URL 또는 파일 경로에서 비디오를 로드하는 것 외에도, 디코딩된 비디오 데이터를 직접 전달할 수 있습니다. 이는 메모리의 다른 위치에서 이미 비디오 프레임을 전처리하거나 디코딩한 경우에 유용합니다. 파일을 저장하거나 URL에 저장할 필요가 없습니다.
PyAV와 Decord는 사용할 수 있지만, 비디오를 직접 디코딩하고
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?"},
],
},
]예: 디코딩된 비디오 객체 전달
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?"}
],
},
]기존의 ("load_video()") 함수를 사용하여 비디오를 로드하고, 메모리에서 비디오를 편집한 후 메시지를 전달할 수도 있습니다.
# 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?"}
],
},
]입력 내용을 토큰화하려면 messages를 apply_chat_template()에 전달합니다. 샘플링 프로세스를 제어하는 몇 가지 추가 매개변수를 apply_chat_template()에 포함해야 합니다.
num_frames 매개변수는 비디오에서 균일하게 샘플링할 프레임 수를 제어합니다. 각 체크포인트는 사전 학습 시 사용된 최대 프레임 수를 가지며, 이 수를 초과하면 생성 품질이 크게 저하될 수 있습니다. 모델 용량과 하드웨어 리소스 모두에 맞는 프레임 수를 선택하는 것이 중요합니다. num_frames이 지정되지 않으면 프레임 샘플링 없이 비디오 전체가 로드됩니다.
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())이 입력들은 이제 generate()에서 사용할 준비가 되었습니다.
더 긴 비디오의 경우, fps 파라미터를 사용하여 더 많은 프레임을 샘플링하는 것이 더 나은 표현을 위해 더 적합할 수 있습니다. 이 파라미터는 초당 몇 개의 프레임을 추출할지 결정합니다. 예를 들어, 비디오가 10초이고 fps=2인 경우, 모델은 20개의 프레임을 샘플링합니다. 다시 말해, 10초마다 2개의 프레임이 균일하게 샘플링됩니다.
processed_chat = processor.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=True,
return_dict=True,
fps=16,
)
print(processed_chat.keys())비디오는 전체 비디오 파일이 아니라 이미지로 저장된 샘플링된 프레임의 집합으로 존재할 수도 있습니다.
이 경우 이미지 파일 경로 목록을 전달하면 프로세서가 자동으로 이를 비디오로 연결합니다. 동일한 비디오에서 가져온 것으로 간주되므로 모든 이미지의 크기가 동일한지 확인하세요.
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())