Мультимодальный RAG 2025: полный гайд по работе с текстом, изображениями, аудио и видео | AiManual
AiManual Logo Ai / Manual.
28 Дек 2025 Гайд

Мультимодальный RAG в 2025: новые подходы для работы с текстом, изображениями, аудио и видео

Глубокий разбор мультимодального RAG в 2025: архитектуры, инструменты, векторные базы данных и практическая реализация для работы с разными типами данных.

Проблема: почему классический RAG уже недостаточен

Если вы работаете с RAG (Retrieval-Augmented Generation), то знаете, что до 2024 года большинство систем были ориентированы исключительно на текстовые данные. Но реальный мир — это не только текст. Это презентации с графиками, обучающие видео с аудиокомментариями, медицинские снимки с описаниями, подкасты с транскриптами. Классический RAG теряет 80% информации, когда работает только с текстом.

Мультимодальный RAG — это не просто "RAG плюс картинки". Это принципиально новый подход к индексации и поиску, где разные типы данных (текст, изображения, аудио, видео) представлены в едином векторном пространстве и могут взаимно дополнять друг друга при поиске.

Архитектурные подходы к мультимодальному RAG

1Единое эмбеддинг-пространство vs. гибридный поиск

Существует два основных подхода к организации мультимодального поиска:

ПодходПреимуществаНедостаткиКогда использовать
Единое пространство эмбеддингов• Естественное сравнение разных модальностей
• Простая архитектура
• Быстрый поиск
• Требует специализированных моделей (CLIP, ImageBind)
• Потеря специфичных признаков модальностей
Для простых приложений, где важна семантическая близость
Гибридный поиск (мультивекторный)• Использует лучшие модели для каждой модальности
• Сохраняет специфичные признаки
• Гибкая настройка весов
• Сложная архитектура
• Требует объединения результатов
• Выше затраты на индексацию
Для экспертных систем, где точность критична

2Современные модели для мультимодальных эмбеддингов

В 2025 году появилось несколько прорывных моделей, которые изменили ландшафт:

  • CLIP-ViT-L/14@336px: Стандарт для изображений, но теперь с улучшенным разрешением и лучшим пониманием контекста
  • ImageBind от Meta: Поддерживает 6 модальностей (изображение, текст, аудио, глубина, тепловые данные, IMU) в едином пространстве
  • OpenCLIP: Открытая реализация с поддержкой множества языков и доменов
  • AudioCLIP: Специализированная версия для аудио и звуков
  • VideoCLIP: Расширение для видео с временным измерением
💡
Для локального запуска этих моделей потребуется соответствующее железо. В нашем обзоре RTX Pro 6000 vs. RTX 4090 для локальных LLM мы подробно разбираем, какое оборудование лучше подходит для мультимодальных задач.

Практическая реализация: пошаговый план

1Подготовка данных: извлечение и сегментация

Первым шагом является подготовка мультимодальных данных. Разные типы контента требуют разных подходов:

import cv2
import whisper
from PIL import Image
import pytesseract

# Пример: обработка видео файла
def process_video(video_path, frame_interval=10):
    """Извлекает кадры, аудио и текст из видео"""
    cap = cv2.VideoCapture(video_path)
    frames = []
    frame_count = 0
    
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
            
        if frame_count % frame_interval == 0:
            # Конвертируем BGR в RGB
            rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            pil_image = Image.fromarray(rgb_frame)
            
            # Извлекаем текст с кадра (если есть)
            text = pytesseract.image_to_string(pil_image)
            
            frames.append({
                'frame': pil_image,
                'timestamp': frame_count / cap.get(cv2.CAP_PROP_FPS),
                'extracted_text': text
            })
        
        frame_count += 1
    
    cap.release()
    return frames

# Извлечение аудио и транскрибирование
model = whisper.load_model("base")
result = model.transcribe("video.mp4")
audio_segments = result["segments"]

2Создание мультимодальных эмбеддингов

Ключевой этап — преобразование разных типов данных в векторы:

import torch
from transformers import CLIPProcessor, CLIPModel
import librosa
import numpy as np

