Запросите ваши документы с помощью Langchain и Deep Lake!

Get your documents with Langchain and Deep Lake!

Введение

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

Однако новый метод, называемый Retrieval Augmented Generation (RAG), кажется многообещающим. Используйте RAG для запроса LLM с использованием вашей собственной базы знаний. Это помогает моделям становиться лучше, добавляя дополнительную информацию из их источников данных. Это делает их более инновационными и помогает уменьшить количество ошибок, когда у них недостаточно информации.

РАГ работает путем расширения запросов с использованием собственных данных, что в конечном итоге обогащает знания этих больших языковых моделей, одновременно уменьшая число галлюцинаций.

Цели обучения

1. Понимание подхода RAG и его преимуществ

2. Распознавание проблем в вопросно-ответных системах

3. Различие между простым формированием и Retrieval Augmented Generation

4. Практическая реализация RAG на примере использования в индустрии, например, в системах вопросно-ответных систем на основе документов

По окончании этой статьи вы должны иметь хорошее представление о Retrieval Augmented Generation (RAG) и его применении для улучшения производительности LLM в вопросно-ответных системах на основе документов и информационном поиске.

Эта статья была опубликована в рамках блогосферы по науке о данных.

Начало работы

Что касается вопросно-ответных систем на основе документов, идеальным решением является предоставление модели конкретной информации, когда она задает вопрос. Однако определение, какая информация является релевантной, может быть сложной задачей и зависит от того, что от модели языка ожидается. Именно здесь важно понимание концепции RAG.

Давайте посмотрим, как работает процесс RAG:

Retrieval Augmented Generation

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

  1. Векторная база данных: В системе RAG ваши документы хранятся в специализированной векторной базе данных. Каждый документ проходит индексацию на основе семантического вектора, сгенерированного моделью вложения. Этот подход позволяет быстро извлекать документы, тесно связанные с данным вектором запроса. Каждому документу присваивается числовое представление (вектор), указывающее его семантическое значение.
  2. Генерация вектора запроса: Когда поступает запрос, та же модель вложения создает семантический вектор, представляющий запрос.
  3. Поиск на основе векторов: Затем модель использует поиск по векторам для определения документов в базе данных, которые имеют векторы, близкие к вектору запроса. Этот шаг является ключевым для нахождения наиболее релевантных документов.
  4. Генерация ответа: После получения соответствующих документов модель использует их с запросом для генерации ответа. Такая стратегия позволяет модели получать доступ к внешним данным в нужный момент и обогащать ее внутренние знания.

Иллюстрация

Ниже представлена иллюстрация, которая подводит итог всем вышеупомянутым шагам:

Согласно рисунку выше, есть 2 важных момента:

  1. В простом формировании мы никогда не узнаем исходную информацию.
  2. Простое формирование может привести к неправильной генерации информации, если модель устарела или ее знания ограничены перед тем, как задан запрос.

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

Таким образом, вместо того, чтобы заниматься хлопотами по повторному обучению пайплайна несколько раз для постоянно меняющейся информационной ситуации, вы можете добавить обновленную информацию в векторные хранилища/хранилища данных. Пользователь может прийти в следующий раз и задать похожие вопросы, на которые ответы изменились (возьмите, например, финансовые отчеты компании XYZ). Вы готовы.

Надеюсь, это освежит вам память о том, как работает RAG. Теперь перейдем к делу. Да, код.

Я знаю, что вы не пришли сюда для пустой болтовни. 👻

Перейдем к хорошей части!

1: Создание структуры проекта в VSCode

Откройте VSCode или ваш редактор кода по умолчанию и создайте каталог проекта следующим образом (внимательно следуйте структуре папок):

Не забудьте создать виртуальное окружение с Python ≥ 3.9 и установить зависимости из файла requirements.txt. (Не волнуйтесь, я поделюсь ссылкой на ресурсы на GitHub.)

2: Создание класса для операций поиска и встраивания

В файле controller.py вставьте следующий код и сохраните его.

from retriever.retrieval import Retriever

