中文翻译暂不可用,显示俄语原文。

Как вы делаете RAG для изображений (image retrieval without text)?

Краткий тезис

RAG для изображений без текста строится на мультимодальных эмбеддингах, чаще всего с помощью модели CLIP, которая переводит и изображения, и текст в единое векторное пространство. Все изображения индексируются в векторной БД (FAISS, Pinecone). Запрос может быть как текстовым описанием, так и другим изображением — его эмбеддинг вычисляется той же моделью, после чего выполняется поиск по косинусной близости. Для мультимодального RAG (текст + изображения) применяется reranking|late fusion — объединение результатов двух независимых retrieval-каналов.


1. Термин: Image Retrieval без текста

Image retrieval — задача поиска изображений, релевантных запросу. Классический подход требует текстовых меток или аннотаций. «Без текста» означает, что у самих изображений в базе нет текстовых описаний — только визуальное содержание. Решение — использовать мультимодальные эмбеддинги, которые кодируют и изображения, и текст в общее пространство, позволяя сравнивать их напрямую.

Ключевая идея: если модель обучена совмещать модальности (например, CLIP), то эмбеддинг изображения и эмбеддинг текстового запроса будут близки, если изображение соответствует запросу. Таким образом, retrieval возможен без единого слова в базе изображений.


2. Модель CLIP: основа современного image retrieval

CLIP (Contrastive Language-Image Pre-training) — модель от OpenAI, обученная на 400 млн пар (изображение, текст) с использованием контрастивной потери (contrastive loss). Она состоит из двух энкодеров: Image Encoder (обычно ViT или ResNet) и Text Encoder (Transformer). На выходе — нормализованные векторы фиксированной размерности (например, 512 или 768).

Принцип работы

  • Для каждой пары (изображение, текст) в батче считается косинусная близость между эмбеддингами.
  • Модель учится увеличивать близость для правильных пар и уменьшать для неправильных (InfoNCE loss).
  • После обучения эмбеддинги разных модальностей выровнены: изображение кота и текст «кот» имеют похожие векторы.

Почему CLIP подходит для image retrieval без текста:

  • Эмбеддинги изображений можно вычислить один раз и сохранить.
  • Запрос может быть текстом (например, «красная машина») — его эмбеддинг сравнивается с эмбеддингами изображений.
  • Запрос может быть другим изображением — его эмбеддинг вычисляется Image Encoder'ом, и поиск идёт среди эмбеддингов изображений (image-to-image retrieval).

3. Индексация изображений в векторной БД

Процесс подготовки базы изображений:

  1. Извлечение эмбеддингов каждое изображение прогоняется через Image Encoder CLIP (или другую мультимодальную модель). Получаем вектор фиксированной размерности.
  2. Нормализация эмбеддинги нормализуются (L2-норма), чтобы косинусная близость равнялась скалярному произведению.
  3. Загрузка в векторную БД используется FAISS (Facebook AI Similarity Search), Pinecone, Weaviate или Milvus. Для больших коллекций применяется ANN (Approximate Nearest Neighbors)индексы типа IVF, HNSW, PQ.
  4. Метаданные: вместе с эмбеддингом хранятся ссылка на файл, возможно, теги или дата создания — для пост-фильтрации.

Пример кода (FAISS):

import torch
import clip
import faiss
import numpy as np

model, preprocess = clip.load("ViT-B/32")
device = "cuda"

# Загружаем изображения, получаем эмбеддинги
image_embeddings = []
for img_path in image_paths:
    image = preprocess(Image.open(img_path)).unsqueeze(0).to(device)
    with torch.no_grad():
        emb = model.encode_image(image).cpu().numpy()
    image_embeddings.append(emb)

image_embeddings = np.vstack(image_embeddings).astype('float32')
faiss.normalize_L2(image_embeddings)

# Строим индекс
index = faiss.IndexFlatIP(image_embeddings.shape[1])  # Inner Product = cosine similarity
index.add(image_embeddings)

# Сохраняем
faiss.write_index(index, "image_index.faiss")

4. Retrieval: текстовый запрос

Если пользователь вводит текст (например, «закат на море»):

  1. Текст кодируется Text Encoder'ом CLIP → получаем вектор запроса.
  2. Вектор нормализуется.
  3. Выполняется поиск в FAISS: index.search(query_vector, k=10).
  4. Возвращаются top-k изображений с наибольшей косинусной близостью.

Важно модель CLIP обучена на естественном языке, поэтому запросы лучше формулировать как описания, а не отдельные слова. Например, вместо «кошка» лучше «фотография кошки, сидящей на подоконнике».


5. Retrieval: запрос-изображение (image-to-image)

Когда пользователь загружает изображение и хочет найти похожие:

  1. Изображение-запрос кодируется Image Encoder'ом CLIP.
  2. Полученный эмбеддинг сравнивается со всеми эмбеддингами в базе (косинусная близость).
  3. Возвращаются наиболее похожие изображения.

Этот сценарий часто используется в системах поиска по визуальному сходству (например, поиск товаров по фото). CLIP здесь работает как visual backbone, но можно использовать и специализированные модели (например, DINOv2), которые дают более чистые визуальные признаки без текстового выравнивания. Однако CLIP удобен тем, что единая модель работает и для текстовых, и для визуальных запросов.