class MultimodalEmbedder:
    def __init__(self):
        # Модель для текста и изображений
        self.clip_model = CLIPModel.from_pretrained("openai/clip-vit-large-patch14-336")
        self.clip_processor = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14-336")
        
        # Модель для аудио (можно использовать Wav2Vec2 или аналоги)
        self.audio_model = torch.hub.load('s3prl/s3prl', 'wav2vec2')
    
    def embed_image(self, image):
        """Создание эмбеддинга для изображения"""
        inputs = self.clip_processor(images=image, return_tensors="pt")
        with torch.no_grad():
            image_features = self.clip_model.get_image_features(**inputs)
        return image_features.numpy()[0]
    
    def embed_text(self, text):
        """Создание эмбеддинга для текста"""
        inputs = self.clip_processor(text=text, return_tensors="pt", padding=True)
        with torch.no_grad():
            text_features = self.clip_model.get_text_features(**inputs)
        return text_features.numpy()[0]
    
    def embed_audio(self, audio_path, sr=16000):
        """Создание эмбеддинга для аудио"""
        audio, _ = librosa.load(audio_path, sr=sr)
        # Преобразуем аудио в формат, подходящий для модели
        audio_tensor = torch.from_numpy(audio).float().unsqueeze(0)
        with torch.no_grad():
            features = self.audio_model(audio_tensor)
        return features.mean(dim=1).numpy()[0]

Важно: для локального запуска больших моделей эмбеддингов потребуется значительный объем VRAM. В нашем гайде "Как избежать основных ошибок при локальном запуске больших LLM" мы разбираем типичные проблемы с памятью и способы их решения.

3Векторные базы данных для мультимодального RAG

Выбор векторной БД критически важен для производительности системы. Вот сравнение популярных вариантов в 2025:

База данныхПоддержка мультимодальностиМакс. размерностьГибридный поискЛучший сценарий
Qdrant 1.9+Нативная поддержка2000+ДаВысоконагруженные продакшн-системы
Weaviate 1.24+Через модули2048ДаСложные схемы с мультитенантностью
PineconeОграниченная2000НетБыстрый старт, облачные решения
ChromaDB 0.5+Экспериментальная2000ЧастичноПрототипирование и разработка
Milvus 2.4+Через плагины32768ДаОчень большие наборы данных
# Пример индексации в Qdrant с мультимодальными данными
from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance, PointStruct
import numpy as np

class MultimodalIndexer:
    def __init__(self, collection_name="multimodal_data"):
        self.client = QdrantClient("localhost", port=6333)
        self.collection_name = collection_name
        
        # Создаем коллекцию с несколькими векторными пространствами
        self.client.recreate_collection(
            collection_name=collection_name,
            vectors_config={
                "image": VectorParams(size=768, distance=Distance.COSINE),
                "text": VectorParams(size=768, distance=Distance.COSINE),
                "audio": VectorParams(size=1024, distance=Distance.COSINE)
            }
        )
    
    def index_document(self, doc_id, image_embedding, text_embedding, audio_embedding, metadata):
        """Индексируем документ с несколькими типами эмбеддингов"""
        point = PointStruct(
            id=doc_id,
            vector={
                "image": image_embedding.tolist(),
                "text": text_embedding.tolist(),
                "audio": audio_embedding.tolist()
            },
            payload=metadata
        )
        self.client.upsert(
            collection_name=self.collection_name,
            points=[point]
        )

4Мультимодальный поиск и ранжирование

Поиск в мультимодальном RAG — это не просто поиск по векторам. Это сложный процесс объединения результатов из разных модальностей:

class MultimodalRetriever:
    def __init__(self, indexer, embedder):
        self.indexer = indexer
        self.embedder = embedder
    
    def search(self, query, modality_weights=None, limit=10):
        """Поиск по мультимодальному запросу"""
        if modality_weights is None:
            modality_weights = {"text": 0.4, "image": 0.3, "audio": 0.3}
        
        results = {}
        
        # Если запрос содержит текст
        if isinstance(query, str):
            query_text_embedding = self.embedder.embed_text(query)
            text_results = self.indexer.search(
                vector={"text": query_text_embedding},
                limit=limit * 2  # Берем больше для последующего объединения
            )
            results["text"] = text_results
        
        # Если запрос содержит изображение (в реальной системе будет обработка)
        # Аналогично для аудио
        
        # Объединяем и ранжируем результаты
        return self._fuse_results(results, modality_weights)
    
    def _fuse_results(self, results_dict, weights):
        """Объединение результатов из разных модальностей"""
        fused_scores = {}
        
        for modality, results in results_dict.items():
            weight = weights.get(modality, 0.1)
            
            for result in results:
                doc_id = result.id
                score = result.score * weight
                
                if doc_id not in fused_scores:
                    fused_scores[doc_id] = {
                        "total_score": 0,
                        "modality_scores": {},
                        "payload": result.payload
                    }
                
                fused_scores[doc_id]["total_score"] += score
                fused_scores[doc_id]["modality_scores"][modality] = result.score
        
        # Сортируем по общему скорингу
        sorted_results = sorted(
            fused_scores.items(),
            key=lambda x: x[1]["total_score"],
            reverse=True
        )
        
        return sorted_results[:10]

