Qdrant - Vector Database

Первый поиск: Search API

Вы проиндексировали данные. Теперь самое интересное - поиск за 10-15ms по миллионам векторов. Но поиск без правильных параметров может давать нерелевантные результаты. Разберём как сделать его точным.

  • **RAG (Retrieval-Augmented Generation):** поиск контекста для LLM - score_threshold 0.75 отсекает мусор
  • **Семантический поиск:** аналог Elasticsearch, но по смыслу - limit: 10, score_threshold: 0.7
  • **Рекомендации:** 'похожие статьи' - поиск по вектору существующего документа

Предварительные знания

  • Points, Vectors, Payloads

Search API: базовый запрос

**Поиск в Qdrant** - найти K ближайших точек к query-вектору. Query-вектор - это embedding вашего запроса (текст, изображение, что угодно). Qdrant возвращает точки, отсортированные по убыванию score (сходства).

**Score** - мера сходства, зависит от выбранной метрики. Для Cosine: от -1 до 1, где 1 = идентичные векторы. На практике похожие документы: 0.85-0.99, несвязанные: < 0.5.

**Используйте ту же embedding-модель** для индексации и поиска. Если документы проиндексированы через `text-embedding-3-small`, запрос тоже должен идти через неё. Смешивать модели нельзя - пространства несовместимы.

Вы проиндексировали документы через OpenAI text-embedding-3-small (1536d). Для поиска хотите использовать более дешёвую модель ada-002 (тоже 1536d). Это сработает?

Метрики расстояния: Cosine, Dot, Euclid

**Метрика расстояния** определяет как вычисляется сходство двух векторов. Выбирается при создании коллекции и не меняется. Разные модели embeddings оптимизированы под разные метрики.

МетрикаФормулаДиапазон scoreКогда использовать
Cosinecos(a,b) = a·b / (|a|·|b|)[-1, 1], выше = лучшеТекстовые embeddings (OpenAI, Cohere, Sentence Transformers)
Dot Producta·b = Σ(aᵢ × bᵢ)[-∞, +∞], выше = лучшеНормализованные векторы, ColBERT, SPLADE
Euclid√Σ(aᵢ - bᵢ)²[0, +∞], ниже = лучшеКоординаты, физические измерения, специальные модели
ManhattanΣ|aᵢ - bᵢ|[0, +∞], ниже = лучшеРедко используется в NLP, спецзадачи

**Cosine vs Dot Product:** если векторы нормализованы (|v|=1), они дают одинаковый ранкинг. OpenAI embeddings нормализованы, так что оба работают. Cosine - более интуитивный (угол), Dot Product - чуть быстрее вычисляется (нет деления на нормы).

Вы используете OpenAI text-embedding-3-small. Документация говорит что embeddings нормализованы (|v|=1). Какие метрики дадут одинаковый ранкинг?

Параметры поиска: limit, threshold, hnsw_ef

**Параметры поиска** позволяют балансировать между точностью, скоростью и количеством результатов.

**`score_threshold`** - важный параметр для production. Без него Qdrant вернёт top-K даже если они совсем не похожи на запрос. С threshold - только реально релевантные результаты.

**Как подобрать score_threshold:** сделайте 20-30 тестовых запросов, посмотрите на score у правильных и неправильных результатов. Граница между ними - ваш threshold. Обычно он стабилен для конкретной модели + домена данных.

В RAG-приложении поиск всегда возвращает 5 результатов, даже на нерелевантные запросы ('какой сегодня день?'). Как это исправить?

Результаты: payload, векторы и пагинация

**Управление результатами** - что возвращается в ответе, как делать пагинацию и искать по конкретным полям payload.

**`with_payload: {include: ['field1', 'field2']}`** - рекомендуется в production. Большой payload увеличивает размер ответа. Если нужен только `title` и `url` - не запрашивайте всё остальное.

Большой offset для пагинации: `offset: 1000, limit: 10`

Для пагинации в vector search нет эффективного решения с большим offset. Лучше возвращать больше результатов (top-50) и пагинировать на стороне клиента

При offset=1000 Qdrant вычисляет top-1010 и возвращает последние 10 - это O(offset × log N). Векторный поиск не предназначен для deep pagination. Альтернатива: scroll() для обхода коллекции, или ограничить пагинацию до 2-3 страниц

Вам нужно делать 10 семантических поисков параллельно в одном запросе. Какой метод использовать?

Ключевые идеи

  • **search(collection, {vector, limit})** - базовый API. Query-вектор из той же модели, что и при индексации
  • **Score** - мера сходства. Для Cosine: 1=идентично, >0.8=очень похоже, <0.5=нерелевантно
  • **score_threshold** - обязателен в production. Без него поиск вернёт K результатов даже для нерелевантного запроса
  • **Метрики:** Cosine/Dot для текстовых embeddings, Euclid для координат. Ориентир - документация модели
  • **hnsw_ef** - точность vs скорость. Default (64) - хороший баланс. `exact: true` только для тестов
  • Помните hook? 10-15ms при миллионах векторов - это HNSW + правильные параметры

Что дальше

Базовый поиск работает. Следующий уровень - понять как HNSW делает это за миллисекунды.

  • HNSW - как работает индекс — Понять m, ef_construct, ef - настроить качество поиска
  • Фильтрация по payload — Фильтры must/should/must_not - найти документы с нужными метаданными
  • Hybrid Search — Сочетание семантического и keyword поиска для лучших результатов

Вопросы для размышления

  • Как выбрать score_threshold для своего домена данных? Какой эксперимент провести?
  • Если поиск возвращает 0 результатов с threshold 0.8, но 10 с threshold 0.6 - что это говорит о качестве embeddings или данных?
  • Чем семантический поиск Qdrant лучше Elasticsearch full-text search? А хуже?

Связанные уроки

  • alg-10-binary-search
Первый поиск: Search API

0

1

Войти