Гайд · TNWS AI

Как найти точный артикул через Haystack InMemoryBM25Retriever

Haystack 3.1Python#Haystack#RAG#Python
4 мин—

Локальный BM25-поиск по кодам и формулировкам ошибок, top_k, проверка ответов и ограничения поисковой схемы.

Применимость и задача

Поисковый запрос: «как искать точные артикулы Haystack InMemoryBM25Retriever». Материал сверён с официальной документацией Haystack 3.1 19 сентября 2026 года. Примеры рассчитаны на Python и пакет haystack-ai; для векторного примера дополнительно нужен пакет sentence-transformers-haystack. Демонстрационное InMemoryDocumentStore не рекомендовано разработчиком для production. Интерфейс командной строки ниже — Python API, а не названия пунктов графического меню.

InMemoryBM25Retriever работает с InMemoryDocumentStore, получает строку query и возвращает список документов. Официальная документация описывает BM25 как взвешенное пересечение слов и рекомендует его в задачах точного поиска имен, артикулов и характерных сообщений об ошибке. Не требуется embedding-модель.

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

  1. Составьте маленький корпус с различимыми артикулами и типовыми запросами.
  2. Запишите ожидаемые ID для точных запросов, включая ошибку набора символов.
  3. Запишите документы в InMemoryDocumentStore и инициализируйте ретривер с тем же объектом store.
  4. Вызовите run(query=...) и посмотрите первые документы вместе со score, не заменяя проверку ID субъективной оценкой.
  5. Отдельно проверьте неподходящий запрос и установите прикладной порог/отказ на основе размеченной выборки, если нужен отказ.

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

from haystack import Document
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever

store = InMemoryDocumentStore()
store.write_documents([
    Document(id="sku-41", content="Артикул AX-41. Синяя лампа."),
    Document(id="sku-42", content="Артикул BX-42. Красная лампа."),
])
retriever = InMemoryBM25Retriever(document_store=store)
result = retriever.run(query="AX-41", top_k=2)
print([(d.id, d.score) for d in result["documents"]])

Пример предназначен для контролируемого теста на своих данных. Установите зависимости в отдельном окружении и зафиксируйте версии; при использовании локальной embedding-модели отдельно проверьте её доступность и разрешённость для вашего проекта. Код был проверен на синтаксис Python, но его вызовы Haystack в данном материале не выдаются за выполненный runtime-тест.

Вход и ожидаемый результат

Вход: AX-41, корпус с товарами AX-41 и BX-42. Ожидается, что документ sku-41 находится среди результатов; порядок и величину score проверяйте при выбранной конфигурации токенизации. Вторая проверка — запрос «синяя лампа»: он должен вернуть соответствующую карточку, но это не подтверждает понимания синонимов.

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

Разбор ограничений и ошибок

BM25 полезен, когда пользователи знают точные коды или терминологию ошибок. Но наличие дефиса в артикуле означает, что токенизация может разделить код на части. Не обещайте буквальное сравнение AX-41 из одного только BM25: для обязательного равенства храните структурный артикул и используйте проверяемый фильтр или прямой поиск по полю. Оцените ложные совпадения на AX-42, BX-41, записи с пропущенным дефисом и смешении латиницы с кириллицей. Для корпуса с правами доступа фильтр по пользователю должен применяться до выдачи результата и проверяться на сервере. top_k ограничивает выдачу, но не превращает низкорелевантный ответ в полезный: проверьте пустую или слабую выдачу. Если в одной записи смешаны спецификация и маркетинг, слишком длинный документ приводит к шуму; разбивайте осмысленно и сохраняйте исходный ID. Локальное in-memory хранилище не заменяет постоянный store в приложении с несколькими процессами.

Проверочный сценарий на реальном корпусе

Сделайте отдельный набор запросов по артикулам, ошибкам и естественным перефразировкам. Измеряйте Recall@k для каждой группы: BM25 может хорошо искать код и хуже распознавать «лампа с холодным светом», если в документе сказано «синяя». Это аргумент в пользу второго поискового канала, а не повод скрыть ошибку в генераторе. При подсчёте правильно разграничивайте релевантность и безопасность: даже корректный документ другого клиента не должен попасть в контекст. Не делайте вывод о точности по единственному демонстрационному поиску, особенно на двух документах. Сохраните список ожидаемых идентификаторов и прогоняйте его после изменения токенизации, корпуса или ранжирования.

Критерии приёмки

  • sku-41 извлекается для AX-41.
  • Чужие или запрещённые документы не попадают в выдачу.
  • Неподходящий запрос не трактуется как подтверждённое совпадение.

Не принимайте демонстрационный вывод за статистику качества. Для рабочего приложения повторите эти проверки на обезличенном наборе документов, измерьте результат после изменения версии корпуса и запретите доступ к источникам вне полномочий пользователя. Корректный ответ HTTP вашего сервиса не означает корректный ответ RAG-системы; последнее устанавливается сопоставлением факта с разрешённым источником.

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

  • Не считать BM25 строго точным сравнением кода.
  • Не считать top_k порогом качества.
  • Не использовать in-memory store как долговременное хранилище.

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

FAQ

Нужны ли embeddings?

Нет, BM25 опирается на совпадение слов.

Где задать top_k?

В вызове run ретривера.

Что делать с синонимами?

Измерить недостающие ответы и при необходимости добавить другой способ поиска.

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

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

Нужны ли embeddings?

Нет, BM25 опирается на совпадение слов.

Где задать top_k?

В вызове run ретривера.

Что делать с синонимами?

Измерить недостающие ответы и при необходимости добавить другой способ поиска.

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

Комментарии

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