Новые подходы и тренды 2025 года

1. Cross-Modal Attention Retrieval

Вместо простого сравнения эмбеддингов, современные системы используют механизмы внимания между модальностями. Например, при поиске по текстовому запросу "человек играет на гитаре", система может:

  • Найти изображения с гитарами
  • Найти аудио с гитарной музыкой
  • Найти видео, где в кадре есть и гитара, и человек
  • Связать эти результаты через cross-attention механизмы

2. Временные эмбеддинги для видео

Видео — это не просто последовательность кадров. Новые подходы учитывают:

  • Динамику изменения сцены
  • Взаимодействие объектов во времени
  • Аудиовизуальную синхронизацию
  • Контекстные переходы между кадрами
💡
Для работы с видео требуется значительные вычислительные ресурсы. В статье "Стратегии масштабирования локальных LLM" мы рассматриваем подходы к распределенной обработке видеофайлов.

3. Онлайн-обучение эмбеддингов

В 2025 году появились системы, которые адаптируют эмбеддинг-модели под специфику домена в процессе работы:

# Псевдокод для онлайн-адаптации эмбеддингов
class AdaptiveEmbedder:
    def __init__(self, base_model):
        self.base_model = base_model
        self.domain_adaptation_layer = torch.nn.Linear(768, 768)
        self.feedback_buffer = []
    
    def adapt_from_feedback(self, query, retrieved_items, user_feedback):
        """Адаптация на основе пользовательского фидбека"""
        # Сохраняем пары запрос-релевантный_документ
        self.feedback_buffer.append({
            'query': query,
            'positive': retrieved_items[user_feedback['relevant']],
            'negative': retrieved_items[user_feedback['irrelevant']]
        })
        
        # Периодическая дообучение
        if len(self.feedback_buffer) >= 100:
            self._fine_tune_on_buffer()

Распространенные ошибки и как их избежать

Ошибка #1: Использование разных размерностей эмбеддингов без нормализации.
Решение: Приводите все эмбеддинги к единой размерности через проекционные слои или используйте модели с одинаковой выходной размерностью.

Ошибка #2: Игнорирование временного аспекта в видео и аудио.
Решение: Используйте модели с поддержкой временных последовательностей (TimeSformer, VideoMAE) и сегментируйте контент на осмысленные фрагменты.

Ошибка #3: Слишком сложная система ранжирования, которая замедляет поиск.
Решение: Начинайте с простых подходов (взвешенная сумма) и усложняйте только при необходимости. Кэшируйте результаты частых запросов.

Ошибка #4: Недостаточные метаданные для кросс-модального поиска.
Решение: Всегда сохраняйте информацию о происхождении данных (из какого документа/видео/аудиофайла), временные метки, разрешение, длительность и другую контекстную информацию.

Инструменты и фреймворки для быстрого старта

В 2025 году экосистема мультимодального RAG значительно выросла:

  • LlamaIndex 0.10+: Добавлена нативная поддержка мультимодальных индексов и ретриверов
  • LangChain 0.2+: Мультимодальные цепочки и агенты с поддержкой Vision LLMs
  • Haystack 2.0+: Пайплайны для обработки смешанного контента
  • CLIP-as-service: Микросервисная архитектура для масштабирования инференса CLIP
  • Jina AI: Энд-ту-энд платформа для мультимодального поиска
💡
Для локального тестирования мультимодальных систем рекомендую начать с Ollama, который теперь поддерживает модели с визуальными возможностями.

Практический пример: система поиска в обучающих материалах

