Решения

Мультимодальные LLM: текст+изображения/видео

Задача страницы. Показать, как собрать и обучить MLLM‑модель (текст↔изображение/видео): архитектуры, данные, бюджет VRAM, пайплайны обучения, экономию памяти и сервинг.

TL;DR

  • Базовая схема: визуальный энкодерпроектор в токены LLMязыковая модель. Для видео добавляется временной слой: выбор кадров, агрегация по времени.
  • Старт быстрее всего: заморозить визуальный энкодер, дообучать проектор + несколько слоёв LLM (LoRA/QLoRA), обучать на инструкционных парах (изображение/кадры, текст).
  • Память решается: BF16, Flash‑Attention, gradient checkpointing, packing, для видео — степ‑семплинг кадров/ресэмплер.
  • Бюджет: для 7B MLLM с 224–336px и μ=1 достаточно 24–48 GB VRAM; видео‑модели с 16–32 кадрами комфортно чувствуют себя на 80 GB+ или нескольких GPU.

Архитектуры: из чего состоит MLLM

Компоненты

  1. Визуальный энкодер (ViT/Conv‑сеть) → даёт визуальные токены.
  2. Проектор (линейный/MLP/перцивер‑ресэмплер/Q‑Former) → сжимает/нормирует визуальные токены и приводит их к размерности эмбеддингов LLM.
  3. LLM (каузальная LM) → принимает текстовые токены и вставки визуальных токенов; обучается автогрешностью (language modeling loss/инструкционный SFT).

Варианты

  • Frozen‑vision: визуальный энкодер заморожен; дообучаем проектор (+ LoRA на части LLM). Минимальный бюджет VRAM.
  • E2E‑обучение: размораживаем часть блоков энкодера — дороже, но лучше адаптируется к домену (сканы/схемы/камеры).
  • Видео: кадры → энкодер (кадрово) → временная агрегация (ресэмплер/attention по времени) → проектор → LLM. Ключ — контролировать число кадров и их разрешение.

Данные и задачи

Классы задач

  • VQA / Doc‑VQA (вопрос‑ответ по изображению/документу), image captioning, OCR‑подсказки, grounding/референсные регионы, мультитёрн‑инструкции «объясни, опиши, сравни».
  • Видео: описание клипа, события, пошаговые инструкции, ответы по нескольким кадрам.

Форматы выборок

  • JSONL с полями: image_path | frames[], prompt, response, опционально bbox/regions, task.
  • Шарды (tar/WebDataset или MDS) — изображения/видео+метаданные в одном архиве; это удобно для быстрого последовательного I/O.
  • Сплиты/версии: фиксируйте версии датасетов, семена, распределение задач (например, 70/15/15).

Разметка

  • Инструкционные пары: «Покажи/Объясни/Опиши/Извлеки таблицу…».
  • Для видео: стратегия кадров — равномерная выборка (stride), ключевые кадры, «кадры‑якоря» начала/конца.

Быстрая оценка VRAM: сколько «весят» визуальные токены

Изображение (ViT‑patch):
Число визуальных токенов ≈ (H / P) × (W / P)
Где P — размер патча (напр., 14).
Примеры:

  • 224×224, P=14 → 16×16 = 256 токенов.
  • 336×336, P=14 → 24×24 = 576 токенов.

Видео:
токенов ≈ токены_кадра × число_кадров (до агрегации).
Снижайте стоимость: уменьшите разрешение, используйте ресэмплер/пулинг, ограничьте кадры (например, 16–32).

Практика

  • Начните с 224–336px и μ=1; при OOM урежьте разрешение, уменьшите кадры, включите checkpointing и LoRA.
  • При целевом длинном контексте (много инструкций) планируйте рост последовательности и KV‑кэша.

Пайплайны обучения (ступени)

A) Выравнивание зрение↔текст (опционально)

 Короткая стадия, если энкодер новый: учим проектор + голову LLM на задачах «описание/ответ по картинке», чтобы визуальные токены «встроились» в пространство LLM.

B) Инструкционный SFT (основная)

 Обучаем диалоговые форматы: (система) + (пользователь c <image>/<video>) → (ответ). Смешивайте задачи (описание, VQA, рассуждение, таблицы/счёты).

C) Доп. корректировка поведения (опционально)

 Предпочтения/безопасность через DPO/RLHF на мультимодальных парах — особенно для пользовательских ассистентов.

Связанные разделы:
/solutions/llm-training/finetune-lora//solutions/llm-training/rlhf-dpo//solutions/llm-training/eval/

Экономия памяти: что включать в первую очередь

  • LoRA/QLoRA на LLM и обязательно на проектор; визуальный энкодер оставить замороженным.
  • BF16 (или FP16 с GradScaler), Flash‑Attention, gradient checkpointing, packing коротких инструкций в фиксированную длину.
  • Снижение визуальной нагрузки: 224–288px; для видео — 8–16 кадров на старте, затем увеличивать.
  • Эффективный батч через grad accumulation.
    См. /solutions/llm-training/mixed-precision/ и /solutions/llm-training/memory-opt/.