6. Ранжирование и пост-обработка

После получения top-k кандидатов можно применить дополнительные этапы:

  • Re-ranking использовать более тяжёлую модель (например, ViT-L/14 CLIP или даже мультимодальный LLM) для переоценки близости.
  • Фильтрация по метаданным если известны дата, автор, категория — отсеять неподходящие.
  • Deduplication удалить дубликаты (почти одинаковые изображения).
  • Query expansion: для текстового запроса можно сгенерировать несколько синонимов, усреднить эмбеддинги (или объединить результаты).

Пример re-ranking с помощью косинусной близости на более точной модели:

# После первого прохода (быстрый индекс) берём top-100
# Пересчитываем эмбеддинги через более качественный энкодер
fine_model, _ = clip.load("ViT-L/14")
# ... пересчёт и сортировка

7. Мультимодальный RAG: объединение текста и изображений

Часто требуется RAG-система, которая работает и с текстовыми документами, и с изображениями. Возможны две стратегии:

СтратегияОписаниеПлюсыМинусы
Early fusionЭмбеддинги текста и изображений объединяются в одном векторном пространстве (например, через CLIP) и хранятся в одной БД.Простота, единый поискПотеря специфики модальностей, сложность с разными размерностями
Late fusionДва независимых retrieval: текстовый (через text embeddings) и визуальный (через image embeddings). Результаты объединяются (ранжирование, конкатенация).Каждый канал оптимизирован под свою модальность, гибкостьДва индекса, больше latency

Late fusion — более распространённый подход в production. Этапы:

  1. Текстовый запрос идёт в текстовый индекс (например, на основе Sentence-BERT).
  2. Тот же запрос (или его часть) идёт в визуальный индекс (CLIP image embeddings).
  3. Результаты объединяются: можно взять top-k из каждого канала и перемешать, или использовать weighted sum scores.

Пример кода (псевдо):

text_results = text_index.search(text_emb, k=5)
image_results = image_index.search(text_emb, k=5)  # text_emb от CLIP
combined = merge(text_results, image_results, weights=[0.7, 0.3])

8. Проблемы и ограничения

  • Domain shift CLIP обучен на интернет-данных, может плохо работать на специфических доменах (медицина, спутниковые снимки). Решение — fine-tune CLIP на своих данных.
  • Размер эмбеддинга для миллионов изображений хранение векторов (512 float32 = 2KB на изображение) может быть затратным. Используют Product Quantization (PQ) для сжатия.
  • Скорость ANN-индексы (HNSW) дают субсекундный поиск для 10M+ векторов, но требуют настройки параметров.
  • Качество эмбеддингов CLIP не идеален для тонких визуальных различий (например, разные породы собак). Альтернативы: SigLIP, OpenCLIP, BLIP-2.
  • Отсутствие текстовых меток если нужно искать по конкретным атрибутам (например, «фото с красным автомобилем 2020 года»), CLIP может не справиться — требуется fine-tuning или добавление метаданных.

9. Альтернативы CLIP

МодельОсобенностьКогда использовать
DINOv2Self-supervised, только визуальные признакиЧистый image-to-image поиск, без текстовых запросов
BLIP-2Мультимодальный encoder-decoder, лучше понимает сложные запросыКогда нужен высококачественный retrieval + генерация
SigLIPАналогичен CLIP, но с сигмоидной loss, часто лучшеЕсли CLIP даёт плохие результаты
ImageBindШестимодальная модель (изображение, текст, аудио, глубина и др.)Мультимодальные запросы (например, «найди изображение, похожее на этот звук»)

Пет-проект для закрепления

Задача Создать сервис поиска изображений по текстовому описанию (image retrieval without text) на основе CLIP и FAISS.

Инструменты

  • Python, PyTorch, CLIP (openai/clip-vit-base-patch32)
  • FAISS (faiss-cpu или faiss-gpu)
  • Streamlit (интерфейс)
  • Датасет: Unsplash Lite (25k изображений) или собственные фото

Шаги:

  1. Скачать датасет изображений (например, Unsplash Lite).
  2. Написать скрипт для извлечения эмбеддингов через CLIP (использовать батчи, GPU).
  3. Нормализовать эмбеддинги и построить FAISS индекс (IndexFlatIP для точности или HNSW для скорости).
  4. Создать Streamlit-приложение: поле ввода текста, кнопка поиска, вывод top-5 изображений с косинусной близостью.
  5. Добавить возможность загрузить своё изображение для image-to-image поиска.
  6. (Опционально) Реализовать re-ranking через ViT-L/14.
  7. Оценить качество: вручную проверить 20 запросов, посчитать HR@5.

Ожидаемый результат Работающий веб-интерфейс, который по тексту «закат в горах» показывает релевантные фото, а по загруженному изображению кота — похожих котов.


Связь с другими вопросами

ВопросТема
1Проектирование RAG-системы
5Оценка качества retrieval
7Уменьшение latency
10Self-RAG
540Мультимодальные эмбеддинги
542Agentic RAG с изображениями

Навигация