Почему vector-only недостаточно
Semantic search силён на перефразировании, но может проиграть точным кодам, фамилиям, версиям и редким терминам. BM25 хорошо ловит совпадения слов, но хуже понимает смысл. Hybrid search создаёт кандидатов обоими путями.
Как устроен pipeline
Один запрос отправляется в lexical и vector retriever. Каждый возвращает ранжированный список. Fusion объединяет списки, после чего применяются permissions, дедупликация и при необходимости reranking.
RRF как безопасный baseline
Reciprocal Rank Fusion суммирует вклад позиции документа в каждом списке. Он не требует сопоставимости сырых score и устойчивее простого сложения BM25 с cosine. Начинайте с равных весов, если нет обучающего набора.
Когда нужны веса
Dense может выигрывать на естественных вопросах, lexical - на идентификаторах. Weighted RRF имеет смысл только после измерений на train/validation split. Один глобальный вес может скрыть провал отдельного сегмента.
Candidate pool и latency
Слишком маленький pool ограничивает recall и не даёт reranker исправить результат. Слишком большой увеличивает сеть и время второго этапа. Sweep по top-k выполняйте вместе с end-to-end latency и answer quality.
Фильтры и права
Tenant, ACL, язык, дата и тип документа должны применяться согласованно к обоим retrievers. Нельзя объединять запрещённые кандидаты, а затем надеяться удалить их prompt-инструкцией.
Отладка результатов
Логируйте отдельные lexical и vector ranks, fusion score и причины фильтрации. Для плохого ответа проверяйте: был ли нужный chunk найден, потерян при fusion, отрезан top-k или проигнорирован генератором.
Оценка и rollout
Используйте запросы с точными кодами, синонимами, опечатками и отрицательными примерами. Сравните BM25-only, vector-only и hybrid. Выпускайте через shadow и храните версии embedding, index и fusion policy.