В предыдущих статьях (начало, продолжение) мы постепенно погружались в мир llamaIndex, рассмотрев основные концепции фреймворка и научившись реализовывать ключевые функции чат-бота для работы с базой документов в формате PDF. Сегодня мы переходим к следующему этапу нашего путешествия — изучению ретриверов в llamaIndex и стратегий их использования.
В мире, где данные становятся новой нефтью, эффективные инструменты для их обработки и анализа становятся неотъемлемой частью успешного проекта. Ретриверы в этом контексте выступают не просто как инструмент поиска, но и как средство структурирования больших данных, позволяя быстро и точно находить нужные фрагменты среди обширных и неструктурированных массивов информации.
Ретривер в контексте llamaIndex — это инструмент, задачей которого является поиск наиболее релевантного контекста на основе пользовательского запроса.
В llamaIndex представлены различные типы ретриверов, каждый из которых имеет свои особенности и предназначен для решения конкретных задач.
VectorIndexRetriever
VectorIndexRetriever
является основным ретривером для работы с векторными индексами. Он использует векторные представления для поиска наиболее релевантных документов в ответ на запрос пользователя.
Если в предыдущих экспериментах мы получали финальный ответ на вопрос, то теперь мы просто ранжируем ноды согласно запросу и выводим наиболее важные (по умолчанию 2), если есть необходимость выводить больше, то можно это указать явно:
Чтобы отобрать ноды выше определенного скора, можно выполнить постпроцессинг:
Добавляем собственный векторайзер
Когда мы получаем оценку релевантности, то мы смотрим на косинусную близость вектора запроса и вектора ноды. По умолчанию используется модель векторизации от OpenAI (поэтому нам и нужен ключ от API). Но что если мы не хотим платить деньги за получение эмбеддингов? Мы можем обучить собственную модель векторизации, которая будет лучше соответствовать нашим задачам.
Llamaindex позволяет добавлять собственные модели для получения эмбеддингов и генерации ответа. Для начала нужно будет поставить в окружение дополнительные пакеты:
Теперь создаем собственный класс для получения векторов:
В классе я использовал модель из коробки от sentence-transformers - distiluse-base-multilingual-cased-v2
Значение скоров существенно изменились, но тем не менее первая нода осталась той же (она же наиболее релевантная запросу).
Другие типы ретриверов
Llamaindex располагает множеством видов ретриверов, вот полный перечень:
Также есть возможность реализовать собственный тип. Кратко про некоторые типы:
SummaryIndexRetriever
предназначен для работы с индексами суммаризации, позволяя находить наиболее релевантные саммари для заданного запроса.TreeIndexRetriever
предназначен для работы с древовидными индексами, обеспечивая эффективный поиск по структурированным данным.KeywordTableRetriever
специализируется на работе с индексами, основанными на таблицах ключевых слов. Его задачей является извлечение и ранжирование документов на основе ключевых слов из запроса пользователя.
Я не буду разбирать каждый из видов, но для моего типа документов будет полезно рассмотреть BM25Retriever
BM25Retriever
Как нетрудно догадаться, этот ретривер использует алгоритм BM25 для семантического поиска. BM25 — это метод ранжирования документов в поисковых системах, который учитывает важность отдельных слов (токенов) из запроса относительно конкретных документов в корпусе. В отличие от методов, использующих векторные представления для документов, BM25 анализирует и оценивает каждый токен запроса независимо и вычисляет специальный «релевантный» скор для каждого токена относительно каждого документа в корпусе.
Попробуем использовать этот алгоритм для поиска нод:
Поиск работает, но нужная нам нода оказалась на втором месте. Еще можно задаться вопросом, почему наши скоры получились отрицательными. Тут нужно вспомнить, что BM25 является вариацией старого доброго TFIDF, и IDF для него считается как log((N – n + 0,5) / (n + 0,5))
, где N
— это количество документов в корпусе, а n
— количество документов, в которых встретился наш токен, т. е. если n > N/2
, то логарифм будет отрицательным, соответственно, и весь скор тоже.
Создаем композитный ретривер
Попробуем теперь соединить преимущества двух подходов в одном ретривере. Llamaindex позволяет создавать собственные типы на основе существующих.
Теперь правильная нода на первом месте. Хотя в нашем примере мы не видим существенного прироста качества, но такой композитный ретривер позволяет дополнительно увеличивать значимость отдельных токенов ноды, которые могут «потеряться» в общем векторе.
На этом обзор ретриверов можно завершать, как, впрочем, и всю серию статей о фреймворке. Я надеюсь, что данная статья поможет вам лучше понять, как эффективно использовать ретриверы в своих проектах на базе llamaIndex. Спасибо за внимание!
Пишу про AI и NLP в телеграм.
Комментарии