Мини‑рецепты (код)

A) Обёртка даталоадера для изображений (WebDataset → PIL → тензор)

				
					# схема: каждый сэмпл содержит fields: image (JPEG/PNG), json (prompt/response)
import io, json, torch
from PIL import Image

def decode_sample(sample, tokenizer, image_processor):
    img = Image.open(io.BytesIO(sample["image"])).convert("RGB")
    pixel_values = image_processor(images=img, return_tensors="pt")["pixel_values"][0]
    text = json.loads(sample["json"].decode("utf-8"))
    enc = tokenizer(text["prompt"] + tokenizer.eos_token, return_tensors="pt")
    labels = tokenizer(text["response"] + tokenizer.eos_token, return_tensors="pt")["input_ids"][0]
    return {
        "pixel_values": pixel_values,  # [C,H,W]
        "input_ids": enc["input_ids"][0],
        "attention_mask": enc["attention_mask"][0],
        "labels": labels
    }

				
			

B) LoRA на проектор + части LLM

				
					from peft import LoraConfig, get_peft_model

# предположим, что model имеет .visual_projector и LLM-блоки
lora = LoraConfig(r=16, lora_alpha=32, lora_dropout=0.05, bias="none",
                  target_modules=["q_proj","k_proj","v_proj","o_proj","up_proj","down_proj","gate_proj"])
model.llm = get_peft_model(model.llm, lora)

# для проектора (если это nn.Linear):
proj_lora = LoraConfig(r=8, lora_alpha=16, lora_dropout=0.05, bias="none",
                       target_modules=["visual_projector"])
model.visual_projector = get_peft_model(model.visual_projector, proj_lora)

# не забыть: bf16/fp16 autocast, gradient checkpointing, отключить use_cache на обучении

				
			

C) Видео: выборка кадров и «пачка»

				
					import av   # PyAV или ffmpeg-python, выбирайте по окружению

def sample_frames(container_path, num=16, stride=4):
    # равномерно N кадров с шагом stride
    frames = []
    with av.open(container_path) as c:
        stream = c.streams.video[0]
        for i, frame in enumerate(c.decode(stream)):
            if i % stride == 0:
                frames.append(frame.to_image())   # PIL Image
            if len(frames) == num:
                break
    return frames  # список PIL-кадров

				
			

Метрики и проверка качества (минимум)

  • Короткая валидация: caption/VQA подвыборка, точность по ответам, длина/полнота описаний.
  • Глубокая проверка: многошаговые инструкции (таблицы, формулы, мелкий текст), мультитёрн‑диалоги.
  • Для видео — сравнение на клипах разной длительности и разных стратегиях выборки кадров.

Связанный раздел: /solutions/llm-training/eval/

Стоимость и планирование

  • On‑Demand для итераций и отладки; Interruptible для длинных эпох с надёжным чекпоинтингом.
  • Учитывайте: VRAM, NVMe‑кэш под датасеты/шарды, исходящий трафик при выгрузке чекпоинтов.

См. /solutions/cost-planner/, /solutions/llm-training/checkpointing/, /solutions/storage-data/.

Сервинг и прод

  • Для инференса держите строго такой же препроцессинг изображений/видео, как на обучении.
  • Для батчинга запросов с картинками используйте prefix‑кэширование подсказок/системных сообщений.
  • Следите за KV‑кэшем (много визуальных токенов → рост памяти), настраивайте пределы контекста и размер батча.

См. /solutions/llm-inference/, /solutions/llm-inference/vllm/, /solutions/monitoring-logging/.

Типовые конфигурации (ориентиры)

  • Изображения, 7B, 224–336px: 1×L40S/4090/A100‑40GB, μ=1, grad‑accum 8–32, BF16, LoRA на LLM+проектор.
  • Изображения, 13B: 1×A100‑80GB или 2×A100‑40GB с FSDP/ZeRO; μ=1, BF16, чекпоинтинг.
  • Видео, 7B, 16 кадров 224px: 1×A100‑80GB/H100‑80GB или 2×A100‑40GB; начать с μ=1 и stride=4.

(Дальше масштабируйтесь по GPU/узлам: см. /solutions/llm-training/fsdp-deepspeed/ и /solutions/multi-gpu/.)

Чек‑лист перед стартом

  • Формат данных утверждён (JSONL + шардирование), есть manifest и версии.
  • Визуальный энкодер и проектор согласованы по размерности; LLM принимает «визуальные» токены.
  • Включены BF16/FP16, Flash‑Attention, gradient checkpointing; use_cache=False на обучении.
  • LoRA/QLoRA на LLM и проектор; слои, попадающие в LoRA, перечислены явно.
  • Оценка: мини‑набор задач (VQA/doc‑VQA/caption), стабильные сиды и сплиты.
  • Чекпоинтинг атомарный, выгрузка во внешнее хранилище; план перезапуска.
  • Мониторинг GPU/узла и алерты собраны.