Руководство для разработчиков программного обеспечения: Создание высокопроизводительных систем семантического поиска с использованием Faiss и Milvus и лучшие практики
Современным приложениям требуется способность отвечать на сложные запросы пользователей не только по ключевым словам, но и семантически. От рекомендаций продуктов до поиска документов, от чат-ботов до фильтрации контента, семантический поиск выходит за рамки традиционных методов, предлагая более релевантные и насыщенные результаты. В этом руководстве мы рассмотрим векторные базы данных – ключевые инструменты, обеспечивающие эти возможности поиска на основе ИИ, и их практические применения.
Семантический поиск и векторные представления
В основе семантического поиска лежит идея создания числовых представлений (эмбеддингов) данных (текста, изображений, аудио и т. д.) в многомерных векторных пространствах. Эти векторы захватывают семантическое содержание данных; данные, которые семантически близки, будут иметь векторы, также расположенные близко друг к другу в этом пространстве. Процесс поиска включает в себя вычисление сходства между векторным представлением запроса и другими векторами в базе данных.
Для создания векторных представлений обычно используются предварительно обученные модели глубокого обучения. Для текста доступны такие варианты, как SBERT (Sentence-BERT) или модели эмбеддингов OpenAI. Вот простой пример эмбеддинга SBERT с использованием Python:
from sentence_transformers import SentenceTransformer
import numpy as np
# Загружаем предварительно обученную модель SBERT
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
# Примеры предложений
sentences = [
"Как обучаются модели искусственного интеллекта?",
"Алгоритмы машинного обучения",
"Архитектуры глубокого обучения",
"Как работает компьютерное оборудование?"
]
# Преобразуем предложения в векторы
embeddings = model.encode(sentences)
print("Размерность вектора первого предложения:", embeddings[0].shape)
print("Косинусное сходство между векторами первых 2 предложений:", np.dot(embeddings[0], embeddings[1]) / (np.linalg.norm(embeddings[0]) * np.linalg.norm(embeddings[1])))
Почему векторные базы данных?
Традиционные реляционные или NoSQL базы данных не предназначены для эффективного выполнения поиска сходства между многомерными векторами. Поиск ближайшего соседа (Nearest Neighbor Search - NNS) или приближенного ближайшего соседа (Approximate Nearest Neighbor - ANN) среди миллионов или даже миллиардов векторов требует специализированных алгоритмов и структур индексирования. Векторные базы данных предлагают оптимизированные структуры, специально разработанные для решения этой проблемы.
Локальные и In-Memory решения: Faiss
Faiss (Facebook AI Similarity Search) — это библиотека, разработанная Facebook AI для высокопроизводительного поиска сходства и кластеризации. Она специально оптимизирована для быстрого поиска приближенных ближайших соседей по миллионам векторов. Работает в оперативной памяти (in-memory) и обычно предназначена для использования на одном сервере или на стороне клиента.
Вот простой пример создания индекса Faiss и поиска:
import faiss
# Размерность вектора и количество точек данных
d = embeddings.shape[1] # 384
nb = embeddings.shape[0] # 4 (в примере)
# Преобразование в Float32 является обычным требованием для Faiss
xb = embeddings.astype('float32')
# Создаем индекс Faiss (например, IndexFlatL2)
# Этот индекс хранит каждый вектор и выполняет точный поиск (NNS, а не ANN)
index = faiss.IndexFlatL2(d)
print("Индекс обучен?", index.is_trained) # Должно быть True, так как IndexFlatL2 не требует обучения
# Добавляем векторы в индекс
index.add(xb)
print("Количество векторов в индексе:", index.ntotal)
# Создаем вектор запроса (например, вектор первого предложения)
xq = np.array([model.encode("Информация об обучении искусственного интеллекта")])
xq = xq.astype('float32')
# Ищем 2 ближайших соседей
k = 2
distances, indices = index.search(xq, k)
print("Расстояния ближайших соседей (L2):", distances)
print("Индексы ближайших соседей:", indices)
print("Ближайшие предложения:", [sentences[i] for i in indices[0]])
Faiss предлагает различные типы индексов (IndexFlatL2, IndexIVFFlat, IndexHNSWFlat и т. д.), позволяя балансировать между производительностью и точностью. Для больших наборов данных использование алгоритмов ANN, таких как IndexIVFFlat или IndexHNSWFlat, более эффективно.
Распределенные и масштабируемые решения: Milvus
Когда вам нужно работать с миллиардами векторов или требуется высокая доступность и масштабируемость в распределенной системе, в дело вступают облачные векторные базы данных, такие как Milvus. Milvus — это система с открытым исходным кодом, разработанная для крупномасштабного векторного поиска, и может быть развернута на таких платформах, как Kubernetes.
Вот пример создания коллекции, добавления векторов и поиска с помощью Milvus (предполагается, что экземпляр Milvus запущен в Docker):
from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility
import random
# Подключаемся к серверу Milvus
connections.connect("default", host="localhost", port="19530")
# Определяем схему коллекции
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=d), # d = 384 from SBERT
FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=512)
]
schema = CollectionSchema(fields, "Это пример коллекции для семантического поиска.")
# Определяем имя коллекции
collection_name = "semantic_search_collection"
# Если коллекция уже существует, удаляем ее (для разработки)
if utility.has_collection(collection_name):
utility.drop_collection(collection_name)
# Создаем коллекцию
collection = Collection(collection_name, schema)
# Подготавливаем векторы и связанный текст
data = [
model.encode(s).tolist() for s in sentences
]
text_data = sentences
# Вставляем данные в Milvus
mr = collection.insert([data, text_data])
# Ждем синхронизации данных в Milvus
collection.flush()
print("Количество добавленных векторов:", collection.num_entities)
# Создаем индекс (например, IVFFlat)
index_params = {
"metric_type": "L2",
"index_type": "IVF_FLAT",
"params": {"nlist": 128}
}
collection.create_index(field_name="embedding", index_params=index_params)
# Загружаем коллекцию в память для поиска
collection.load()
# Подготавливаем вектор запроса
search_vector = model.encode("Методы обучения искусственного интеллекта").tolist()
# Параметры поиска
search_params = {"metric_type": "L2", "params": {"nprobe": 10}}
# Выполняем поиск
results = collection.search(
data=[search_vector],
anns_field="embedding",
param=search_params,
limit=2, # Получаем 2 ближайших результата
expr=None,
output_fields=["text"]
)
print("Результаты поиска:")
for hit in results[0]:
print(f"Расстояние (L2): {hit.distance}, Текст: {hit.entity.get('text')}")
# Освобождаем коллекцию из памяти
collection.release()
В приведенном выше примере мы рассмотрели, как создать коллекцию для семантического поиска, добавить векторы и выполнять запросы к ним, используя основные функции Milvus. Milvus поддерживает различные типы индексов, такие как FLAT, IVF_FLAT и HNSW, и благодаря своей распределенной архитектуре легко справляется с большими объемами данных и нагрузками запросов.
Лучшие практики
- Размерность и качество векторов: Используемая модель эмбеддинга, и, следовательно, размерность вектора, напрямую влияют на точность и производительность поиска. Выберите наиболее подходящую модель и размерность вектора для вашего приложения.
- Выбор типа индекса: Выбор правильного типа индекса Faiss или Milvus (например,
IVFFlat,HNSW) имеет решающее значение в зависимости от размера ваших данных и требований к точности/скорости. - Предварительная фильтрация: Используйте возможности фильтрации векторных баз данных (например, параметр
exprв Milvus) для сужения области семантического поиска на основе конкретных метаданных. Это увеличивает как скорость, так и релевантность. - Гибридный поиск: Иногда комбинация поиска по ключевым словам и семантического поиска дает наилучшие результаты. Вы можете разрабатывать возможности гибридного поиска, интегрируя векторные базы данных с традиционными поисковыми системами (например, Elasticsearch).
- Обновления и удаления: Для динамических наборов данных тщательно изучите и эффективно используйте механизмы обновления и удаления векторных баз данных.
Заключение
Векторные базы данных являются одним из краеугольных камней современных приложений искусственного интеллекта. Они предлагают широкий спектр инструментов, от локальных решений, таких как Faiss, до распределенных систем, таких как Milvus, позволяя разработчикам создавать масштабируемые и интеллектуальные системы поиска, рекомендаций и анализа данных. С помощью этого практического руководства вы сделали первый шаг к расширению своих собственных возможностей семантического поиска. Продолжайте исследовать мощь векторных баз данных в своих приложениях!
Комментарии (0)
Пока нет комментариев. Будьте первым!