# Создаем класс Controller для управления встраиванием и поиском документов
class Controller:
    def __init__(self):
        self.retriever = None
        self.query = ""

    def embed_document(self, file):
        # Встраиваем документ, если предоставлен 'file'
        if file is not None:
            self.retriever = Retriever()
            # Создаем и добавляем встраивания для предоставленного файла документа
            self.retriever.create_and_add_embeddings(file.name)

    def retrieve(self, query):
        # Извлекаем текст на основе запроса пользователя
        texts = self.retriever.retrieve_text(query)
        return texts  

Это вспомогательный класс для создания объекта нашего Retriever. Он реализует две функции:

embed_document: генерирует встраивания документа

retrieve: извлекает текст, когда пользователь задает запрос

В будущем мы подробнее рассмотрим вспомогательные функции create_and_add_embeddings и retrieve_text в нашем Retriever!

3: Кодирование нашего пайплайна поиска!

В файле retrieval.py вставьте следующий код и сохраните его.

3.1: Импортируем необходимые библиотеки и модули

import os
from langchain import PromptTemplate
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores.deeplake import DeepLake
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import PyMuPDFLoader
from langchain.chat_models.openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.memory import ConversationBufferWindowMemory

from .utils import save

import config as cfg

3.2: Инициализируем класс Retriever

# Определяем класс Retriever
class Retriever:
    def __init__(self):
        self.text_retriever = None
        self.text_deeplake_schema = None
        self.embeddings = None
        self.memory = ConversationBufferWindowMemory(k=2, return_messages=True)csv

3.3: Давайте напишем код для создания и добавления встраиваний документов в Deep Lake

def create_and_add_embeddings(self, file):
    # Создаем каталог с именем "data", если он не существует
    os.makedirs("data", exist_ok=True)

    # Инициализируем встраивания с использованием OpenAIEmbeddings
    self.embeddings = OpenAIEmbeddings(
        openai_api_key=cfg.OPENAI_API_KEY,
        chunk_size=cfg.OPENAI_EMBEDDINGS_CHUNK_SIZE,
    )

    # Загружаем документы из предоставленного файла с помощью PyMuPDFLoader
    loader = PyMuPDFLoader(file)
    documents = loader.load()

    # Разбиваем текст на части с помощью CharacterTextSplitter
    text_splitter = CharacterTextSplitter(
        chunk_size=cfg.CHARACTER_SPLITTER_CHUNK_SIZE,
        chunk_overlap=0,
    )
    docs = text_splitter.split_documents(documents)

    # Создаем схему DeepLake для текстовых документов
    self.text_deeplake_schema = DeepLake(
        dataset_path=cfg.TEXT_VECTORSTORE_PATH,
        embedding_function=self.embeddings,
        overwrite=True,
    )

    # Добавляем разбитые документы в схему DeepLake
    self.text_deeplake_schema.add_documents(docs)

    # Создаем текстовый поисковик на основе схемы DeepLake с типом поиска "similarity"
    self.text_retriever = self.text_deeplake_schema.as_retriever(
        search_type="similarity"
    )

    # Настраиваем параметры поиска для текстового поисковика
    self.text_retriever.search_kwargs["distance_metric"] = "cos"
    self.text_retriever.search_kwargs["fetch_k"] = 15
    self.text_retriever.search_kwargs["maximal_marginal_relevance"] = True
    self.text_retriever.search_kwargs["k"] = 3

3.4: Теперь давайте напишем функцию, которая будет извлекать текст!

