Перейти к содержанию

Вопросы для оценки поиска и ответа

Результат поиска выглядит убедительно, когда вопрос совпадает с формулировкой в документе. Однако библиотека должна помогать и при других словах, отсутствии доказательств или ограниченном доступе. Подготовим независимый набор случаев, с которым можно разбирать качество поиска и ответа. В этом уроке мы составляем материал для будущих наблюдений, а не публикуем несуществующие результаты эксперимента.

Состояние lesson-11 содержит evaluation-cases.json. В нём четыре учебных вопроса и пустой массив runs. Программы, модели и замеры автором не запускались. После урока у читателя будет договор: какие источники считаются полезными, какие запрещены и как интерпретировать разные состояния ответа.

Вопрос отличается от запроса из примера

Когда разработчик подбирает вопрос специально под один абзац, он проверяет отдельный маршрут, но мало узнаёт о библиотеке. Контрольный вопрос должен выражать задачу читателя. Например, «Как сохранить адрес статьи?» описывает потребность и допускает разные формулировки исходного текста.

Набор полезно составлять до подбора параметров поиска. Иначе возникает соблазн менять вопросы вслед за удачной выдачей. Параметр, подобранный под известные примеры, может плохо работать на новых обращениях. Для серьёзного сравнения нужна отдельная часть вопросов, которую не использовали при настройке.

В нашей маленькой лаборатории четыре случая не представляют реальный поток пользователей ProfessorWeb. Это исходная форма записи, которую предстоит расширить собственными вопросами. Нельзя на её основе утверждать процент качества для всей библиотеки или обещать, что система понимает любой учебный материал.

{
  "fictional": true,
  "runs": [],
  "cases": [
    {
      "id": "urls",
      "query": "Как сохранить адрес статьи?",
      "role": "reader",
      "relevant_doc_ids": [
        "urls"
      ],
      "forbidden_doc_ids": [
        "editor"
      ]
    },
    {
      "id": "cache",
      "query": "Как проверить версию кэшированного документа?",
      "role": "reader",
      "relevant_doc_ids": [
        "cache"
      ],
      "forbidden_doc_ids": [
        "editor"
      ]
    },
    {
      "id": "unknown",
      "query": "Какой курс акций будет завтра?",
      "role": "reader",
      "relevant_doc_ids": [],
      "forbidden_doc_ids": [
        "editor"
      ]
    },
    {
      "id": "private",
      "query": "Служебная заметка редактора",
      "role": "editor",
      "relevant_doc_ids": [
        "editor"
      ],
      "forbidden_doc_ids": []
    }
  ]
}

Полезный документ и полезный фрагмент

Поле relevant_doc_ids задаёт ожидаемые документы. Такой уровень удобен в начале: в документе про адреса несколько разделов, которые могут помогать одному вопросу. Если поиск нашёл два его фрагмента, это ещё один найденный документ, а не две независимые удачи.

При более точной оценке потребуется разметка фрагментов и оснований. Запишите, какое утверждение должен подтверждать источник, а не только его название. Документ может упоминать URL в случайном примере и всё же не объяснять нужный перенос. Содержательный критерий отличает релевантность от совпадения слова.

Номера частей зависят от разбиения и текста. Поэтому эталон с идентификаторами фрагментов относится к определённой ревизии корпуса и версии splitter. Если после изменения абзацев прежний part-01 означает другое содержание, старую разметку нельзя молча использовать для нового опыта.

Как читать показатели поиска

Для вопроса с известным непустым набором полезных документов можно вычислить полноту: долю этих документов, которые попали в результат. Перед подсчётом сворачиваем найденные фрагменты до уникальных doc_id. Повтор одного документа не увеличивает полноту.

Точность на выбранной глубине показывает, какая доля найденных документов признана полезной. Но её знаменатель зависит от договора. Если измерять документы, нельзя в одном опыте считать все фрагменты, а в другом уникальные документы. Запишите единицу оценки и ограничение выдачи до сравнения вариантов.

Для случая без полезных источников полнота с пустым знаменателем не определена обычной формулой. Не подставляйте автоматически единицу и не включайте такое значение в среднее без объяснения. Здесь лучше отдельно оценивать корректный отказ, отсутствие неподтверждённого ответа и техническое состояние системы.

Порядок тоже имеет значение. Источник на первом месте легче заметить, чем тот же источник после нескольких отвлекающих результатов. Если выбираете показатель ранжирования, сохраните его определение и уровень разметки. Одно число не заменяет разбора конкретного вопроса, на котором порядок ухудшился.

Запрещённые источники — отдельный критерий

Поле forbidden_doc_ids описывает документы, которые нельзя показать заданной роли. Для reader таким документом является служебная заметка редактора. Её отсутствие не следует растворять в средней релевантности: нарушение доступа является самостоятельным дефектом, даже если остальные результаты полезны.

Проверять нужно весь путь: кандидаты после SQL, контекст генератора и ссылки в конечном ответе. Фильтр в интерфейсе недостаточен, если скрытый текст уже был передан модели. В лаборатории роль задаётся доверенной конфигурацией процесса; вопрос пользователя не должен менять её на editor.

Случай для редактора подтверждает другой договор: служебный документ может быть допустимым для этой роли. Это не тест настоящей пользовательской авторизации, которой в примере нет. При переходе к многопользовательскому сервису понадобится отдельная проверка сессий, полномочий и границ хранения данных.

Оценка генерации не равна оценке поиска

Хороший источник в контексте не гарантирует хороший ответ. Модель может пропустить условие, расширить вывод или сослаться на соседний фрагмент. Поэтому разбор генерации должен включать отдельные вопросы: подтверждается ли каждый значимый тезис, сохранены ли ограничения и достаточно ли материалов для ответа.

Статус generated_unverified означает, что форма и обозначения прошли проверки, но содержание ещё не подтверждено. Режим sources_only вообще не создаёт утверждений модели. Сравнивать их как два равнозначных «правильных ответа» нельзя; они дают читателю разные результаты.

Для неизвестного вопроса поиск ближайших векторов может всё равно вернуть документы. Это нормальное свойство выбора соседей и важная причина не считать непустую выдачу доказательством. Отказ модели при недостаточном контексте нужно наблюдать отдельно. Сам статус no_sources не является обязательным результатом любого вопроса вне корпуса.

Запись будущего наблюдения

В запись выполненного опыта должны войти вопрос, роль, ревизии корпуса, пространство эмбеддингов, модель ответа и правила контекста. Для HNSW дополнительно нужны параметры и фактический план запроса. Иначе изменение результата нельзя уверенно связать с одним выбранным механизмом.

Сохраняйте исходный результат вместе с разбором ошибки. Среднее значение может скрыть ухудшение важных вопросов о доступе или обновлениях. Полезный отчёт объясняет, какие случаи улучшились, какие ухудшились и что осталось неизвестным. Числа без условий воспроизведения имеют ограниченную ценность.

Наш массив runs остаётся пустым именно потому, что наблюдений пока нет. Теперь у проекта есть подготовленный предмет для оценки, а не рекламная цифра качества. В последнем уроке свяжем поиск с локальной веб-страницей и опишем, какие сведения нужны для передачи проекта следующему разработчику.

Исходники и документация

Оглавление серии · Все состояния проекта. Для этого урока откройте папку lesson-11.

pgvector, транзакции Psycopg, Ollama Embed, структурированные ответы.

Примеры подготовлены как исходники. Их выполнение, замеры, тесты и публикация при написании не проводились. Описанные результаты ожидаемые.