Генерация дополненного извлечения (RAG): от теории к реализации LangChain
От теории из оригинальной академической статьи до ее реализации на Python с OpenAI, Weaviate и LangChain
С тех пор как мы осознали, что мы можем перегрузить крупные языковые модели (LLM) нашими собственными данными, активно велись дискуссии по поводу того, как наиболее эффективно преодолеть разрыв между общими знаниями LLM и нашими собственными данными. Было много споров о том, что больше всего подходит для этого: тонкая настройка или генерация дополненного извлечения (RAG) (внимание, спойлер: и то, и другое).
Что такое генерация дополненного извлечения
Генерация дополненного извлечения (RAG) — это концепция предоставления LLM дополнительной информации из внешнего источника знаний. Это позволяет им генерировать более точные и контекстные ответы, одновременно уменьшая галлюцинации.
Проблема
Современные LLM обучаются на больших объемах данных для достижения широкого спектра общих знаний, хранящихся в весах нейронной сети (параметрическая память). Но побуждение LLM генерировать выполнение, требующее знаний, которые не были включены в его обучающие данные, такие как более новая или специфичная для домена информация, может привести к фактическим неточностям (галлюцинациям), как показано на следующем скриншоте:
Таким образом, важно преодолеть разрыв между общими знаниями LLM и любым дополнительным контекстом, чтобы помочь LLM генерировать более точные и контекстные выполнения, одновременно уменьшая галлюцинации.
Решение
Традиционно нейронные сети адаптируются к специфичной для домена или частной информации путем точной настройки модели. Этот метод эффективен, но он требует больших вычислительных ресурсов, затрат и технических знаний, что делает его менее гибким для адаптации к меняющейся информации.
В 2020 году в статье «Генерация дополненного извлечения для задач обработки естественного языка с интенсивным использованием знаний» (Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks)» Льюис и др. предложили более гибкий метод под названием «Генерация дополненного извлечения» (RAG). В этой статье исследователи объединили генеративную модель с модулем извлечения, чтобы предоставить дополнительную информацию из внешнего источника знаний, которую можно было бы легче обновлять.
Проще говоря, RAG для LLM — то же самое, что открытый экзамен для людей. На открытом экзамене студентам разрешается приносить справочные материалы, такие как учебники или заметки, которые они могут использовать для поиска релевантной информации для ответа на вопрос. Идея открытого экзамена заключается в том, что тест фокусируется на навыках рассуждения студентов, а не на их способности запоминать конкретную информацию.
Аналогичным образом, фактические знания отделены от возможностей рассуждения LLM и хранятся во внешнем источнике знаний, к которому можно легко получить доступ и обновить:
- Параметрические знания: полученные во время обучения, которые неявно хранятся в весах нейронной сети.
- Непараметрические знания: сохраненные во внешнем источнике знаний, например, в векторной базе данных.
(Кстати, это гениальное сравнение придумал не я. Насколько мне известно, это сравнение впервые упомянул JJ во время конкурса Kaggle — LLM Science Exam).
Ниже изображен рабочий процесс стандартного RAG:
- Извлечь: пользовательский запрос используется для извлечения соответствующего контекста из внешнего источника знаний. Для этого пользовательский запрос встраивается с моделью встраивания в то же векторное пространство, что и дополнительный контекст в векторной базе данных. Это позволяет выполнить поиск по сходству и вернуть первые k ближайших объектов данных из векторной базы данных.
- Дополнить: пользовательский запрос и извлеченный дополнительный контекст вставляются в шаблон подсказки.
- Генерировать: и, наконец, подсказка с дополненным извлечением передается в LLM.
Реализация генерации дополненного извлечения с использованием LangChain
Предварительные условия
Убедитесь, что вы установили необходимые пакеты Python:
- langchain для оркестровки
- openai для модели встраивания и LLM
- weaviate-client для векторной базы данных
Кроме того, определите соответствующие переменные среды в файле .env в корневом каталоге. Чтобы получить ключ API OpenAI, вам нужна учетная запись OpenAI, где вам нужно создать новый секретный ключ в разделе ключей API.
Затем выполните следующую команду, чтобы загрузить необходимые переменные среды.
Подготовка
На этом этапе вам необходимо подготовить векторную базу данных в качестве внешнего источника знаний, содержащего всю дополнительную информацию. Эта векторная база данных заполняется следующими шагами:
- Собрать и загрузить данные
- Разбить документы на части
- Встроить и сохранить фрагменты
Первый шаг — собрать и загрузить данные. В этом примере в качестве дополнительного контекста вы будете использовать Послание президента Байдена о положении страны от 2022 года. Необработанный текстовый документ доступен в репозитории LangChain на GitHub. Для загрузки данных вы можете использовать один из множества встроенных DocumentLoaders на LangChain. Document представляет собой словарь с текстом и метаданными. Для загрузки текста вы будете использовать TextLoader на LangChain.
Далее разбить документы на фрагменты — поскольку Document в своем исходном состоянии слишком длинный, чтобы поместиться в контекстное окно LLM, вам нужно разбить его на более мелкие части. Для этой цели в LangChain имеется множество встроенных разделителей текста. Для этого простого примера вы можете использовать CharacterTextSplitter с chunk_size около 500 и chunk_overlap 50, чтобы сохранить непрерывность текста между фрагментами.
И, наконец, встроить и сохранить фрагменты — чтобы включить семантический поиск по текстовым фрагментам, вам нужно сгенерировать векторные встраивания для каждого фрагмента, а затем сохранить их вместе с их встраиваниями. Для генерации векторных встраиваний вы можете использовать модель встраивания OpenAI, а для их хранения вы можете использовать векторную базу данных Weaviate. При вызове .from_documents() векторная база данных автоматически заполняется фрагментами.
Шаг 1: Извлечение
После заполнения векторной базы данных вы можете определить ее как компонент извлекателя, который извлекает дополнительный контекст на основе семантического сходства между запросом пользователя и встроенными фрагментами.
Шаг 2: Дополнение
Далее, чтобы дополнить подсказку дополнительным контекстом, вам необходимо подготовить шаблон подсказки. Подсказку можно легко настроить из шаблона подсказки, как показано ниже.
Шаг 3: Генерация
И, наконец, вы можете построить цепочку для конвейера RAG, объединив вместе извлекатель, шаблон подсказки и LLM. Как только цепочка RAG определена, вы можете вызвать ее.
Ниже изображен полученный конвейер RAG для этого конкретного примера.
Резюме
Мы рассмотрели концепцию RAG, которая была представлена в статье «Генерация дополненного извлечения для задач обработки естественного языка с интенсивным использованием знаний» (Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks)» от 2020 года. Сначала мы рассмотрели теорию, лежащую в основе этой концепции, включая мотивацию и решение проблем, затем - ее реализацию в Python. В этой статье мы реализовали конвейер RAG с использованием LLM от OpenAI в сочетании с векторной базой данных Weaviate и моделью встраивания OpenAI. Для оркестровки мы использовали LangChain.
Понравилась статья? Еще больше информации на тему данных, AI, ML, LLM вы можете найти в моем Telegram канале.
- Как подготовиться к сбору данных, чтобы не провалиться в процессе?
- Какие данные нужны для обучения LLM?
- В чем специфика работы с GenAI проектами? И какие бенчмарки сравнения LLM есть на российском рынке?
Обо всем этом читайте в “Роман с данными”