def retrieve_text(self, query):
    # Создаем схему DeepLake для текстовых документов в режиме только для чтения
    self.text_deeplake_schema = DeepLake(
        dataset_path=cfg.TEXT_VECTORSTORE_PATH,
        read_only=True,
        embedding_function=self.embeddings,
    )

    # Определяем шаблон подсказки для дать инструкцию модели
    prompt_template = """Вы - передовой искусственный интеллект, способный анализировать текст из 
    документов и предоставлять подробные ответы на запросы пользователей. Ваша цель - 
    предлагать исчерпывающие ответы, чтобы пользователи не имели необходимости возвращаться 
    к документу. Если у вас нет ответа, пожалуйста, признайте это, а не выдумывайте информацию.
    {context}
    Вопрос: {question} 
    Ответ:
    """

    # Создаем PromptTemplate с "context" и "question"
    PROMPT = PromptTemplate(
        template=prompt_template, input_variables=["context", "question"]
    )

    # Определяем тип цепочки
    chain_type_kwargs = {"prompt": PROMPT}

    # Инициализируем модель ChatOpenAI
    model = ChatOpenAI(
        model_name="gpt-3.5-turbo",
        openai_api_key=cfg.OPENAI_API_KEY,
    )

    # Создаем экземпляр RetrievalQA модели
    qa = RetrievalQA.from_chain_type(
        llm=model,
        chain_type="stuff",
        retriever=self.text_retriever,
        return_source_documents=False,
        verbose=False,
        chain_type_kwargs=chain_type_kwargs,
        memory=self.memory,
    )

    # Запрашиваем модель с вопросом пользователя
    response = qa({"query": query})

    # Возвращаем ответ от llm
    return response["result"]

4: Вспомогательная функция для запроса нашей конвейерной обработки и извлечения результата

Вставьте следующий код в ваш файл utils.py:

def save(query, qa):
    # Используйте функцию get_openai_callback
    with get_openai_callback() as cb:
        # Запрашиваем объект qa с вопросом пользователя
        response = qa({"query": query}, return_only_outputs=True)
        
        # Возвращаем ответ из llm
        return response["result"]

5: Конфигурационный файл для хранения ваших ключей… ничего особенного!

Вставьте следующий код в ваш файл config.py:

import os
OPENAI_API_KEY = os.getenv(OPENAI_API_KEY)
TEXT_VECTORSTORE_PATH = "data\deeplake_text_vectorstore"
CHARACTER_SPLITTER_CHUNK_SIZE = 75
OPENAI_EMBEDDINGS_CHUNK_SIZE = 16

Наконец, мы можем написать наше приложение Gradio для демонстрации!!

6: Приложение Gradio!

Вставьте следующий код в ваш файл app.py:

# Импортируем необходимые библиотеки
import os
from controller import Controller
import gradio as gr

# Отключаем параллелизм токенизаторов для лучшей производительности
os.environ["TOKENIZERS_PARALLELISM"] = "false"

# Инициализируем класс Controller
controller = Controller()

# Определяем функцию для обработки загруженного файла PDF
def process_pdf(file):
    if file is not None:
        controller.embed_document(file)
    return (
        gr.update(visible=True),
        gr.update(visible=True),
        gr.update(visible=True),
        gr.update(visible=True),
    )

# Определяем функцию для ответа на сообщения пользователя
def respond(message, history):
    botmessage = controller.retrieve(message)
    history.append((message, botmessage))
    return "", history

# Определяем функцию для очистки истории разговора
def clear_everything():
    return (None, None, None)

# Создаем интерфейс Gradio
with gr.Blocks(css=CSS, title="") as demo:
    # Отображаем заголовки и описания
    gr.Markdown("# AskPDF ", elem_id="app-title")
    gr.Markdown("## Загрузите PDF и задайте вопросы!", elem_id="select-a-file")
    gr.Markdown(
        "Перетащите интересный PDF и задайте вопросы о нем!",
        elem_id="select-a-file",
    )
    
    # Создаем раздел загрузки
    with gr.Row():
        with gr.Column(scale=3):
            upload = gr.File(label="Загрузить PDF", type="file")
            with gr.Row():
                clear_button = gr.Button("Очистить", variant="secondary")

    # Создаем интерфейс чат-бота
    with gr.Column(scale=6):
        chatbot = gr.Chatbot()
        with gr.Row().style(equal_height=True):
            with gr.Column(scale=8):
                question = gr.Textbox(
                    show_label=False,
                    placeholder="например, О чем документ?",
                    lines=1,
                    max_lines=1,
                ).style(container=False)
            with gr.Column(scale=1, min_width=60):
                submit_button = gr.Button(
                    "Спросить 🤖", variant="primary", elem_id="submit-button"
                )

    # Определяем кнопки
    upload.change(
        fn=process_pdf,
        inputs=[upload],
        outputs=[
            question,
            clear_button,
            submit_button,
            chatbot,
        ],
        api_name="upload",
    )
    question.submit(respond, [question, chatbot], [question, chatbot])
    submit_button.click(respond, [question, chatbot], [question, chatbot])
    clear_button.click(
        fn=clear_everything,
        inputs=[],
        outputs=[upload, question, chatbot],
        api_name="clear",
    )

