Используйте Milvus и Airbyte для поиска по сходству во всех ваших данных
Milvus — популярная векторная база данных с открытым исходным кодом. Векторы — это многомерные массивы чисел. При работе с большими языковыми моделями (LLM) «эмбеддинги» конкретно относятся к последнему скрытому слою внутри компонента Encoder глубокой нейронной сети на основе трансформеров. Этот слой эмбеддингов представляет собой набор векторов, отражающих семантическое значение слов или пикселей (для текста или изображений).
Учитывая богатство информации в слое эмбеддингов обученной LLM, эффективное хранение и извлечение векторов стало критически важным. Milvus — это векторная база данных, специально созданная для хранения, индексирования и эффективного поиска высокоразмерных векторных данных. Векторные базы данных обычно используются для поиска сходства по неструктурированным данным, что позволяет улучшать ответы Generative Chat, рекомендации продуктов и другие приложения.
С помощью Airbyte легко переносить данные из множества разных источников в Milvus, попутно вычисляя векторные эмбеддинги текстов.
Сила эмбеддингов заключается в возможности искать релевантные фрагменты информации, даже если похожие концепции сформулированы по-разному. В этой статье эта функциональность будет использована, чтобы сделать форму поддержки на сайте умнее за счет поиска релевантной информации на лету. Это будет использоваться, чтобы информировать пользователя о похожих заявках, которые уже обработаны, и выделять релевантные статьи базы знаний, которые могут помочь решить проблему без помощи агента поддержки.
Мы будем использовать Zilliz Cloud в качестве нашего векторного хранилища, Airbyte для извлечения и загрузки данных, OpenAI embedding API для вычисления эмбеддингов и Streamlit для создания умной формы отправки, показывающей релевантные данные.
Вам потребуется:
Аккаунт Zendesk (или другой источник данных, из которого вы хотите синхронизировать данные)
Аккаунт Airbyte или локальный экземпляр
OpenAI API key
Аккаунт Zilliz Cloud или локальный кластер Milvus
Python 3.10, установленный локально
Шаг 1: Настройте кластер Milvus
На cloud.zilliz.com вы можете зарегистрироваться и получить бесплатный кластер для хранения ваших эмбеддингов векторов для поиска сходства. После создания аккаунта вам нужно настроить новый кластер.
Отдельные сущности (в нашем случае заявки в поддержку и статьи базы знаний) хранятся в «коллекции» — после настройки кластера вам нужно создать коллекцию. Выберите подходящее имя и установите Dimension равным 1536, чтобы оно соответствовало размерности векторов, генерируемых сервисом OpenAI embeddings:
После создания Zilliz покажет вам endpoint и API key — запишите их, поскольку они понадобятся нам на следующем шаге.
Шаг 2: Настройте подключение в Airbyte
Наша база данных готова, давайте перенесем в нее данные! Для этого нам нужно настроить подключение в Airbyte. Либо зарегистрируйтесь в облачном аккаунте Airbyte на cloud.airbyte.com, либо запустите локальный экземпляр, как описано в документации.
Когда ваш экземпляр будет запущен, нам нужно настроить подключение — нажмите “New connection” и выберите коннектор “Zendesk Support” в качестве источника.
В Airbyte cloud вы можете легко пройти аутентификацию, нажав кнопку Authenticate. При использовании локального экземпляра Airbyte следуйте инструкциям, приведенным на странице документации.
Информация::
Если вы хотите использовать другой источник данных — остальная часть этой статьи применима ко всем видам текстовых источников
::
После нажатия кнопки “Test and Save” Airbyte проверит, можно ли установить соединение. Если всё работает правильно, следующим шагом будет настройка назначения для передачи данных. Здесь выберите коннектор “Milvus”.
Коннектор Milvus выполняет три вещи:
- Разбиение на фрагменты и форматирование - Разделение записей Zendesk на текст и метаданные. Если текст больше указанного размера фрагмента, записи разбиваются на несколько частей, которые загружаются в коллекцию по отдельности. Разделение текста (или chunking) может, например, происходить в случае больших заявок в поддержку или статей базы знаний. Разделяя текст, вы можете гарантировать, что поиски всегда будут давать полезные результаты.
Давайте выберем размер фрагмента 1000 токенов и текстовые поля body, title, description и subject, поскольку они будут присутствовать в данных, которые мы получим из Zendesk.
Embedding - Использование моделей машинного обучения преобразует текстовые фрагменты, созданные частью обработки, в векторные embeddings, по которым затем можно выполнять поиск семантического сходства. Чтобы создать embeddings, необходимо предоставить ключ OpenAI API. Airbyte отправит каждый фрагмент в OpenAI и добавит полученный вектор к сущностям, загруженным в ваш кластер Milvus.
Indexing - После того как вы векторизовали фрагменты, вы можете загрузить их в базу данных. Для этого вставьте информацию, которую вы получили при настройке своего кластера и коллекции в Zilliz Cloud.
Нажатие “Test and save” проверит, правильно ли всё согласовано (действительные учетные данные, коллекция существует и имеет ту же размерность вектора, что и настроенный embedding, и т. д.)
Последний шаг перед тем, как данные будут готовы к передаче, — выбрать, какие “streams” синхронизировать. Stream — это коллекция записей в источнике. Поскольку Zendesk поддерживает большое количество streams, не относящихся к нашему варианту использования, давайте выберем только “tickets” и “articles” и отключим все остальные, чтобы сэкономить пропускную способность и убедиться, что в поиске будет отображаться только релевантная информация:
Вы можете выбрать, какие поля извлекать из источника, нажав на имя stream. Режим синхронизации “Incremental | Append + Deduped” означает, что последующие запуски соединения поддерживают синхронизацию Zendesk и Milvus, передавая минимальный объем данных (только статьи и заявки, которые изменились с момента последнего запуска).
Как только соединение настроено, Airbyte начнет синхронизировать данные. Их появление в вашей коллекции Milvus может занять несколько минут.
Если вы выберете частоту репликации, Airbyte будет запускаться регулярно, чтобы поддерживать вашу коллекцию Milvus в актуальном состоянии с учетом изменений в статьях Zendesk и новых созданных обращений.
Вы можете проверить в интерфейсе Zilliz Cloud, как данные структурированы в коллекции, перейдя в playground и выполнив запрос “Query Data” с фильтром, установленным на “_ab_stream == \”tickets\””
Как видно в представлении Result, каждая запись, поступающая из Zendesk, хранится как отдельные сущности в Milvus со всеми указанными метаданными. Текстовый фрагмент, на котором основан embedding, отображается как свойство “text” — это текст, который был преобразован в embedding с помощью OpenAI и по которому мы будем выполнять поиск.
Шаг 3: Создание приложения Streamlit, запрашивающего коллекцию
Наши данные готовы — теперь нужно создать приложение, чтобы их использовать. В этом случае приложение будет простой формой поддержки, с помощью которой пользователи смогут отправлять обращения в поддержку. Когда пользователь нажмет submit, мы сделаем две вещи:
Найдем похожие заявки, отправленные пользователями той же организации
Найдем статьи базы знаний, которые могут быть релевантны пользователю
В обоих случаях мы будем использовать семантический поиск с помощью embeddings OpenAI. Для этого описание проблемы, введенное пользователем, также преобразуется в embedding и используется для получения похожих сущностей из кластера Milvus. Если есть релевантные результаты, они отображаются под формой.
Вам понадобится локальная установка Python, так как мы будем использовать Streamlit для реализации приложения.
Сначала установите Streamlit, клиентскую библиотеку Milvus и клиентскую библиотеку OpenAI локально:
pip install streamlit pymilvus openai
Чтобы отобразить базовую форму поддержки, создайте python-файл app.py:
import streamlit as st
with st.form("my_form"):
st.write("Submit a support case")
text_val = st.text_area("Describe your problem")
submitted = st.form_submit_button("Submit")
if submitted:
# TODO check for related support cases and articles
st.write("Submitted!")
Чтобы запустить ваше приложение, используйте Streamlit run:
streamlit run app.py
Это отобразит базовую форму:
Код для этого примера также можно найти на GitHub.
Далее давайте проверим наличие существующих открытых тикетов, которые могут быть релевантны. Для этого мы преобразуем текст, введенный пользователем, в embedding с помощью OpenAI, затем выполнили поиск по сходству в нашей коллекции, отфильтровав все еще открытые тикеты. Если есть один с очень малым расстоянием между отправляемым тикетом и существующим тикетом, сообщите пользователю и не отправляйте:
import os
import pymilvus
import openai
org_id = 360033549136 # TODO Load from customer login data
pymilvus.connections.connect(uri=os.environ["MILVUS_URL"], token=os.environ["MILVUS_TOKEN"])
collection = pymilvus.Collection("zendesk")
embedding = openai.Embedding.create(input=text_val, model="text-embedding-ada-002")['data'][0]['embedding']
results = collection.search(data=[embedding], anns_field="vector", param={}, limit=5, output_fields=["_id", "subject", "description"], expr=f'status == "new" and organization_id == {org_id}')
st.write(results[0]) # debug output just for now
if len(results[0]) > 0 and results[0].distances[0] < 0.35:
matching_ticket = results[0][0].entity
st.write(f"This case seems very similar to {matching_ticket.get('subject')} (id #{matching_ticket.get('_id')}). Make sure it has not been submitted before")
else:
st.write("Submitted!")
Здесь происходит несколько вещей:
Настраивается подключение к кластеру Milvus.
Сервис OpenAI используется для генерации embedding описания, введенного пользователем.
Выполняется поиск по сходству, фильтруя результаты по статусу тикета и id организации (так как релевантны только открытые тикеты той же организации).
Если есть результаты и расстояние между embedding-векторами существующего тикета и недавно введенного текста ниже определенного порога, укажите на этот факт.
Чтобы запустить новое приложение, сначала нужно задать переменные окружения для OpenAI и Milvus:
export MILVUS_TOKEN=...
export MILVUS_URL=https://...
export OPENAI_API_KEY=sk-...
streamlit run app.py
При попытке отправить тикет, который уже существует, результат будет выглядеть так:
Код для этого примера также можно найти на GitHub.
Как видно в зеленом отладочном выводе, скрытом в финальной версии, два тикета совпали с нашим поиском (в статусе new, из текущей организации и близко к embedding-вектору). Однако первый (релевантный) получил более высокий рейтинг, чем второй (нерелевантный в этой ситуации), что отражено в более низком значении расстояния. Эта связь фиксируется в embedding-векторах без прямого совпадения слов, как в обычном полнотекстовом поиске.
В завершение давайте покажем полезную информацию после отправки тикета, чтобы предоставить пользователю как можно больше релевантной информации заранее.
Для этого мы выполним второй поиск после отправки тикета, чтобы получить наиболее подходящие статьи базы знаний:
article_results = collection.search(data=[embedding], anns_field="vector", param={}, limit=5, output_fields=["title", "html_url"], expr=f'_ab_stream == "articles"')
st.write(article_results[0])
if len(article_results[0]) > 0:
st.write("We also found some articles that might help you:")
for hit in article_results[0]:
st.write(f"* [{hit.entity.get('title')}]({hit.entity.get('html_url')})")
Если нет открытого тикета в поддержку с высокой оценкой сходства, новый тикет отправляется, а релевантные статьи базы знаний отображаются ниже:
Код для этого примера также можно найти на Github.
Хотя показанный здесь UI — это не реальная форма обращения в поддержку, а пример для иллюстрации варианта использования, сочетание Airbyte и Milvus очень мощное — оно позволяет легко загружать текст из самых разных источников (от баз данных, таких как Postgres, через API вроде Zendesk или GitHub, до полностью пользовательских источников, созданных с помощью SDK Airbyte или визуального конструктора коннекторов) и индексировать его во встроенной форме в Milvus — мощной векторной поисковой системе, способной масштабироваться до огромных объемов данных.
Airbyte и Milvus имеют открытый исходный код и полностью бесплатны для использования в вашей инфраструктуре, а при желании доступны облачные предложения, позволяющие передать эксплуатационные задачи внешнему сервису.
Помимо классического варианта использования семантического поиска, проиллюстрированного в этой статье, общая схема также может использоваться для создания чат-бота для ответов на вопросы с применением метода RAG (Retrieval Augmented Generation), рекомендательных систем или для повышения релевантности и эффективности рекламы.
Читать далее

Vector Lakebase: End the AI Data Silo
Learn how Vector Lakebase unifies vector search, data lakes, and AI data operations so teams can serve RAG and agents without copy-and-sync pipelines.

Our Journey to 35K+ GitHub Stars: The Real Story of Building Milvus from Scratch
Join us in celebrating Milvus, the vector database that hit 35.5K stars on GitHub. Discover our story and how we’re making AI solutions easier for developers.

8 Latest RAG Advancements Every Developer Should Know
Explore eight advanced RAG variants that can solve real problems you might be facing: slow retrieval, poor context understanding, multimodal data handling, and resource optimization.



