RAG-системы: как я научился на своих ошибках и что действительно работает
В мире RAG (Retrieval-Augmented Generation) существует множество статей, которые обещают простое решение: подключите векторную базу, используйте эмбеддер, добавьте реранкер и гибридный поиск с BM25, и ваша система будет готова к продакшену. Однако реальность зачастую оказывается более сложной. Я прошёл этот путь на практике и обнаружил, что многие из этих "правильных" улучшений на моих данных не только не сработали, но даже ухудшили результаты. BM25 снизил метрику, реранкер также не оправдал ожиданий. Единственное, что действительно помогло, — это несколько дней работы с данными и тщательные замеры.
Правильный ответ есть, но находится не в топ-3 (проблема ранжирования).
Правильного ответа нет в топ-50 (проблема полноты поиска).
Без этого разделения улучшения RAG превращаются в гадание. Мои данные показали, что hit@3 составляет 74%, а hit@50 — 86%, что указывает на необходимость улучшения эмбеддера.
Сначала создайте честный эталон, затем работайте над улучшениями.
Разделяйте recall и ранжирование, чтобы понимать, что именно нужно улучшать.
Порог зависит от роли продукта, а не от данных.
"Best practice" — это гипотеза, которую нужно проверять на своих данных.
Данные важнее модели: качество корпуса и разметка эталона имеют решающее значение.
Эта статья — первая из цикла, в которой я расскажу о технической стороне системы: детекторе просьб о помощи, типизаторе и архитектуре.
Откуда взялась задача
Всё началось с того, что мой знакомый разработал бота для модерации групп, который использует локальную ИИ-модель для решения задач, вместо традиционных текстовых фильтров. Я, имея 20-летний опыт в веб-разработке, решил переключиться на тему ИИ и агентов, осознав, что моя профессия может стать невостребованной. Изучая RAG-системы, я решил создать что-то практическое, что решает реальные проблемы. Собрав публичные экспорты 11 крупных чатов криптобирж — около 3.9 миллионов сообщений за полгода — я прогнал их через классификатор, чтобы выявить сообщения от пользователей с проблемами: замороженные средства, зависшие выводы и так далее. Выяснилось, что лишь 19-42% пользователей получают публичные ответы от администраторов, что создает необходимость в автоматизации.Построение RAG-системы
Идея заключалась в том, чтобы создать модуль, который будет подсказывать пользователям ссылки на прошлые ответы администраторов, если их вопрос уже обсуждался. Это классический подход RAG: база вопросов-ответов, векторный поиск и выдача ответов. Однако на практике день кода обернулся двумя неделями работы над пониманием, как система функционирует.Честный эталон и метрики
Первым шагом стало создание eval-линейки — набора вопросов с размеченными правильными ответами. Я выбрал метрику hit@3, чтобы определить, попадает ли правильный ответ в топ-3. Однако вскоре я столкнулся с проблемой: моя разметка занижала метрики. Я размечал только один ответ, что было логично для обучающего датасета, но для замеров это оказалось ошибкой. Бот мог находить правильные ответы, но из-за неправильной разметки метрика показывала промахи. Я также столкнулся с проблемой, что классические метрики precision@k и recall@k не учитывают, когда система должна молчать. Для моего бота это было критично, так как молчание было желаемым состоянием. Я разработал свои метрики: silence, noise и none_ok, чтобы получить полное представление о работе системы.Диагностика и анализ
После того как я исправил эталон, я добавил диагностику, которая должна быть в любом RAG-проекте. Я анализировал, на какой позиции стоит правильный ответ в топ-50. Это позволило разделить две проблемы:Повороты в процессе
Порог отсечения
Первое, что я протестировал, — это порог отсечения по близости. Оказалось, что 26 процентных пунктов hit@3 терялись из-за неправильно выставленного порога. Это было неожиданным открытием: порог нельзя выбирать объективно, он зависит от роли бота в продукте. Если бот заменяет поддержку, лучше промолчать, чем ошибиться. Если он подстраховывает, то ошибки могут вызвать недовольство.BM25 и реранкер
Следующим шагом был тест гибридного поиска с BM25. Ожидалось, что он улучшит результаты, но на практике метрика упала на 19 пунктов. Причина заключалась в том, что BM25 искал точные токены, которых не было в корпусе. Это подтверждает, что стандартные решения должны проверяться на своих данных, а не приниматься на веру. Реранкер также не оправдал ожиданий. Его использование привело к снижению hit@3 с 74% до 64%. Это произошло потому, что реранкер, работая с уже хорошим базовым поиском, нарушил порядок правильных ответов.Итоги и выводы
В итоге, единственное, что действительно сработало, — это калибровка порога. Чистый векторный поиск с правильно выставленным порогом показал лучший результат. Все остальные улучшения, включая BM25 и реранкер, оказались неэффективными.Что стоит запомнить
Источник:
Хабр: Машинное обучение