Давайте рассмотрим реальный кейс — создание системы поиска по курсу, который включает видео-лекции, презентации PDF, аудио-интервью и текстовые конспекты.

# Архитектура системы
class CourseSearchSystem:
    def __init__(self):
        self.processor = MultimodalProcessor()
        self.embedder = UnifiedEmbedder()
        self.indexer = QdrantIndexer()
        self.retriever = HybridRetriever()
        self.llm = self._load_llm()  # Например, LLaMA-3.2-Vision
    
    def index_course(self, course_materials):
        """Индексация всего курса"""
        for material in course_materials:
            # Обработка в зависимости от типа
            if material.type == "video":
                segments = self.processor.extract_video_segments(material.path)
                for segment in segments:
                    embedding = self.embedder.embed_video_segment(segment)
                    self.indexer.add(
                        embedding=embedding,
                        metadata={
                            "type": "video",
                            "course": material.course_id,
                            "timestamp": segment.timestamp,
                            "duration": segment.duration,
                            "transcript": segment.transcript
                        }
                    )
            # Аналогично для других типов...
    
    def search(self, query, course_id=None):
        """Поиск по курсу"""
        # Получаем релевантные фрагменты
        results = self.retriever.retrieve(query, course_filter=course_id)
        
        # Формируем контекст для LLM
        context = self._format_context(results)
        
        # Генерируем ответ с ссылками на материалы
        response = self.llm.generate(
            f"На основе контекста ответь на вопрос: {query}\n\nКонтекст: {context}"
        )
        
        return {
            "answer": response,
            "sources": results,
            "suggested_materials": self._suggest_related(results)
        }

FAQ: ответы на частые вопросы

Q: Сколько данных нужно для обучения мультимодальной системы?

A: Для базовой системы достаточно нескольких тысяч примеров пар "контент-описание". Для специализированных доменов (медицина, инженерия) потребуются десятки тысяч размеченных примеров или использование техник few-shot learning.

Q: Можно ли использовать мультимодальный RAG на CPU?

A: Для инференса небольших моделей (CLIP-ViT-B/32) — да, но производительность будет ограничена. Для обработки видео и работы с большими моделями необходим GPU. В статье про запуск LLM на старом железе есть рекомендации по оптимизации.

Q: Как оценивать качество мультимодального поиска?

A: Используйте метрики: MRR (Mean Reciprocal Rank), NDCG@K, Precision@K. Для субъективной оценки создайте тестовый набор запросов с эталонными релевантными документами. Особое внимание уделите кросс-модальной релевантности (находит ли система изображения по текстовому описанию и наоборот).

Q: Какие есть альтернативы CLIP для русскоязычного контента?

A: Рассмотрите ruCLIP от SberAI, Multilingual CLIP или дообучите OpenCLIP на русскоязычных данных. Также можно использовать отдельные модели для текста (например, LaBSE) и изображений, а затем объединять их через проекционные слои.

Q: Как обрабатывать конфиденциальные данные (медицинские снимки, документы)?

A: Используйте локальные модели, шифрование данных на диске, приватные векторные базы данных. Для особо чувствительных данных рассмотрите federated learning подходы или дифференциально-приватные эмбеддинги.

Заключение и будущее мультимодального RAG

Мультимодальный RAG в 2025 перестал быть экспериментальной технологией и стал стандартом для сложных систем поиска и анализа информации. Ключевые направления развития:

  1. Унификация эмбеддинг-пространств — переход к моделям, которые естественным образом работают со всеми типами данных
  2. Интерактивное обучение — системы, которые обучаются на лету на основе пользовательского фидбека
  3. Эффективность — методы сжатия эмбеддингов, квантования и акселерации для работы на edge-устройствах
  4. Объяснимость — возможность понять, почему система нашла именно этот документ/изображение/видео

Начинать внедрение мультимодального RAG стоит с пилотного проекта на ограниченном наборе данных, постепенно добавляя новые типы контента и улучшая механизмы поиска. Уже сегодня эта технология позволяет создавать системы, которые действительно понимают контент во всей его полноте, а не только текстовую составляющую.

💡
Для глубокого погружения в тему рекомендую также изучить нашу статью про квантование моделей, которое особенно актуально для развертывания мультимодальных систем на ограниченных ресурсах.