Как создать мультимодальное приложение поиска с помощью Chroma?
Как разработать мультимодальное приложение для поиска с использованием Chroma?
Введение
Вы когда-нибудь задумывались, как наш сложный мозг обрабатывает мир? В то время как внутренние процессы мозга остаются загадкой, мы можем сравнить его с универсальной нейронной сетью. Благодаря электрохимическим сигналам, он обрабатывает различные типы данных – звук, видео, запахи, вкусы и осязание. С развитием искусственного интеллекта появляются многофункциональные модели, революционирующие возможности поиска. Эта инновация открывает новые возможности, повышая точность и актуальность поиска. Откройте захватывающий мир многофункционального поиска.
Цели обучения
- Понять термин «многообразие в искусственном интеллекте».
- Получить представление о модели OpenAI по обработке изображений и текста CLIP.
- Узнать, что такое векторная база данных и кратко понять векторное индексирование.
- Использовать CLIP и векторную базу данных Chroma для создания рекомендателя еды с интерфейсом Gradio.
- Исследовать другие реальные примеры использования многофункционального поиска.
Эта статья была опубликована в рамках Data Science Blogathon.
Что такое многообразие в искусственном интеллекте?
Если вы зайдете в Google, вы узнаете, что многообразие означает вовлечение нескольких режимов или методов в процесс. В искусственном интеллекте многообразные модели – это нейронные сети, которые могут обрабатывать и понимать различные типы данных. Например, GPT-4 и Bard. Это модели, которые могут понимать тексты и изображения. Другими примерами могут быть автомобили Tesla, объединяющие визуальные и сенсорные данные для восприятия окружающей среды, а также Midjourney или Dalle, которые могут создавать изображения на основе текстовых описаний.
Контрастное предварительное обучение языком и изображением (CLIP)
CLIP – это многофункциональная нейронная сеть с открытым исходным кодом от OpenAI, обученная на большом наборе пар изображений и текста. Это обеспечивает возможность CLIP связывать визуальные концепции на изображениях с текстовыми описаниями. Модель CLIP может быть научена классифицировать широкий спектр изображений на основе человеческой речи без специального обучения.
- «Универсальная карта быстрой разработки фреймворк контекстуальных строительных лесов (CSF)»
- Исследуйте улучшенные возможности проверки данных Pydantic V2
- «Используйте LLM только в том случае, если вы знаете, как выполнять задачу самостоятельно»
Возможность нулевого примера CLIP сравнима с моделью GPT 3. Поэтому CLIP может использоваться для классификации изображений на любое множество категорий без необходимости обучения на этих конкретных категориях. Например, для классификации изображений собак и кошек нам просто нужно сравнить оценки логитов изображения с текстовым описанием “изображение собаки” или “изображение кошки”; Фотография кошки или собаки имеет больше шансов иметь более высокие оценки логитов с соответствующими текстовыми описаниями.
Это известно как классификация по нулевому примеру, потому что CLIP не требуется обучение на наборе изображений собак и кошек для их классификации. Вот визуальное представление работы CLIP.
CLIP использует Vision Transformer (ViT) для изображений и модель текста для текстовых особенностей. Векторные кодировки проецируются на общее векторное пространство с одинаковыми размерностями. Скалярное произведение между ними используется в качестве показателя сходства для предсказания сходства между фрагментом текста и изображением. Другими словами, CLIP может классифицировать изображения в любой набор категорий без оптимизации для них. В этой статье мы реализуем CLIP программно.
Зачем нужны векторные базы данных?
Алгоритмы машинного обучения не понимают данные в их исходном формате. Поэтому, чтобы они работали, нам нужно преобразовать данные в их числовую форму. Векторы или эмбеддинги – это числовые представления различных типов данных, таких как тексты, изображения, аудио и видео. Однако традиционные базы данных не обладают достаточной возможностью для запросов на высокомерном векторном данных. Для создания приложения, которое использует миллионы векторных эмбеддингов, нам нужна база данных, способная хранить, искать и запрашивать их. Это невозможно с использованием традиционных баз данных. Для достижения этого нам нужны векторные базы данных, созданные специально для хранения и запроса эмбеддингов.
На следующей иллюстрации показан упрощенный рабочий процесс векторной базы данных.
Нам потребуются специализированные модели встраивания, способные уловить скрытое семантическое значение данных. Модели различаются в зависимости от типов данных. Используйте модели изображений, такие как Resnet или Visual Transformers для обработки изображений. Для текстов используются модели текстов, такие как Ada и SentenceTransformers. Для кросс-модального взаимодействия используются мультимодальные модели, такие как Tortoise (текст в речь) и CLIP (текст в изображение). Эти модели будут использоваться для получения встраиваний входных данных. Векторные базы данных обычно имеют специальные реализации моделей встраивания, но мы также можем определить собственные модели для получения встраиваний и сохранения их в векторных хранилищах.
Индексирование
Встраивания обычно имеют высокую размерность, и запросы поиска векторов с высокой размерностью часто требуют много времени и вычислительных ресурсов. Поэтому векторные базы данных используют различные методы индексирования для эффективного поиска. Индексирование представляет собой организацию векторов с высокой размерностью таким образом, чтобы обеспечивать эффективный поиск ближайших соседей.
Некоторые популярные алгоритмы индексирования: HNSW (Hierarchical Navigable Small World), Quantizing Product, Inverted File System, Scalar Quantization и т. д. Из всех этих алгоритмов наиболее популярным и широко используемым в различных векторных базах данных является HNSW.
В этом приложении мы будем использовать базу данных Chroma Vector. Chroma – это открытая векторная база данных. Она позволяет быстро настроить клиент для сохранения и запроса векторов и связанных метаданных. Есть и другие подобные векторные хранилища, которые вы можете использовать, такие как Weaviate, Qdrant, Milvus и т. д.
Что такое Gradio?
Gradio, написанный на Python, направлен на быстрое создание веб-интерфейса для обмена моделями машинного обучения в качестве инструмента с открытым исходным кодом. Он позволяет нам создавать демонстрационный веб-интерфейс с использованием Python. Он обеспечивает гибкость в создании достойного прототипа для демонстрации моделей на backend.
Для получения дополнительной информации о создании см. эту статью.
Создание приложения
В этом разделе мы рассмотрим коды для создания простого приложения рекомендации ресторанного блюда с использованием Gradio, Chroma и CLIP. Chroma пока не поддерживает многомодальные модели. Поэтому это будет обходное решение.
Есть два способа использовать CLIP в вашем проекте. Либо реализация CLIP от OpenAI, либо реализация CLIP от Huggingface. В этом проекте мы будем использовать реализацию CLIP от OpenAI. Убедитесь, что у вас есть виртуальная среда с установленными следующими зависимостями.
import clip, torch\nfrom numpy import ndarray\nfrom typing import List\nfrom PIL import Image\nclass ClipEmbeddings:\n def __init__(self, model_name: str = "ViT-B/32", device: str = "cpu"):\n self.device = device # Сохраняем указанное устройство для выполнения модели\n self.model, self.preprocess = clip.load(model_name, self.device)\n\n def __call__(self, docs: List[str]) -> List[ndarray]:\n # Определяем метод, который принимает список путей к изображениям как входные данные\n list_of_embeddings = [] # Создаем пустой список для хранения встроенных изображений\n for image_path in docs:\n image = Image.open(image_path) # Открываем и загружаем изображение из указанного пути\n image = image.resize((224, 224)) # Предварительно обрабатываем изображение и перемещаем его на указанное устройство\n image_input = self.preprocess(image).unsqueeze(0).to(self.device)\n with torch.no_grad():\n # Вычисляем встраивания изображения с помощью модели CLIP и преобразуем их в массивы NumPy\n embeddings = self.model.encode_image(image_input).cpu().detach().numpy()\n list_of_embeddings.append(list(embeddings[0]))\n return list_of_embeddings\n\n def get_text_embeddings(self, text: str) -> List[ndarray]:\n # Определяем метод, который принимает текстовую строку в качестве входных данных\n text_token = clip.tokenize(text) # Токенизируем входной текст\n with torch.no_grad():\n # Вычисляем текстовые встроенные вектора, используя модель CLIP и преобразуем их в массивы NumPy\n text_embeddings = self.model.encode_text(text_token).cpu().detach().numpy()\n return list(text_embeddings[0])
В вышеуказанном коде мы определили класс для извлечения вложений текстов и изображений. Класс принимает имя модели и устройство в качестве входных данных. Если ваше устройство поддерживает Cuda, вы можете включить его, передав устройство. CLIP поддерживает несколько моделей, таких как
clip.available_models()['RN50', 'RN101', 'RN50x4', 'RN50x16', 'RN50x64', 'ViT-B/32', 'ViT-B/16', 'ViT-L/14', 'ViT-L/14@336px']
По умолчанию имя модели установлено как “ViT-B/32”. Вы можете передать любую другую модель по вашему желанию.
Метод __call__ принимает список путей к изображениям и возвращает список массивов numpy. Метод get_text_embeddings принимает входные данные в виде строки и возвращает список вложений.
Загрузка вложений
Сначала нам нужно заполнить нашу базу данных векторов. Для этого я собрал несколько изображений блюд, чтобы добавить их в нашу коллекцию. Создайте список путей к изображениям и список описаний о них. Пути к изображениям будут нашими документами, а описания изображений мы будем хранить как метаданные.
Но сначала создайте коллекцию Chroma.
import osfrom chromadb import Client, Settingsfrom clip_embeddings import ClipEmbeddingsfunctionfrom typing import Listef = ClipEmbeddingsfunction()client = Client(settings = Settings(is_persistent=True, persist_directory="./clip_chroma"))coll = client.get_or_create_collection(name = "clip", embedding_function = ef)
Мы импортировали ранее определенную функцию вложения и передали ее в качестве функции вложения по умолчанию для коллекции.
Теперь загрузите данные в базу данных.
coll.add(ids=[str(i) for i in range(len(img_list))], documents = img_list, #пути к изображениям metadatas = menu_description,# описание блюд )
Вот и все. Теперь вы готовы приступить к созданию финальной части.
Приложение Gradio
Сначала создайте файл app.py, импортируйте следующие зависимости и инициируйте функцию вложения.
import gradio as grfrom chromadb import Client, Settingsfrom clip_embeddings import ClipEmbeddingsfunctionclient = Client(Settings(is_persistent=True, persist_directory="./clip_chroma"))ef = ClipEmbeddingsfunction()
В качестве интерфейса мы будем использовать простой интерфейс, который принимает поисковый запрос, либо текст, либо изображение, и показывает соответствующие выходные изображения.
with gr.Blocks() as demo: with gr.Row(): with gr.Column(): query = gr.Textbox(placeholder = "Введите запрос") gr.HTML("ИЛИ") photo = gr.Image() button = gr.UploadButton(label = "Загрузить файл", file_types=["image"]) with gr.Column(): gallery = gr.Gallery().style( object_fit='contain', height='auto', preview=True )
Теперь мы определим события-триггеры для приложения Gradio.
query.submit( fn = retrieve_image_from_query, inputs=[query], outputs= ) button.upload( fn = show_img, inputs=[button], outputs = [photo]).\ then( fn = retrieve_image_from_image, inputs=[button], outputs= )
В вышеуказанном коде у нас есть события-триггеры. Мы обрабатываем текстовый запрос с помощью функции retrieve_image_from_query. Сначала мы отображаем изображения на объекте photo, а затем вызываем retrieve_image_from_image(), отображая результат на объекте Gallery.
Запустите файл app.py с помощью команды gradio и перейдите по локальному адресу, указанному в терминале.
Теперь мы определим фактические функции.
def retrieve_image_from_image(image): # Получаем коллекцию с именем "clip", используя указанную функцию вложения (ef) coll = client.get_collection(name="clip", embedding_function=ef) # Извлекаем имя файла изображения image = image.name # Запрашиваем коллекцию, используя имя файла изображения в качестве текста запроса result = coll.query( query_texts=image, # Используем имя файла изображения в качестве текста запроса include=["documents", "metadatas"], # Включаем документы и метаданные в результаты n_results=4 # Указываем количество результатов для получения ) # Получаем извлеченные документы и их метаданные docs = result['documents'][0] descs = result["metadatas"][0] # Создаем список для хранения пар документов и соответствующих им метаданных list_of_docs = [] # Перебираем извлеченные документы и метаданные for doc, desc in zip(docs, descs): # Добавляем в список кортеж, содержащий документ и его метаданные list_of_docs.append((doc, list(desc.values())[0])) # Возвращаем список пар документов и метаданных return list_of_docs
У нас также есть другая функция для обработки текстовых запросов.
def retrieve_image_from_query(query: str): # Получить коллекцию "clip" с использованием указанной функции встраивания (ef) coll = client.get_collection(name="clip", embedding_function=ef) # Получить текстовые встраивания для входного запроса с использованием функции встраивания (ef) emb = ef.get_text_embeddings(text=query) # Преобразовать текстовые встраивания в значения с плавающей запятой emb = [float(i) for i in emb] # Запросить коллекцию с использованием текстовых встраиваний result = coll.query( query_embeddings=emb, # Использовать текстовые встраивания в качестве запроса include=["documents", "metadatas"], # Включить документы и метаданные в результаты n_results=4 # Указать количество результатов для извлечения ) # Получить извлеченные документы и их метаданные docs = result['documents'][0] descs = result["metadatas"][0] # Создать список для хранения пар документов и соответствующих метаданных list_of_docs = [] # Перебрать извлеченные документы и метаданные for doc, desc in zip(docs, descs): # Добавить кортеж, содержащий документ и его метаданные, в список list_of_docs.append((doc, list(desc.values())[0])) # Вернуть список пар документ-метаданные return list_of_docs
Вместо передачи текстов напрямую в коде мы извлекли встраивания и затем передали их методу запроса Чомы.
Итак, вот полный код для app.py.
# Импортировать необходимые библиотекиimport gradio as grfrom chromadb import Client, Settingsfrom clip_embeddings import ClipEmbeddingsfunction# Инициализировать клиента chromadb с постоянным хранилищемclient = Client(Settings(is_persistent=True, persist_directory="./clip_chroma"))# Инициализировать функцию ClipEmbeddingsef = ClipEmbeddingsfunction()# Функция для получения изображений из текстового запросаdef retrieve_image_from_query(query: str): # Получить коллекцию "clip" с указанной функцией встраивания coll = client.get_collection(name="clip", embedding_function=ef) # Получить текстовые встраивания для входного запроса emb = ef.get_text_embeddings(text=query) emb = [float(i) for i in emb] # Запросить коллекцию для похожих документов result = coll.query( query_embeddings=emb, include=["documents", "metadatas"], n_results=4 ) # Извлечь документы и их метаданные docs = result['documents'][0] descs = result["metadatas"][0] list_of_docs = [] # Объединить документы и описания в список for doc, desc in zip(docs, descs): list_of_docs.append((doc, list(desc.values())[0])) return list_of_docs# Функция для получения изображений из загруженного изображенияdef retrieve_image_from_image(image): # Получить коллекцию "clip" с указанной функцией встраивания coll = client.get_collection(name="clip", embedding_function=ef) # Получить имя загруженного изображения image = image.name # Запросить коллекцию с именем файла изображения result = coll.query( query_texts=image, include=["documents", "metadatas"], n_results=4 ) # Извлечь документы и их метаданные docs = result['documents'][0] descs = result["metadatas"][0] list_of_docs = [] # Объединить документы и описания в список for doc, desc in zip(docs, descs): list_of_docs.append((doc, list(desc.values())[0])) return list_of_docs# Функция для отображения изображенияdef show_img(image): return image.name# Создать интерфейс с использованием блоковwith gr.Blocks() as demo: with gr.Row(): with gr.Column(): # Текстовое поле для запроса query = gr.Textbox(placeholder="Введите запрос") gr.HTML("ИЛИ") # Загрузка изображения через загрузку файла photo = gr.Image() button = gr.UploadButton(label="Загрузить файл", file_types=["image"]) with gr.Column(): # Отображение галереи изображений gallery = gr.Gallery().style( object_fit='contain', height='auto', preview=True ) # Определить вход и выход для отправки запросов query.submit( fn=retrieve_image_from_query, inputs=[query], outputs= ) # Определить вход и выход для загрузки изображения button.upload( fn=show_img, inputs=[button], outputs=[photo]).\ then( fn=retrieve_image_from_image, inputs=[button], outputs= )# Запустить интерфейс Gradio, если скрипт запущен как основная программаif __name__ == "__main__": demo.launch()
Теперь запустите приложение, выполнив gadio app.py в терминале и перейдите по локальному адресу.
Репозиторий GitHub: https://github.com/sunilkumardash9/multi-modal-search-app
Практические примеры использования
Мультимодальный поиск может иметь множество применений в различных отраслях.
- Электронная коммерция: Мультимодальный поиск может улучшить опыт покупок для клиентов. Например, вы можете сфотографировать товар в физическом магазине и найти похожие продукты онлайн.
- Здравоохранение: Он может помочь в диагностике заболеваний и поиске лечения. Врачи могут использовать изображение для поиска клинических исследований из медицинской базы данных.
- Образование: Приложения для образования с мультимодальным поиском могут помочь студентам и профессорам быстрее находить соответствующие документы. Получение текстов на основе изображений и наоборот может сэкономить много времени.
- Обслуживание клиентов: Мультимодальный поиск может помочь оптимизировать поиск ответов на запросы клиентов из базы знаний. Эти запросы могут содержать изображения или видео продуктов.
Заключение
Мультимодальный поиск будет революционным в будущем. Возможность взаимодействия в нескольких модальностях открывает новые возможности для роста. Поэтому этот статья описывает использование базы данных векторов Chroma и мультимодельной модели CLIP для создания базового приложения поиска. Так как Chroma-база данных не имеет “из коробки” поддержки мультимодельных моделей, мы создали пользовательский класс вложения CLIP для получения вложений изображений и объединили различные компоненты для создания приложения по поиску продуктов.
Ключевые моменты
- В ИИ мультимодальность означает способность взаимодействия с несколькими типами коммуникации, такими как текст, изображение, аудио и видео.
- CLIP – это модель совмещения изображений и текста, обученная на тысячах примеров изображений и текста с возможностью классификации “нулевого шага”.
- Векторные базы данных предназначены для хранения, поиска и запроса высокоразмерных векторов.
- Алгоритмы ANN – это движки, обеспечивающие работу Векторных Хранилищ. HNSW является одним из наиболее популярных и эффективных графических алгоритмов ANN.
Часто задаваемые вопросы
Медиа, показанное в этой статье, не принадлежит Analytics Vidhya и используется по решению автора.