Расширенная генерация с помощью поиска (RAG) от теории к реализации LangChain

От Теории к Реализации Расширенная Генерация с Помощью Поиска (RAG) в LangChain

От теории оригинального научной статьи к её реализации на Python с использованием OpenAI, Weaviate и LangChain

Workflow с увеличенным извлечением для генерации

После понимания, что вы можете усилить большие модели языка (БМЯ) с помощью ваших оригинальных данных, возникло обсуждение о том, как наиболее эффективно преодолеть разрыв между общими знаниями БМЯ и вашими оригинальными данными. Возникло много дебатов о том, что лучше подходит для этого: тонкая настройка модели или увеличенное извлечение для генерации (RAG) (спойлер: это оба варианта).

В этой статье в первую очередь рассматривается концепция RAG и охватывается его теория. Затем демонстрируется, как можно реализовать простую RAG платформу, используя LangChain для оркестрации, модели языка OpenAI и векторную базу данных Weaviate.

Что такое увеличенное извлечение для генерации

Увеличенное извлечение для генерации (RAG) – это концепция предоставления БМЯ дополнительной информации из внешнего источника знаний. Это позволяет им генерировать более точные и контекстуальные ответы, снижая проявление галлюцинаций.

Проблема

Современные БМЯ обучаются на больших объемах данных, чтобы достичь широкого спектра общих знаний, которые хранятся в весах нейронной сети. Однако, если потребуется, чтобы БМЯ сгенерировала завершение, требующее знаний, которые не были включены в обучающие данные, такие как более новая, оригинальная или предметно-областная информация, это может привести к фактическим неточностям (галлюцинациям), как показано на следующем скриншоте:

Ответ ChatGPT на вопрос

Поэтому важно преодолеть разрыв между общими знаниями БМЯ и любым дополнительным контекстом, чтобы помочь БМЯ генерировать более точные и контекстуальные завершения, снижая при этом галлюцинации.

Решение

Традиционно, нейронные сети адаптируются к предметно-областным или оригинальным данным путем тонкой настройки модели. Хотя эта техника эффективна, она также требует больших вычислительных ресурсов, стоит дорого и требует технической экспертизы, что делает ее менее гибкой для адаптации к изменяющейся информации.

В 2020 году Льюис и др. предложили более гибкую технику, называемую увеличенным извлечением для генерации (RAG) в статье Увеличенное извлечение для генерации в задачах ОИЯ со знаниями [1]. В этой работе исследователи объединили генеративную модель с модулем извлекателя, чтобы предоставить дополнительную информацию из внешнего источника знаний, которую можно легко обновлять.

Простыми словами, RAG – это для БМЯ то же самое, что и экзамен с возможностью использования учебника для людей. На таком экзамене студентам разрешено использовать справочные материалы, такие как учебники или записи, чтобы найти соответствующую информацию для ответа на вопрос. Идея за экзаменом с возможностью использования учебника заключается в том, что тест сосредоточен на навыках рассуждения студентов, а не на их способности запомнить конкретную информацию.

Аналогично, фактические знания отделены от способности рассуждения БМЯ и хранятся во внешнем источнике знаний, который можно легко получить и обновить:

  • Параметрические знания: Выученные в процессе обучения, которые неявно хранятся в весах нейронной сети.
  • Непараметрические знания: Хранятся во внешнем источнике знаний, таком как векторная база данных.

(Кстати, я не придумал эту гениальную аналогию. Насколько мне известно, эта аналогия была впервые упомянута JJ во время соревнования Kaggle — LLM Science Exam.)

Методика обработки RAG представлена ниже:

Методика улучшенного поиска и генерации
  1. Поиск: Ответ на запрос пользователя получается путем извлечения соответствующего контекста из внешнего источника знаний. Для этого запрос пользователя встраивается моделью векторного представления в тот же векторный пространственный контекст, что и дополнительный контекст в векторной базе данных. Это позволяет осуществлять поиск похожих векторов, и возвращаются k ближайших объектов данных из векторной базы данных.
  2. Дополнение: Запрос пользователя и полученный дополнительный контекст помещаются в шаблон.
  3. Генерация: В конечном итоге, полученный улучшенный запрос передается модели LLM.

Реализация методики улучшенного поиска и генерации с использованием LangChain

В данном разделе реализуется конвейер RAG на Python с использованием модели LLM от OpenAI в сочетании с векторной базой данных Weaviate и моделью векторного представления от OpenAI. Для координации используется LangChain.

Если вы не знакомы с LangChain или Weaviate, вам может быть интересно прочитать следующие две статьи:

Начало работы с LangChain: руководство для начинающих по созданию приложений на базе LLM

Урок по LangChain: о том, как создавать любые приложения на базе больших языковых моделей на Python

towardsdatascience.com

Начало работы с Weaviate: руководство для начинающих по поиску с использованием векторных баз данных

Как использовать векторные базы данных для семантического поиска, ответа на вопросы и генерации поисковых запросов на Python с помощью OpenAI и других

towardsdatascience.com

Подготовка

В качестве подготовительного шага необходимо подготовить векторную базу данных в качестве внешнего источника знаний, содержащего всю дополнительную информацию. Эта векторная база данных заполняется следующим образом:

  1. Соберите и загрузите ваши данные
  2. Разделите документы на части
  3. Получите векторные представления и сохраните их

