Гайд · TNWS AI

Как выполнить nearestNeighbor-поиск Vespa через YQL и rank-profile

4 мин—

Рабочая схема YQL nearestNeighbor: totalTargetHits, input.query(q), ranking, hits и проверка источника ответа.

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

Русскоязычный поисковый запрос: «как выполнить nearestNeighbor Vespa YQL». Материал проверен по официальной документации Vespa, актуальной на 19 сентября 2026 года. Для Vespa с числовым tensor-полем embedding, включённым индексом HNSW и rank-profile semantic, определяющим query(q) и closeness(field, embedding). Ниже передаём готовый вектор; если в приложении настроен embedder, строковый вызов embed(...) — отдельный вариант, требующий его конфигурации.

nearestNeighbor(embedding,q) сопоставляет документное tensor-поле и query tensor. Аннотация totalTargetHits задаёт число кандидатов для ранжирования, тогда как hits ограничивает итоговую выдачу. ranking=semantic выбирает rank-profile; одно наличие ANN-индекса не определяет итоговый score. Вектор запроса должен совпадать с типом входа профиля и с моделью документа.

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

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

  1. Получите embedding вопроса той же моделью и тем же протоколом предварительной обработки.
  2. Проверьте размерность и конечность всех чисел до HTTP-запроса.
  3. Укажите YQL с nearestNeighbor, totalTargetHits и имя документного поля.
  4. Передайте input.query(q) и ranking=semantic; hits задайте отдельно от размера пула кандидатов.
  5. Проверьте source_id и текст каждого hit на небольшой вручную размеченной выборке.

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

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

vespa query   'yql=select source_id,text from article where {totalTargetHits:10}nearestNeighbor(embedding,q)'   'input.query(q)=[0.10,0.20,0.30]'   'ranking=semantic' 'hits=3'

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

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

Вход: вопрос Как оформить возврат? преобразован в трёхмерный canary vector, в корпусе есть запись refund:1 о возврате и shipping:1 о доставке. Ожидается не фиксированный искусственный score, а возврат source_id и текста без самого embedding и включение релевантной записи в top-3 на настоящем embedding-тесте.

Для реального теста подготовьте десять вопросов и ручную разметку допустимых source_id. Рассчитывайте Recall@3 и сравнивайте порядок с устойчивой контрольной версией. Если выдача пуста, диагностируйте документный ID, наличие вектора, совпадение schema/rank-profile и формат input.query(q); бессмысленно повышать hits, когда оператор не получает совместимого tensor. Если документ найден, но ответ LLM ошибается, разделите retrieval и generation: сначала проверьте фактический фрагмент, затем prompt. Не считайте closeness вероятностью того, что документ прав: это функция близости в конкретной конфигурации расстояния и набора данных. Для production не возвращайте массив embeddings клиенту без практической необходимости.

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

  • Имя tensor-поля в YQL совпадает со схемой.
  • Имя q и его тип совпадают с inputs профиля.
  • totalTargetHits не смешан с размером ответа hits.
  • На размеченных вопросах считается доля найденных source_id.

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

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

  • Путать ranking с названием embedding-модели.
  • Выполнять запрос с вектором другой модели той же размерности.
  • Считать высокий score подтверждением истинности ответа.

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

FAQ

Нужен ли rank-profile?

Да, он задаёт вычисление и порядок результатов.

Почему hits=3, но кандидатов 10?

Кандидаты ранжируются до ограничения конечной выдачи.

Можно ли подать сам вопрос вместо vector?

Только при отдельно настроенном Vespa embedder и соответствующем запросе.

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

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

Нужен ли rank-profile?

Да, он задаёт вычисление и порядок результатов.

Почему `hits=3`, но кандидатов 10?

Кандидаты ранжируются до ограничения конечной выдачи.

Можно ли подать сам вопрос вместо vector?

Только при отдельно настроенном Vespa embedder и соответствующем запросе.

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

Комментарии

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