Гайд · TNWS AI

Как найти релевантный фрагмент через semantic_search в Sentence Transformers

5 мин—

Кодируем вопрос и документы, связываем corpus_id с текстом, проверяем top_k и строим отказ при отсутствии подходящего источника.

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

Поисковый запрос: «как найти нужный фрагмент в документах util.semantic_search». Ниже одна практическая задача для Python с библиотекой Sentence Transformers 6.1.0, опубликованной 18 сентября 2026 года, и checkpoint sentence-transformers/all-MiniLM-L6-v2. Пример на английских предложениях выбран потому, что поддержка русского выбранной демонстрационной моделью не должна подразумеваться автоматически. Для реального русского корпуса подберите подтверждённую карточкой языков модель и повторите оценку. Внешний поиск, генерация LLM и принятие бизнес-решения остаются отдельными этапами.

Фактическая основа: util.semantic_search(query_embeddings, corpus_embeddings, top_k) возвращает для каждого запроса список словарей с corpus_id и score. Из индекса corpus_id необходимо вернуться к исходному корпусу; функция не генерирует готовый ответ и не фильтрует разрешения доступа. Точный прогноз значений векторных оценок без запуска весов модели не обещается. Примеры кода ниже сверены с текущей официальной документацией и проверены на синтаксис Python; в этом окружении сами веса не загружались. При обновлении модели или зависимости сначала повторите контрольный пример.

Нумерованная инструкция

  1. Подготовьте маленький корпус с ID и тестовым вопросом, у которого есть один известный источник.
  2. Закодируйте документы и вопросы тем же checkpoint.
  3. Вызовите util.semantic_search с top_k меньше числа документов.
  4. Сопоставьте каждый corpus_id с тем текстом, который действительно был закодирован.
  5. Проверьте нерелевантный запрос и не допускайте ответ без проверенного источника.

Подготовьте изолированное окружение и установите зафиксированный пакет: pip install "sentence-transformers==6.1.0". Библиотека потребует подходящих зависимостей и свободной памяти под выбранные веса; установка пакета не скачивает заранее любую модель. Перед тестом напечатайте установленную версию и зафиксируйте имя checkpoint. Не отправляйте в примеры клиентские имена, закрытые документы или ключи доступа.

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

from sentence_transformers import SentenceTransformer, util

model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
docs = [("R7", "Returns are accepted for 14 days."),
        ("D9", "Delivery is available on weekdays."),
        ("P2", "Payment is possible by card.")]
queries = ["What is the return period?"]
hits = util.semantic_search(model.encode(queries),
                            model.encode([text for _, text in docs]), top_k=2)
for hit in hits[0]:
    print(docs[hit["corpus_id"]][0], hit["score"],
          docs[hit["corpus_id"]][1])

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

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

На входе R7 со сроком 14 дней, D9 о доставке, P2 об оплате и вопрос «What is the return period?». Ожидаемая проверка — верхний doc_id R7; API при этом вернёт до двух кандидатов, не одно готовое предложение про возврат. Если R7 не первый, сначала исследуйте качество выбора текста и модели.

Проверяйте структуру отдельно от смысла. Массив верного размера не означает хорошего поиска, а высокий score не удостоверяет факт в документе. Сохраните реальные выводы программы и сопоставьте их с заранее размеченными эталонными ID. При переносе на другой корпус обновите проверочные данные; простая замена входного предложения в коде не доказывает обобщения метода.

Разбор метода и ограничений

Удобно хранить корпус как пары (ID, текст). util.semantic_search сообщает числовую позицию corpus_id в том массиве embeddings, который передали функции. Если между кодированием и чтением результата отсортировать docs заново, метка источника станет ложной. В длительном сервисе фиксируйте snapshot корпуса или храните прямое соответствие позиции документу. Когда top_k=2, функция по определению выдаст два ближайших текста, даже если второй совершенно не подходит; модель не получает понятие «нет ответа» автоматически. Порог релевантности и отказ надо проверять отдельно на запросах без факта. Доступ к данным другого клиента также не реализован этой функцией: фильтруйте корпус на стороне приложения до передачи embeddings либо обеспечивайте правильную изоляцию на уровне хранилища.

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

Сформируйте контрольную таблицу из трёх вопросов: о возврате, о доставке и о гарантийном ремонте, которого нет. Для первых двух ожидается соответствующий ID в top-1, для третьего — отказ приложения от утверждения без основания. Даже если абстрактная модель выбрала P2 для гарантии, это не превращает P2 в источник такого ответа. Сохраните численные результаты и вручную отметьте ложные срабатывания. Отрицания, даты и артикулы проверяйте отдельным точным фильтром или reranker; смысловая близость может не различить номер договора. Если нужны тысячи и миллионы документов, этот пример с прямым поиском по матрице — лишь эталон; для быстрого продакшен-поиска выбирайте подходящий индекс и измеряйте recall относительно прямого перебора.

Критерии принятия

  • corpus_id отображает исходный, а не переставленный документ.
  • R7 присутствует в результатах контрольного вопроса.
  • Отсутствующая гарантия не превращается в придуманную цитату.

Если один пункт не проходит, настройка не готова для массового применения. При перезапуске сервиса повторно прогоните контрольный запрос и сверяйте ID, а не только наличие числовой оценки. Разделяйте ошибки получения embeddings, поиска кандидатов, фильтрации доступа и формирования финального ответа; хорошая метрика одного этапа не подтверждает работу остальных.

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

  • Не считать второй результат по top_k подтверждением факта.
  • Не перемешивать docs после вычисления corpus_embeddings.
  • Не забывать фильтр разрешений перед поиском.

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

FAQ

Возвращает ли функция текст ответа?

Нет, возвращает ID позиции и score.

Что значит corpus_id?

Индекс в переданном массиве документов.

Можно ли ждать отказа при отсутствии факта?

Нет, отказ реализуется отдельно.

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

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

Возвращает ли функция текст ответа?

Нет, возвращает ID позиции и score.

Что значит corpus_id?

Индекс в переданном массиве документов.

Можно ли ждать отказа при отсутствии факта?

Нет, отказ реализуется отдельно.

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

Комментарии

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