Гайд · TNWS AI

Как измерить Recall@10 ANN-поиска Vespa через exact baseline

4 мин—

Два сопоставимых nearestNeighbor-запроса с approximate:false, формула Recall@10 и ограничения exact baseline.

Какую задачу решаем и где применимо

Русскоязычный поисковый запрос: «как сравнить ANN и exact поиск Vespa». Материал проверен по официальной документации Vespa, актуальной на 19 сентября 2026 года. Для Vespa с HNSW на tensor-поле и неизменным корпусом. Exact-запрос применяется как временная оценочная линия, а не универсальная замена ANN в онлайн-трафике. Стандартный query timeout может быть недостаточен на большом объёме, поэтому диагностируйте таймаут, а не записывайте его как пустую выдачу.

Аннотация approximate:false принуждает точный nearest-neighbor-поиск даже при наличии HNSW. ANN по умолчанию приблизителен для проиндексированного tensor-поля; точный и приблизительный пути должны иметь одинаковые фильтр, embedding, rank-profile и число результатов для честного сравнения. totalTargetHits не тождественен параметру hits.

До начала эксперимента подготовьте маленький набор документов с известными source_id и один отрицательный пример. Сохраните версию schema, embedding-модели, набор входных вопросов и ожидаемые IDs: так результат можно воспроизвести после обновления системы, а не оценивать по одному удачному ответу. Все значения для маленького tensor в шаблоне — иллюстрация контрактов, не показатели качества модели.

Пошаговое выполнение

  1. Заморозьте корпус, набор вопросов и embedding-модель, присвойте каждому вопросу case_id.
  2. Запустите exact запрос с approximate:false,totalTargetHits:10, соберите top-10 source_id.
  3. Запустите ANN-запрос с теми же условиями и totalTargetHits:10, соберите top-10.
  4. Для каждого case_id вычислите размер пересечения множеств ID, делённый на десять; отдельно отметьте корпус с менее чем десятью подходящими объектами.
  5. Сопоставьте recall с p50/p95/p99 при целевой нагрузке и только после этого меняйте один HNSW-параметр.

Эти шаги предполагают доступ к собственному тестовому приложению Vespa. Для Vespa Cloud и самостоятельной установки способы деплоя отличаются; не угадывайте имена кнопок консоли. Используйте показанный интерфейс schema, YQL или CLI, сверяя конкретное окружение и permissions с документацией. При деплое сохраняйте предыдущее определение, чтобы сопоставить результаты и откатить неудачное изменение без смешения двух причин.

Готовый шаблон

# exact: фрагмент YQL
select source_id from article where {approximate:false,totalTargetHits:10}nearestNeighbor(embedding,q)

# ANN: те же профиль, вектор, фильтр и hits=10
select source_id from article where {totalTargetHits:10}nearestNeighbor(embedding,q)

Recall@10 = |set(exact_ids) ∩ set(ann_ids)| / 10

Шаблон адаптируйте к своей размерности и именам документов. Если он содержит ручной трёхмерный вектор, он полезен для smoke-теста схемы и синтаксиса, но не заменяет настоящий embedding вопроса. Секреты провайдера, токены Vespa и данные закрытых клиентов не вставляйте ни в публичный prompt, ни в статью, ни в логи запроса.

Конкретный вход и ожидаемый выход

Вход: exact IDs [a,b,c,d,e,f,g,h,i,j], ANN IDs [a,b,c,d,e,f,g,h,x,y]. Ожидаемый Recall@10 равен 8/10=0.8, а не 1.0 из-за одинакового первого результата. Фиксируйте ещё и порядок/nDCG, если пользователю важны верхние позиции.

Оценка совпадения с exact не измеряет полезность текста для человека. Можно сохранить Recall@10 и ухудшить ответы из-за плохого chunking либо устаревших источников. Поэтому рядом храните экспертную разметку и результат генератора с цитатами. Для filtered retrieval используйте один и тот же ACL в обоих запросах; сравнение без фильтра даёт ложное ощущение качества. Exact на большом корпусе дороже и может не уложиться в обычный бюджет задержки, что прямо отмечено в документации. Выполняйте baseline вне критического пользовательского пути и задайте достаточный timeout для эксперимента. Изменяйте только один фактор — totalTargetHits, hnsw.exploreAdditionalHits или граф — и записывайте его цену в памяти и задержке.

Сравнение сценариев

МетодПоискНазначение
approximate:falseточный переборэталон IDs на замороженном корпусе
ANN/HNSWприблизительный графонлайн-поиск с измеряемым recall

Вывод: сопоставляйте эти варианты на своих вопросах и зафиксированном корпусе. Изменение конфигурации имеет смысл только если оно улучшает оговорённую метрику и укладывается в допустимую задержку.

Проверка результата

  • Одинаковые модель, корпус, фильтр, rank-profile и hits.
  • Таймаут exact не интерпретирован как пустая выдача.
  • Recall@10 рассчитан по IDs, а не по численным score.
  • Задержка и потребление ресурсов измерены отдельно.

Успех означает прохождение всех перечисленных пунктов на положительных и отрицательных кейсах. Снимите фактические IDs, число hits и latency до и после изменения; если есть LLM-ответ, проверьте цитаты вручную. Пустой результат из-за ошибки типов, времени ожидания, прав доступа или отсутствующей записи нельзя выдавать за низкую релевантность. Удобно хранить отдельный отчёт по каждым case_id, иначе невозможно обнаружить регрессию на редких формулировках.

Типичные ошибки: чего не делать

  • Сравнивать exact без ACL с ANN под фильтром.
  • Приравнивать совпадение первого ID к идеальному Recall@10.
  • Переключать весь онлайн-трафик на exact без нагрузочного теста.

Не исправляйте нерелевантную выдачу произвольным повышением top-k: сперва отделите ошибку модели, схемы, фильтра и ранжирования. Не отключайте проверку tenant ради красивого теста. Не делайте вывод о производительности на крошечном демонстрационном корпусе; проверяйте рабочий объём, конкурентную нагрузку и p95, а также расход памяти/скорость обновлений там, где они существенно меняются.

FAQ

Что даёт approximate:false?

Точный поиск для контрольного набора.

Можно ли сравнивать score вместо IDs?

Для Recall@k нужно пересечение идентификаторов.

Точность поиска равна качеству ответа?

Нет, отдельно проверяют релевантность текста и генерацию.

Официальные источники

Частые вопросы

Что даёт approximate:false?

Точный поиск для контрольного набора.

Можно ли сравнивать score вместо IDs?

Для Recall@k нужно пересечение идентификаторов.

Точность поиска равна качеству ответа?

Нет, отдельно проверяют релевантность текста и генерацию.

Читайте также

Комментарии

Пока тихо. Скажите первое слово