# Запускаем интерфейс Gradio
if __name__ == "__main__":
    demo.launch(enable_queue=False, share=False)

Возьмите свою🧋, потому что пришло время узнать, как работает наша конвейерная линия!

Чтобы запустить приложение Gradio, откройте новый экземпляр терминала и введите следующую команду:

python app.py

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

Gradio запустит новый экземпляр вашего приложения на локальном сервере следующим образом:

Все, что вам нужно сделать, это нажать CTRL + щелкнуть на URL-адресе localhost (последняя строка), и ваше приложение откроется в браузере.

УРА!

Наше приложение Gradio здесь!

Давайте загрузим интересный PDF! Я воспользуюсь главой 1 книги о Гарри Поттере из этого репозитория Kaggle, содержащего книги о Гарри Поттере в формате .pdf для глав 1-7.

Люмос! Пусть свет будет с тобой🪄

Теперь, как только вы загрузите файл, поле для ввода запроса будет активировано:

Теперь давайте перейдем к самой ожидаемой части – викторине!

Вау! 😲

Мне нравится, насколько точными являются ответы!

Также обратите внимание, как память Langchain сохраняет состояние цепи, интегрируя контекст из предыдущих запусков.

Она помнит, что она здесь – наша любимая профессор МакГонагалл! ❤️‍🔥

Краткое демо того, как работает приложение!

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

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

2. В поддержке клиентов компании могут использовать чат-боты на основе RAG для решения запросов клиентов, жалоб и предоставления информации о продуктах и инструкциях, ЧАВО из частной базы данных продуктов и информации о заказах, предоставляя точные ответы и улучшая опыт клиента!

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

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

Возможности неограничены!

Заключение

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

Что получается в итоге? Более точные, контекстно подходящие ответы, обогащенные собственными данными. Надеемся, вам понравилось и вы что-то узнали по пути! Не стесняйтесь скачать полный код из моего репозитория на GitHub, чтобы попробовать его.

Основные выводы

  1. Введение в RAG: Retrieval Augmented Generation (RAG) – это многообещающая техника в крупных языковых моделях (LLM), которая улучшает их знания, добавляя дополнительную информацию из собственных источников данных, делая их умнее и уменьшая ошибки, когда им не хватает информации.
  2. Проблемы в Document QnA: Большие языковые модели достигли значительного прогресса в вопросно-ответных системах для документов (Document QnA), но иногда могут испытывать затруднения в определении, когда им не хватает информации, что приводит к ошибкам.
  3. RAG Pipeline: RAG Pipeline использует семантическую схожесть для определения соответствующей информации запроса. Он включает в себя векторную базу данных, генерацию вектора запроса, векторный поиск и генерацию ответа, что в конечном итоге обеспечивает более точные и контекстно подходящие ответы.
  4. Преимущества RAG: RAG позволяет моделям предоставлять доказательства для полученной информации, что уменьшает необходимость частого переобучения в быстро меняющихся сценариях информации.
  5. Практическая реализация: В статье представлен практический руководство по реализации RAG Pipeline, включая настройку структуры проекта, создание классов для поиска и встраивания, кодирование процесса поиска и создание приложения Gradio для взаимодействия в реальном времени.

Часто задаваемые вопросы

Показанный в этой статье контент не принадлежит Analytics Vidhya и используется по усмотрению автора.