Первый шаг – собрать и загрузить данные – Для этого примера вы будете использовать Выступление президента Байдена о состоянии Союза в 2022 году в качестве дополнительного контекста. Исходный текстовый документ доступен в репозитории GitHub LangChain. Чтобы загрузить данные, вы можете использовать один из встроенных загрузчиков документов LangChain – DocumentLoader. Document – это словарь с текстом и метаданными. Чтобы загрузить текст, вы будете использовать TextLoader LangChain.

import requestsfrom langchain.document_loaders import TextLoaderurl = "https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt"res = requests.get(url)with open("state_of_the_union.txt", "w") as f:    f.write(res.text)loader = TextLoader('./state_of_the_union.txt')documents = loader.load()

Далее, разбейте ваши документы на части – Поскольку Document в своем исходном состоянии слишком длинный, чтобы поместиться в окно контекста LLM, вам нужно разбить его на более мелкие части. LangChain поставляется с множеством встроенных разделителей текста для этой цели. В этом простом примере вы можете использовать CharacterTextSplitter с размером чанка около 500 и перекрытием чанков около 50, чтобы сохранить непрерывность текста между чанками.

from langchain.text_splitter import CharacterTextSplittertext_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)chunks = text_splitter.split_documents(documents)

Наконец, встраивайте и сохраняйте чанки – Чтобы обеспечить семантический поиск по чанкам текста, вам нужно сгенерировать векторные вложения для каждого чанка, а затем сохранить их вместе со своими вложениями. Для генерации векторных вложений вы можете использовать модель вложений OpenAI, а для их сохранения – базу данных векторных изображений Weaviate. Вызовом метода .from_documents() векторная база данных автоматически заполняется чанками.

from langchain.embeddings import OpenAIEmbeddingsfrom langchain.vectorstores import Weaviateimport weaviatefrom weaviate.embedded import EmbeddedOptionsclient = weaviate.Client(  embedded_options = EmbeddedOptions())vectorstore = Weaviate.from_documents(    client = client,        documents = chunks,    embedding = OpenAIEmbeddings(),    by_text = False)

Шаг 1: Получение

Как только векторная база данных заполнена, вы можете определить ее как компонент получателя, который извлекает дополнительный контекст на основе семантической схожести между пользовательским запросом и вложенными чанками.

retriever = vectorstore.as_retriever()

Шаг 2: Дополнение

Затем, чтобы дополнить промпт дополнительным контекстом, вам нужно подготовить шаблон промпта. Промпт можно легко настроить из шаблона, как показано ниже.

from langchain.prompts import ChatPromptTemplatetemplate = """Вы являетесь помощником для выполнения задач по вопросно-ответной системе. Используйте следующие части полученного контекста, чтобы ответить на вопрос. Если вы не знаете ответа, просто скажите, что вы не знаете. Используйте не более трех предложений и держите ответ кратким.Вопрос: {question} Контекст: {context} Ответ:"""prompt = ChatPromptTemplate.from_template(template)print(prompt)

Шаг 3: Генерация

Наконец, вы можете создать цепочку для пайплайна RAG, состоящую из получателя, шаблона промпта и LLM. После определения цепочки RAG вы можете ее вызвать.

from langchain.chat_models import ChatOpenAIfrom langchain.schema.runnable import RunnablePassthroughfrom langchain.schema.output_parser import StrOutputParserllm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)rag_chain = (    {"context": retriever,  "question": RunnablePassthrough()}     | prompt     | llm    | StrOutputParser() )query = "Что президент сказал о Юстиции Брейере"rag_chain.invoke(query)

"Президент поблагодарил Юстицию Брейера за его службу и отметил его приверженность служению стране. Президент также упомянул, что он назначил судью Кетанджи Браун Джексон в качестве преемника, чтобы продолжить наследие превосходства Юстиции Брейера."

Вы можете увидеть результирующий конвейер RAG для данного примера ниже:

Рабочий процесс повышения эффективности поиска с генерацией

Резюме

В этой статье рассматривается концепция RAG, которая была представлена в статье Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks [1] 2020 года. После изложения некоторой теории, включая мотивацию и решение проблемы, в этой статье осуществляется ее реализация на языке Python. В статье описывается конвейер RAG, использующий LLM от OpenAI в сочетании с векторной базой данных Weaviate и моделью вложения OpenAI. При организации процесса использовалась LangChain.

Нравится эта история?

Подпишитесь бесплатно, чтобы получать уведомления о публикации новых историй.

Получайте уведомления по электронной почте, когда Леони Монигатти что-то публикует.

Получайте уведомления по электронной почте, когда Леони Монигатти что-то публикует. При регистрации вы создадите учетную запись VoAGI, если ее еще нет…

VoAGI.com

Найдите меня на LinkedIn, Twitter и Kaggle!

Отказ от ответственности

Я работаю в Weaviate в качестве разработчика-пропагандиста на момент написания данной статьи. Кроме этой статьи, я также добавил тот же пример в тетради Weaviate в документации LangChain. Также вы можете начать с использования шаблона rag-weaviate в LangChain.

Ссылки

Литература

[1] Lewis, P. и др. (2020). Retrieval-augmented generation for knowledge-intensive NLP tasks. Advances in Neural Information Processing Systems, 33, 9459–9474.

Изображения

Если не указано иное, все изображения созданы автором.