От CLIP к JinaCLIP: универсальное обучение текстово-изобразительных представлений для поиска и мультимодального RAG
Недавно всплеск интереса к мультимодальным embedding-моделям привлек внимание в различных отраслях, изменив то, как машины интерпретируют текст и изображения. Однако, несмотря на значительный прогресс, эти модели сталкиваются с ключевыми проблемами, одна из которых — разрыв модальностей. Этот разрыв проявляется в том, что embedding-представления изображений и текста оказываются пространственно удалены друг от друга в латентном пространстве, даже когда описывают один и тот же объект.
На недавней встрече Unstructured Data Meetup, организованной Zilliz, Бо Ван, Engineering Manager в Jina AI, рассказал нам о сложностях разрыва модальностей и переходе от модели OpenAI CLIP к JinaCLIP.
В этом блоге мы кратко изложим его основные тезисы, а также реализуем мультимодальную систему поиска по сходству. Эта система будет использовать JinaCLIP для генерации мультимодальных embedding-представлений и векторную базу данных Milvus для хранения и извлечения похожих embedding-представлений по заданному запросу. Для получения дополнительных подробностей рекомендуем посмотреть полное выступление Бо на YouTube.
Что делает embedding-модель хорошей?
Основная функция embedding-модели — отображать такие объекты, как тексты и изображения, в векторы, числовые представления, которые отражают семантические связи внутри данных. Например, расстояние между двумя векторами должно отражать сходство двух элементов, которые они представляют, будь то два изображения, два текста или по одному из каждого типа.
Embedding-модели лежат в основе современных задач ИИ, таких как семантический поиск, поиск изображений и многое другое. Но что делает embedding-модель хорошей?
Универсальность в разных областях
Хорошая embedding-модель должна хорошо работать в широком спектре областей без необходимости дообучения. Такая адаптивность гарантирует, что embedding-представления будут универсально полезны, независимо от того, является ли входными данными текст, изображения или другие типы данных. Например, если изображение встроено в векторное пространство, а связанный текст встроен в то же пространство, два embedding-представления должны находиться близко друг к другу, что указывает на их семантическое сходство. Такая широкая применимость важна для задач ИИ, таких как поиск по сходству, поиск изображений и междоменные приложения.
Точное семантическое сходство
Ключевая характеристика хорошей embedding-модели — ее способность связывать левое и правое, создавая embedding-представления с высокими показателями сходства для семантически связанных элементов. Это выходит за рамки только текстовых данных и применимо к любым мультимодальным входным данным. Будь то сравнение текста с текстом, изображения с изображением или текста с изображением, модель должна отражать правильные связи через близость embedding-представлений в векторном пространстве.
Однако более старым моделям, которые связывали текстовые и визуальные модальности, было сложнее достичь этой цели. Они опирались на ручные процессы, такие как разметка изображений тегами или использование окружающего текста, чтобы устанавливать связи. Эти методы приводили к плохой обобщающей способности, особенно в сценариях за пределами распределения.
Проблема мультимодальных задач
До появления таких моделей, как CLIP, связывание модальностей (текста и изображений) было в значительной степени ручной задачей, основанной на гипотезах. Будь то теги Flickr или текстовые описания, добавленные пользователями, процесс был далек от бесшовного. Подходы с учителем, часто использующие метки классификаторов, были подвержены нестабильности, а их производительность вне домена была неудовлетворительной. Это означало, что, хотя изображения и тексты можно было связывать, результаты не всегда были последовательными, особенно когда входные данные были сложными.
Для решения этой проблемы была разработана CLIP, модель контрастивного предварительного обучения языка и изображений, чтобы повысить производительность мультимодальных моделей путем обучения на парах изображение-текст. Способность CLIP выравнивать две модальности в общем пространстве эмбеддингов была инновационной. Однако у этой модели также есть свои ограничения.
Модель CLIP: прорыв с ограничениями
CLIP установила новый стандарт, обучая два отдельных энкодера: один для текста и один для изображений. Основная идея заключалась в том, чтобы выучить общее пространство эмбеддингов, где текстовые и графические векторы могли бы сосуществовать, а семантически похожие тексты и изображения располагались бы ближе друг к другу. Результаты были впечатляющими: CLIP позволила выполнять мультимодальные задачи с использованием простой функции косинусного сходства.
Рисунок: Как работает модель CLIP
Однако у CLIP есть свои недостатки. Одна из существенных проблем — ее неспособность эффективно справляться с задачами, связанными только с текстом. Поскольку CLIP в основном оптимизировалась для коротких подписей (часто менее 77 символов), более длинные тексты представляют собой проблему. Кроме того, в процессе обучения CLIP отсутствовали сложные отрицательные примеры. Сложные отрицательные примеры — это примеры, которые близки, но неверны, и они крайне важны для доработки моделей, особенно в таких задачах, как поиск по тексту. Без них производительность CLIP вышла на плато в задачах, требующих детального понимания текста.
Переход к JinaCLIP: устранение недостатков Clip
JinaCLIP строится на исходной архитектуре CLIP, чтобы устранить ее ограничения. Она расширяет текстовый ввод и использует адаптированную архитектуру BERT v2 для кодирования текста. Для обработки изображений JinaCLIP включает модель EVA-02. Процесс обучения JinaCLIP сосредоточен на преодолении проблем, связанных с короткими текстовыми входами в подписях к изображениям, и введении сложных отрицательных примеров. Этот процесс проходит в три этапа, как показано ниже:
Рисунок: Процесс обучения JinaCLIP
Этапы включают обучение выравниванию, интеграцию длинных текстов и тонкую настройку:
Обучение выравниванию с короткими текстами и подписями: На этом этапе модель обучается с использованием как данных изображений с подписями, так и текстовых пар со схожими значениями. Цель состоит в том, чтобы выровнять эмбеддинги изображений и текста путем совместной оптимизации сходства текст-изображение и текст-текст. Этот процесс совместного обучения гарантирует, что, пока модель учится связывать текст с изображениями, она также сохраняет свои возможности работы только с текстом. Хотя производительность только на тексте немного снижается по сравнению с обучением исключительно на текстовых парах, эта фаза сохраняет сбалансированный подход.
Интеграция длинных текстовых описаний: На втором этапе для обучения модели вводятся синтетические данные. Эти данные сопоставляют изображения с более длинными текстами, созданными AI-моделями, описывающими содержимое более подробно. Одновременно для обучения продолжают использоваться пары только с текстом. Модель учится обрабатывать более развернутые текстовые описания, сохраняя выравнивание с изображениями, что повышает ее способность понимать как короткие, так и длинные отношения текст-изображение.
Тонкая настройка с текстовыми триплетами и сложными негативными примерами: Финальный этап сосредоточен на использовании текстовых триплетов, включающих сложные негативные примеры, то есть пары текстов, где два семантически похожи, а один намеренно отличается. Это помогает модели проводить более тонкие семантические различия, особенно в сценариях только с текстом. В то же время модель продолжает обучаться на синтетических парах изображений и длинных текстов. Этот этап значительно улучшает производительность модели в текстовых задачах, одновременно обеспечивая сохранение устойчивого выравнивания изображений и текста, изученного на предыдущих этапах.
Этот подход сохраняет высокую производительность в мультимодальных задачах, одновременно расширяя возможности в сценариях только с текстом. Давайте посмотрим, как этот новый подход сравнивается с исходным Clip.
Метрики производительности показывают изменения в качестве поиска по сравнению с исходной моделью CLIP: изменение на 165% в поиске текст-текст, 12% в изображение-изображение, 6% в изображение-текст и 2% в текст-изображение, как показано на изображении ниже.
Рисунок: Сравнение производительности моделей jina-clip, openai-clip-vit-b-16 и jina-embeddings-v2-base-en
Новый процесс обучения улучшает обобщение между задачами и помогает уменьшить разрыв между модальностями. Давайте обсудим разрыв между модальностями, серьезное препятствие в мультимодальных AI-моделях, и почему возникает эта проблема.
Разрыв между модальностями: почему он возникает
Разрыв между модальностями — это пространственное разделение между эмбеддингами разных типов входных данных, таких как тексты и изображения, которые семантически похожи, но находятся далеко друг от друга в векторном пространстве. Этот разрыв снижает эффективность мультимодальных систем поиска, поскольку эмбеддинги не полностью отражают истинную связь между связанными входными данными. Как видно на изображении ниже, представление выглядит как усеченный конус: эмбеддинги изображений находятся на одном конце, а эмбеддинги текста — на другом, что явно демонстрирует разрыв между модальностями.
Рисунок: Начальные позиции эмбеддингов изображений и текста в Jina CLIP, с полностью случайными весами и без предварительного обучения, спроецированные в два измерения
Есть несколько ключевых причин, по которым этот разрыв возникает даже в современных моделях:
Эффект конуса при инициализации
Мультимодальные модели, особенно те, которые обрабатывают текстовые и визуальные входные данные, часто используют отдельные энкодеры для каждой модальности. Эти энкодеры обычно инициализируются случайными или предварительно обученными весами, из-за чего текстовые эмбеддинги группируются в одной области векторного пространства, а эмбеддинги изображений — в другой, как видно на изображении выше. Это начальное разделение, называемое эффектом конуса, затрудняет корректное выравнивание эмбеддингов разных модальностей (например, изображений и связанных с ними текстов). Например, текстовый эмбеддинг для пушистой кошки и эмбеддинг изображения кошки могут изначально находиться далеко друг от друга из-за такого смещения при инициализации, хотя они семантически связаны.
Температурное масштабирование
Во время обучения AI-модели используют метод, называемый температурным масштабированием, в своей контрастивной функции потерь, чтобы регулировать, насколько близко выравниваются эмбеддинги. Хотя это помогает тонко настраивать расстояния между эмбеддингами, температурное масштабирование также может непреднамеренно сохранять начальное разделение между модальностями, усиливая разрыв между модальностями. Например, если температурное масштабирование не настроено тщательно, эмбеддинги для игривого щенка и изображения собаки могут оставаться слишком далеко друг от друга в векторном пространстве, хотя они описывают одну и ту же концепцию.
Ложные негативные примеры внутри батча
При обучении на больших наборах данных несовпадающие пары точек данных (например, изображение собаки, сопоставленное с текстом «красное яблоко”) рассматриваются как отрицательные примеры. Однако эти ложные отрицательные примеры всё же могут иметь некоторое семантическое пересечение. Например, если оба элемента относятся к широкой категории животных (например, изображение собаки и текст «игривый волк”), модель может отталкивать эти эмбеддинги дальше друг от друга, чем необходимо, ещё сильнее усугубляя разрыв между модальностями из-за ошибочной трактовки их как полностью несвязанных.
Понимание того, почему возникает разрыв между модальностями, — это только первый шаг. Чтобы преодолеть этот разрыв, были разработаны различные стратегии обучения, позволяющие сближать эмбеддинги из разных модальностей и обеспечивать более точный поиск в мультимодальных задачах.
Устранение разрыва между модальностями: методы обучения и не только
Разрыв между модальностями — это структурная проблема, у которой нет простого решения, но существуют стратегии для смягчения её влияния. Главное — уменьшить разделение между эмбеддингами из разных модальностей во время обучения, обеспечивая отображение изображений и текстов, которые принадлежат друг другу, ближе в векторном пространстве.
Масштабирование с более высокой температурой
На практике повышение температуры во время обучения может побуждать эмбеддинги из разных модальностей сближаться, добавляя больше случайности в процесс обучения модели. Например, повышение температуры может помочь более точно согласовать эмбеддинги изображения кошки и текста «пушистая кошка”. Однако это происходит ценой более медленной сходимости и требует больше вычислительных ресурсов. Хотя модели, обученные с масштабированием при высокой температуре, как правило, улучшают согласование текстовых и визуальных эмбеддингов, компромиссом часто становятся более длительное время обучения и повышенные вычислительные требования.
Выборка сложных отрицательных примеров
Введение сложных отрицательных примеров — несовпадающих пар, которые семантически близки, — это ещё один метод уменьшения разрыва между модальностями. Такие сложные отрицательные пары заставляют модель учиться более тонким различиям между связанными понятиями, повышая точность поиска. Например, сопоставление изображения кошки с текстом «маленький тигр» может казаться несоответствием, но модель узнаёт, что эти два входа имеют пересекающуюся семантику (оба являются кошачьими) и всё же должны быть в некоторой степени согласованы в пространстве эмбеддингов. Этот процесс учит модель распознавать как сходства, так и различия между связанными понятиями, совершенствуя её способность различать близкие совпадения.
Мультимодальный поиск с Milvus и JinaCLIP: практический пример
Теперь, когда мы рассмотрели технические причины разрыва между модальностями, давайте перейдём к практическому примеру того, как построить мультимодальную поисковую систему с использованием Milvus, открытой векторной базы данных, и JinaCLIP.
Milvus управляет, ищет и запрашивает многомерные векторы, что делает его идеальным решением для задач мультимодального поиска и задач генерации с дополнением извлечённой информацией (RAG). Независимо от того, работаете ли вы с текстом, изображениями или другими типами данных, Milvus позволяет эффективно хранить эмбеддинги и извлекать релевантные результаты с использованием продвинутых методов поиска по сходству.
В этом разделе мы пошагово рассмотрим процесс использования Milvus для создания мультимодальной поисковой системы, которая обрабатывает текстовые и визуальные эмбеддинги. Система позволит пользователям вводить либо текст, либо изображения и извлекать наиболее семантически релевантные результаты из смешанного набора данных.
Шаг 1: Настройка окружения
Сначала нам нужно установить библиотеки, которые понадобятся для нашей системы в нашем окружении:
!pip install pymilvus transformers torch timm
Затем нам нужно импортировать необходимые библиотеки и настроить наш класс кодировщика.
# Import necessary libraries
from transformers import AutoModel
from pymilvus import MilvusClient
import torch
# Define Encoder class to handle text and image embedding generation
class Encoder:
def __init__(self, model_name: str):
# Initialize the model (AutoModel from transformers instead of SentenceTransformer)
self.model = AutoModel.from_pretrained(model_name, trust_remote_code=True)
def encode_text(self, text: list[str]) -> list[float]:
# Generate embeddings for text only
with torch.no_grad():
text_emb = self.model.encode_text(text)
return text_emb
def encode_image(self, image_urls: list[str]) -> list[list[float]]:
# Generate embeddings for images only
with torch.no_grad():
image_emb = self.model.encode_image(image_urls)
return image_emb
# Initialize the encoder with the model jinaai/jina-clip-v1
model_name = "jinaai/jina-clip-v1"
encoder = Encoder(model_name)
В приведенном выше коде мы сначала импортируем необходимые библиотеки: AutoModel из transformers для нашей модели кодирования, MilvusClient для взаимодействия с Milvus и torch для операций с тензорами.
Затем мы определяем класс Encoder, который оборачивает AutoModel из transformers. Методы encode_text и encode_image используют модель для генерации эмбеддингов для текста и изображений соответственно. Менеджер контекста torch.no_grad() используется для отключения вычисления градиентов, которое не требуется для инференса и экономит память.
Наконец, мы инициализируем энкодер моделью jinaai/jina-clip-v1, которая может кодировать и текст, и изображения в общее пространство эмбеддингов.
Шаг 2: Подготовка данных
Далее мы подготовим наши примерные данные для создания эмбеддингов и вставки в Milvus.
# Load data: images and text for embeddings
sentences = ['A blue cat', 'A red cat', 'A red cat generated by AI', 'A dog biting on a stick']
image_urls = [
'https://i.pinimg.com/600x315/21/48/7e/21487e8e0970dd366dafaed6ab25d8d8.jpg',
'https://i.pinimg.com/736x/c9/f2/3e/c9f23e212529f13f19bad5602d84b78b.jpg',
'https://images.fineartamerica.com/images/artworkimages/mediumlarge/1/red-cat-art-3771-bb-james-ahn.jpg',
'https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/29708160-9b39-42d0-a5ed-4f8b9c85a267/labrador+retriever+dans+pet+care.jpeg?format=1500w'
]
# Generate embeddings for text and images
text_embeddings = encoder.encode_text(sentences)
image_embeddings = encoder.encode_image(image_urls)
# Ensure consistent dimensions
dim = len(image_embeddings[0])
Здесь мы определяем списки примерных предложений и URL-адресов изображений. URL-адреса содержат изображения рыжих кошек, синих кошек и собаки. Затем мы используем наш энкодер для генерации эмбеддингов как для текста, так и для изображений. Переменная dim хранит размерность эмбеддингов, которая понадобится нам при создании коллекции Milvus.
Шаг 3: Настройка Milvus
Теперь мы настроим наш клиент Milvus и создадим коллекцию для наших мультимодальных данных.
# Insert embeddings into Milvus
collection_name = "multimodal_rag_demo"
milvus_client = MilvusClient(uri="./milvus_demo.db")
# Check if collection exists and drop it if so
if milvus_client.has_collection(collection_name):
print(f"Collection {collection_name} already exists. Deleting it...")
milvus_client.drop_collection(collection_name)
# Create Milvus collection
milvus_client.create_collection(
collection_name=collection_name,
auto_id=True,
dimension=dim,
enable_dynamic_field=True,
)
Мы инициализируем клиент Milvus и подключаемся к локальному файлу базы данных. Мы проверяем, существует ли уже коллекция с нужным нам именем, и, если да, удаляем ее, чтобы начать с чистого листа.
Затем мы создаем новую коллекцию с указанным именем. Параметр auto_id=True указывает Milvus автоматически генерировать ID для наших записей. Мы задаем dimension в соответствии с нашими эмбеддингами и включаем динамические поля, что позволяет добавлять дополнительные метаданные к нашим записям.
Шаг 4: Создание индекса
Перед вставкой данных мы создадим индекс для оптимизации производительности поиска:
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
field_name="vector", # The field to be indexed (your embedding field)
metric_type="COSINE", # Can be L2, COSINE, etc.
index_type="FLAT", # FLAT ensures exact search, ideal for small datasets
)
# Create the index for the collection
milvus_client.create_index(collection_name, index_params)
print(f"Index created successfully for collection: {collection_name}")
Приведенный выше код создает индекс FLAT, используя косинусное сходство в качестве метрики расстояния.
Шаг 5: Вставка данных в Milvus
После настройки нашей коллекции и индекса мы можем вставить наши данные в Milvus.
data_to_insert = []
# Insert text embeddings
for idx, txt_emb in enumerate(text_embeddings):
data_to_insert.append({"text": sentences[idx], "vector": txt_emb})
# Insert image embeddings
for idx, img_emb in enumerate(image_embeddings):
data_to_insert.append({"image_url": image_urls[idx], "vector": img_emb})
# Insert data into Milvus
insert_result = milvus_client.insert(
collection_name=collection_name,
data=data_to_insert,
)
print(f"Insert result: {insert_result}")
milvus_client.load_collection(collection_name)
В приведенном выше коде мы создаем список словарей, каждый из которых содержит либо текстовое предложение, либо URL изображения вместе с соответствующим вектором эмбеддинга. Затем мы используем метод insert клиента Milvus, чтобы добавить эти данные в нашу коллекцию. После вставки мы загружаем коллекцию в память, чтобы подготовиться к поиску.
Шаг 6: Выполнение мультимодального поиска
Наконец, мы выполняем мультимодальный поиск, используя как изображения, так и текстовые запросы.
# Multimodal search with a combination of image and text query
query_image_url = 'https://imgcdn.stablediffusionweb.com/2024/4/5/5e70d71c-a7f6-44e9-972d-8c5a27d45c3d.jpg'
query_text = "Give me similar red cats"
# Generate query embedding (image + text)
query_embedding_image = encoder.encode_image([query_image_url])[0]
query_embedding_text = encoder.encode_text([query_text])[0]
# Perform search in Milvus using image embedding
search_results_image = milvus_client.search(
collection_name=collection_name,
data=[query_embedding_image],
output_fields=["image_url", "text"], # Ensure both fields are included in the results
limit=5, # Number of results to return
search_params={"metric_type": "COSINE", "params": {"nprobe": 10}}
)
# Perform search in Milvus using text embedding
search_results_text = milvus_client.search(
collection_name=collection_name,
data=[query_embedding_text],
output_fields=["image_url", "text"], # Ensure both fields are included in the results
limit=5, # Number of results to return
search_params={"metric_type": "COSINE", "params": {"nprobe": 10}}
)
# Retrieve and print results from image query
print("Image Query Results:")
for result in search_results_image:
for hit in result:
image_url = hit['entity'].get('image_url')
text = hit['entity'].get('text')
if image_url:
print(f"Retrieved Image URL (from image query): {image_url}")
if text:
print(f"Retrieved Text (from image query): {text}")
# Retrieve and print results from text query
print("Text Query Results:")
for result in search_results_text:
for hit in result:
image_url = hit['entity'].get('image_url')
text = hit['entity'].get('text')
if image_url:
print(f"Retrieved Image URL (from text query): {image_url}")
if text:
print(f"Retrieved Text (from text query): {text}")
В приведённом выше коде мы демонстрируем процесс выполнения мультимодального поиска. Мы начинаем с определения URL изображения запроса и текста запроса. Изображение запроса выглядит так:
Рисунок 2: Входное изображение запроса с рыже-белым котом
Затем мы кодируем эти запросы с помощью нашего энкодера, чтобы сгенерировать соответствующие им эмбеддинги. После этого мы выполняем два отдельных поиска в Milvus: один с использованием эмбеддинга изображения, а другой — с использованием эмбеддинга текста. Для каждого поиска мы запрашиваем в выводе поля image_url и text, что позволяет нам получать оба типа данных. Мы ограничиваем результаты до 5 для каждого поиска и используем косинусное сходство в качестве нашей метрики расстояния. Параметр nprobe в наших параметрах поиска позволяет нам точно настроить количество кластеров для поиска, обеспечивая баланс между скоростью и точностью поиска. Наконец, мы отображаем результаты, показывая, какие изображения или тексты были получены для каждого типа запроса, тем самым демонстрируя способность системы обрабатывать и сопоставлять как текстовые запросы, так и запросы на основе изображений.
Полный код можно найти здесь.
Вот примеры результатов:
Как видите, когда мы используем изображение для выполнения векторного поиска, мы получаем как URL изображений, так и текст, связанный с изображением, и наоборот. В этом и заключается сила мультимодального поиска. Вот одно из изображений, которое извлекается как похожее изображение в обоих случаях.
Рисунок 3: Выходное изображение рыжего кота после выполнения поиска по сходству в Milvus
Как видите, изображение похоже на изображение рыжего кота, которое мы передали системе в качестве нашего запроса.
Вы можете добавить reranker в эту систему, чтобы упорядочить результаты поиска по релевантности, при этом наиболее релевантные результаты будут находиться сверху. Хотя, как очевидно, Milvus хорошо справляется с извлечением лучших совпадений первыми. Вы также можете развить эту систему, создав мультимодальную RAG-систему.
Заключение
Бо Ван объяснил тонкости преодоления разрыва между модальностями в мультимодальных моделях и показал переход от CLIP к JinaCLIP. Он разобрал ключевые проблемы выравнивания текста и изображения и продемонстрировал, как JinaCLIP решает эти проблемы.
В этой статье мы расширили его идеи, создав систему мультимодального поиска по сходству с использованием JinaCLIP для генерации эмбеддингов и Milvus для эффективного извлечения. Обладая этими знаниями, теперь вы можете реализовывать свои мультимодальные поисковые приложения, обеспечивая бесперебойную работу с текстовыми запросами и запросами на основе изображений, а также пойти дальше, интегрировав продвинутые поисковые техники, такие как reranking.
Дополнительные ресурсы
Читать далее

What Is a Vector Lakebase?
A Vector Lakebase is a unified, lake-native data architecture for AI that combines vector-database-grade serving with open lake storage, reusable lake-level indexes, and a shared semantic layer.

How to Install and Run OpenClaw (Previously Clawdbot/Moltbot) on Mac
Turn your Mac into an AI gateway for WhatsApp, Telegram, Discord, iMessage, and more — in under 5 minutes.

Why Teams Are Migrating from Weaviate to Zilliz Cloud — and How to Do It Seamlessly
Explore how Milvus scales for large datasets and complex queries with advanced features, and discover how to migrate from Weaviate to Zilliz Cloud.


