Гайд · TNWS AI

Как измерить hit rate и MRR поиска в LlamaIndex RetrieverEvaluator

LlamaIndex FrameworkPython#LlamaIndex#Python#RAG
4 мин—

Размеченный вопрос, expected_ids и оценка позиции релевантного узла до тестирования ответов генератора.

Задача и применимость

Поисковый запрос: «как измерить hit rate MRR LlamaIndex RetrieverEvaluator». Факты и синтаксис сверены с официальной документацией LlamaIndex Framework для Python 19 сентября 2026 года. Пример предназначен для актуального Python-пакета llama-index и указанных в коде интеграций; доступность конкретной модели и конфигурация её провайдера зависят от среды запуска. Если код обращается к embeddings или LLM, ключ задаётся через серверное окружение и здесь не приводится. Точный релиз локально не установлен, поэтому перед рабочим запуском фиксируйте номер установленной версии и повторите тест на ней.

RetrieverEvaluator.from_metric_names принимает имена метрик, например mrr и hit_rate, и объект retriever. Метод evaluate получает строку query и expected_ids релевантных node IDs. Руководство также показывает aevaluate_dataset для набора запросов и ручное составление датасета. Эти метрики оценивают retrieval, не фактическую точность LLM.

Нумерованный порядок работы

  1. Сохраните ID узла, содержащего ответ, до запуска оценки; ID документа и node ID могут отличаться.
  2. Постройте retriever с явным similarity_top_k и составьте тестовый вопрос.
  3. Создайте RetrieverEvaluator с mrr и hit_rate и передайте expected_ids.
  4. Повторите на вопросе с другим релевантным узлом и на отрицательном случае.
  5. Разберите позиции релевантных узлов и только после этого меняйте chunking или embeddings.

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

from llama_index.core import Document, VectorStoreIndex
from llama_index.core.evaluation import RetrieverEvaluator

index = VectorStoreIndex.from_documents([
    Document(text="Возврат по R7: 14 дней.", id_="R7"),
    Document(text="Доставка по D9: по будням.", id_="D9"),
])
retriever = index.as_retriever(similarity_top_k=2)
question = "Сколько дней на возврат по R7?"
seen = retriever.retrieve(question)
# ID эталонного узла размечают ВРУЧНУЮ по содержимому, не выбирают top-1.
expected_ids = [n.node.node_id for n in seen if "14 дней" in n.node.get_content()]
evaluator = RetrieverEvaluator.from_metric_names(
    ["mrr", "hit_rate"], retriever=retriever)
print(evaluator.evaluate(query=question, expected_ids=expected_ids))

Код ниже в статье предназначен для тестовых источников без персональных сведений. Вызовы SDK не выполнялись в данном окружении с реальной моделью; синтаксис Python проверен отдельно. Не переносите вывод демонстрационного эксперимента на любой корпус и любого провайдера без повторной проверки.

Пример входа и ожидаемого результата

Вход: вопрос про R7 и два узла, один про возврат, второй про доставку. Ожидается попадание вручную размеченного узла в выдачу; hit rate отмечает наличие, MRR учитывает его позицию. В коде фильтр по содержимому демонстрирует форму ID, но для честной оценки эталоны надо разметить до просмотра выдачи, иначе метрика будет завышена.

Сохраните входные файлы, идентификаторы документов и ожидаемое утверждение в отдельном проверочном наборе. При неуспехе выделяйте слой ошибки: чтение источника, преобразование в nodes, получение embedding, поиск, синтез ответа или UI. Правильная форма ответа ещё не гарантирует правильного происхождения сведений.

Диагностика и границы решения

Главная ловушка evaluation — утечка ответа при создании эталона. Если брать expected_ids прямо из первых результатов retriever, он гарантированно проверяет самого себя и может получить высокий score при плохой релевантности. В рабочем наборе человек читает исходные узлы независимо от поиска и связывает вопрос с корректным ID заранее. MRR отражает позицию первого релевантного результата и полезен, когда генератор видит мало документов; hit rate говорит о факте попадания в top_k. Увеличение k почти всегда повышает шанс попадания, но может ухудшить итоговый ответ из-за шумного контекста. Фиксируйте версию корпуса, модель embeddings и способ разбиения для каждого отчёта. Если два узла вместе нужны для ответа, дополнительные метрики полноты или ручная проверка необходимы.

Дополнительный проверочный сценарий

Сформируйте группы вопросов: точные коды, перефразировки, отрицания, вопросы об исключениях и запросы без ответа. По каждой группе сохраните список node IDs и проверьте доступность источника для данного пользователя. Разница между 0.8 и 0.9 на пяти вопросах не является серьёзным доказательством улучшения; нужен отложенный размеченный набор. При смене chunk_size старые node IDs могут поменяться, поэтому переотметьте соответствие узлов, не переписывая сами ожидаемые факты задним числом. После измерения retrieval оцените отдельно, правильно ли генератор воспользовался найденным фрагментом; метрики поиска не могут гарантировать правдивость ответа. Не показывайте в пользовательском интерфейсе сырые внутренние ID без привязки к документу.

Критерии проверки

  • Эталон размечен независимо от результата.
  • Релевантный node ID попадает в top_k.
  • Позиция и наличие интерпретированы раздельно.

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

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

  • Не формировать expected_ids из результатов тестируемого retriever.
  • Не считать hit_rate проверкой ответа LLM.
  • Не сравнивать разные версии корпуса как одинаковый эксперимент.

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

FAQ

Что передают в expected_ids?

ID релевантных узлов.

Что измеряет MRR?

Позицию первого релевантного узла.

Зачем отложенный набор?

Чтобы настройка не переобучилась на тех же вопросах.

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

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

Что передают в expected_ids?

ID релевантных узлов.

Что измеряет MRR?

Позицию первого релевантного узла.

Зачем отложенный набор?

Чтобы настройка не переобучилась на тех же вопросах.

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

Комментарии

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