Transcription
Совершенно верно. Загрузка PDF завершена. Теперь вы видите поле для ввода чата, и мы можем общаться с нашей моделью. Я собираюсь сначала задать очень простой вопрос, например, давайте спросим: «Какова численность населения Германии?» Какова численность населения Германии? Окей. Наш ответ говорит, что, согласно предоставленным данным, численность населения Германии составляет около 80 миллионов, что совершенно верно. Как видите, оценка модели составляет около 80, и это довольно хорошо. Я также задам немного более сложный вопрос. Я спрошу: «Какая страна имеет большее население: США или Египет?» И вопрос… давайте просто спросим: «Какая страна имеет большее население: США или Египет?» Давайте отправим. Это хорошо, потому что мы спрашиваем об одной из стран из таблицы и об одной из стран с графика, и мы хотим убедиться, что модель правильно обрабатывает как таблицу, так и изображение. Окей, модель говорит, что численность населения США составляет 332 миллиона, а Египта – 104 миллиона. Поэтому у США большее население, чем у Египта. И снова это правильно. Модель оценила численность населения Египта примерно как 104 миллиона, а США – как указано здесь. Она смогла корректно извлечь всю эту информацию и сравнить её, что удивительно.
Привет всем, Нимман здесь. Добро пожаловать на мой канал! Сегодня мы хотим использовать новую модель с открытым исходным кодом от Google, которая называется GMA Tre, для создания мультимодального RAG. Если вы пытались создавать RAG для PDF-файлов раньше, вы знаете, что большинство из них содержат не только текст. Многие из них содержат множество изображений, графиков, столбчатых диаграмм, круговых диаграмм, а также много таблиц. И эти изображения обычно содержат важную информацию. Но поскольку раньше можно было извлекать только текст, а затем передавать его в LLM через RAG, вы не могли обрабатывать изображения и задавать вопросы о них при использовании LLM для чата с этим PDF-файлом. Для создания мультимодальных RAG вам нужна модель, которая понимает как текст, так и изображения. И, к счастью, сейчас, благодаря Google, у нас есть очень хорошая модель. GMA Tre была недавно выпущена, и, как вы видите, она также доступна на Hugging Face. Она может понимать как текст, так и изображения. Если вы посмотрите, вы увидите, что она существует в четырёх разных версиях, и вы можете увидеть некоторую информацию о ней в части оценки. Вы видите, что это очень хорошая модель. Здесь есть некоторые бенчмарки. Если вы хотите установить её, я буду использовать версию 27B. Вам нужно перейти в командную строку и вызвать `huggingface-cli pull gma-tre 27b`. Затем вы нажмёте Enter, и модель будет загружена.
Теперь давайте перейдём к коду и попробуем создать RAG с этой новой моделью. Прежде всего, давайте посмотрим, какие зависимости нам нужны. Я буду использовать Streamlit для создания пользовательского интерфейса для чата с PDF-файлом, а затем я буду использовать LangChain для подключения к Hugging Face и в этом конкретном случае к модели GMA Tre, чтобы взаимодействовать с ней. Есть много зависимостей, касающихся LangChain, и одна из самых важных зависимостей, которую мы будем использовать сегодня, – это Unstructured. Unstructured – это одна из тех библиотек, которая помогает нам разбирать PDF-файлы и извлекать из них текст, изображения и таблицы. Чтобы установить эти зависимости, вам нужно снова перейти в командную строку и затем выполнить `pip install -r requirements.txt`. Обратите внимание, что я уже нахожусь в директории своего проекта. Затем я нажму Enter, и начнётся установка всех зависимостей.
Итак, теперь, когда мы установили все необходимые зависимости, давайте вернёмся к коду. Я уже создал файл Python с именем `multimodal_rag.py`, и я скопировал весь код из одного из своих предыдущих проектов, который был RAG для PDF-файлов с использованием Sentence Transformers. Я очень быстро объясню вам этот код, но если вы понятия не имеете, как работает RAG, или хотите более глубоких объяснений по этому коду, я бы посоветовал вам посмотреть это видео, которое я размещу сверху. В этом видео я подробно объяснил, как написал этот код. Итак, вкратце, пользователь будет загружать PDF-файл. Мы загрузим этот PDF-файл, проанализируем его с помощью PDF Plumber, который является ещё одной библиотекой помимо Unstructured, которая работает с PDF-файлами и помогает их разбирать. Затем я извлекаю из него только текст. Если есть какие-либо изображения или таблицы, я буду игнорировать их. Затем я разделяю этот текст, потому что иногда PDF-файлы очень большие, и наличие меньших фрагментов помогает улучшить точность при использовании LLM. Затем я индексирую их в хранилище векторов, то есть, используя некоторые эмбеддинги, я переношу этот текст в векторное пространство, а затем сохраняю этот вектор в хранилище векторов. Как вы видите, здесь определены некоторые эмбеддинги, а также хранилище векторов в памяти, которое я собираюсь использовать. Это часть индексирования. Затем у нас есть простой пользовательский интерфейс с использованием Streamlit, пользователь будет загружать PDF-файл, а затем после завершения всех этапов индексирования пошагово появится окно чата, и пользователь будет вводить вопросы. Мы передадим этот вопрос в хранилище векторов, и мы получим все похожие документы. Эти извлечённые документы будут играть роль контекста. Мы передадим их, а также вопрос пользователя в LLM. У нас есть очень длинный запрос, в котором говорится: «Вы – помощник для ответа на вопросы. Вам нужно использовать предоставленный контекст для ответа на вопрос», потому что LLM не знает, что находится в вашем PDF-файле. Вы загружаете эту информацию для него и передаёте её в запрос, а затем просите LLM ответить на ваш вопрос на основе предоставленного контекста. Это то, что мы называем RAG, и это то, что мы реализовали в этом видео. Ещё раз, если вы хотите лучше понять, как работает этот код, просто посмотрите это видео, прежде чем смотреть это. А теперь, чтобы добавить поддержку изображений и таблиц, нам нужно поработать над этой частью, где мы загружаем PDF-файл. Здесь мы просто использовали загрузчик PDF Plumber, который игнорировал все изображения и таблицы и сохранял только текст. Нам нужно это изменить. Давайте удалим эту часть, а затем я буду использовать `partition_pdf` внутри библиотеки Unstructured. С помощью этого метода вы передадите PDF-файл, а затем получите разделенные элементы, такие как фрагменты текста, изображения, таблицы. Все они будут разделены и переданы вам. Вы можете настроить его, вы можете передать, как вы видите, здесь много параметров, вы можете передать их со значениями, которые вы хотите, и настроить, как вы загружаете PDF-файл. Сначала я, конечно же, передам путь к файлу. У нас есть загруженный PDF-файл в этом каталоге. Я также собираюсь передать стратегию. Есть несколько стратегий разбиения. Я буду использовать `high_res`, которая похожа на высокое разрешение, которое позволяет извлекать также изображения и таблицы и использовать OCR. Другой параметр – `extract_images_block_types`. Этот и этот укажут Unstructured: «Пожалуйста, сохраните на диске эти категории». Я скажу, например, `image` и, да, может быть, `table`. Думаю, лучше будет так. Я не знаю, чувствителен ли он к регистру или нет. Поэтому, когда Unstructured разбирает ваш PDF-файл, он будет давать каждой части, каждому элементу категорию. И здесь я хочу сохранить их где-нибудь, когда это изображение или таблица. Я хочу сохранить изображения в этом каталоге, который я создал здесь, который называется `figures`. Следующим шагом будет `extract_image_output_dir`. Да, этот. Этот теперь должен быть этим каталогом, который у меня есть. Давайте создадим новый, который называется `figures`, и я назову его здесь `figures`, и я буду использовать его, чтобы передать его в Unstructured. Что всё это значит? Проще говоря, мы просто передаём PDF-файл в Unstructured. Мы просим сохранить также изображения и текст, и мы собираемся сохранить его где-нибудь на жёстком диске. И мы явно просим: «Сделай это в этом каталоге, пожалуйста». После всего этого он даст нам множество элементов. Я назову это `elements`. Нам это тоже не нужно. Давайте просто избавимся от этого. Теперь давайте сначала извлечём все текстовые элементы. Я скажу `text_elements`, а затем я сделаю здесь list comprehension: `for element in elements if element.category not in ['image', 'table']`. Как я говорил, каждая часть или каждый элемент имеет свою собственную категорию. Я собираюсь выбрать этот элемент, и он также имеет поле `text`. Что я сделал здесь, так это то, что если мой элемент не является изображением или таблицей, просто сохраните текст. Таким образом, я уже извлёк весь текст в PDF-файле. Следующим шагом будет получение текстового представления изображений и таблиц. Как это возможно? У нас есть наша модель GMA Tre. Я просто загружу все изображения и таблицы, которые сохранены здесь в этом каталоге `figures`, а затем передам их нашей модели и спрошу: «Опишите, что вы видите на этой картинке», а затем я сохраню это текстовое представление изображения и таблицы. Давайте продолжим и определим наши эмбеддинги и модели с нашей новой моделью. Я скажу `gma-tre-27b`. Дело в том, что для эмбеддингов я попробовал GMA Tre, и она выдала мне ошибку, что эта модель не поддерживает эмбеддинги. Вы можете использовать любые другие эмбеддинги, которые хотите. Вы можете использовать Sentence Transformers, вы можете использовать, например, llama-3.2. Какую бы модель эмбеддингов вы ни использовали, убедитесь, что вы загрузили её в Hugging Face раньше, как я показал вам, например, если я собираюсь использовать llama-3.2, я перейду в терминал и скажу `huggingface-cli pull llama-3.2`, и я загружу её, и я убежусь, что она существует на моей локальной машине. Давайте вернёмся. Да, пожалуйста, имейте в виду, что GMA Tre по некоторым причинам не поддерживает эмбеддинги. Остальное выглядит хорошо. Давайте создадим новый метод. Я назову его, не знаю, `extract_text`. Может быть, снова. Он будет получать путь к файлу, как и другой метод. Окей, чтобы передать изображения в модель, в данном случае модель Hugging Face, вы видите, что у нас уже есть модель здесь, да, GMA Tre. Вам нужно привязать это изображение. Я буду привязывать изображения, а затем путь к файлу. Думаю, это должен быть список, потому что их несколько. Давайте сделаем так. Это даст вам новую модель. Я скажу `model_with_image_context` что-нибудь такое. А затем вы можете просто сказать `invoke`. Я спрошу свою модель: «Расскажите, что вы видите на этой картинке». И всё. Я верну это. Таким образом, вы можете легко получить текстовое представление из вашего изображения. Таким образом, вы привязываете изображение, а затем с помощью этой модели, которая имеет этот контекст изображения, вы спрашиваете: «Расскажите, что вы видите на этом изображении». Вы можете использовать гораздо более сложные запросы, если это не даст вам правильного ответа. Я просто буду придерживаться этого для нашей демонстрации. Окей, теперь, когда у нас это есть, я загружу все файлы, которые находятся в каталоге `figures`, используя `os.listdir`. У нас есть каталог `figures` в качестве переменной. Давайте сделаем это. А теперь по одному я буду вызывать `extract_text`. Я скажу `extract_text`, и это будет путь к файлу, и это даст нам извлечённый текст, который я хочу. Я добавлю это также в `text_elements`, потому что он содержит весь текст. Вот так. Ой, извини, `extracted_text`. А теперь у нас есть все текстовые элементы, а также текстовое представление наших изображений. Мы можем просто вернуть огромный текст. Может быть, мы соединим… Я скажу, соединим с помощью нескольких новых строк эти текстовые элементы. Мы закончили с этой загрузкой PDF-файла. И если вы посмотрите сюда, вы загрузили PDF-файл, но здесь, поскольку мы больше не возвращаем документы LangChain, я просто назову это `text`, а затем я передам этот текст в `split_text` здесь. Это не должно быть `text` больше, поэтому я буду использовать `split_text` вместо `split_documents`. И да, здесь может быть `chunk_text`, и я передам это сюда, а затем `index_docs` может быть также `add_text` вместо `documents`. Кроме этого, всё выглядит хорошо. Думаю, мы готовы. Теперь, когда у нас есть представление наших изображений, а затем мы также добавляем их в хранилище векторов в качестве текстового представления, да, думаю, всё выглядит хорошо. Давайте продолжим и попробуем. Давайте перейдём в терминал. Нам нужно вызвать `streamlit run`, а затем наш файл Python. Давайте запустим его. Давайте перейдём в браузер. Как вы видите, мы можем загрузить наш PDF-файл. Для нашей демонстрации я создал простой PDF-файл на одной странице. Я покажу его вам сейчас. Это просто очень простой документ, который я создал сам о населении. Я просто говорю, что этот документ предоставляет некоторую информацию о населении стран. Этот абзац в основном просто это говорит, но суть в том, что вся важная информация находится в таблице или на графике. Наш RAG может быть полезен только в том случае, если он может правильно разобрать эту таблицу, а также правильно разобрать это изображение. Кроме того, нет много информации, которую он может мне дать, когда я общаюсь с ним. Есть некоторые страны в таблице с их населением. Есть некоторые страны, такие как Япония, Германия и Египет на графике, а также вы можете видеть, что, например, здесь на оси населения численность населения не такая уж точная. Да, вы можете видеть, что численность населения Японии составляет где-то около 125 миллионов, но не точно. Поэтому модель должна также каким-то образом оценить это, чтобы понять, какова численность населения трёх стран, которые находятся на этой столбчатой диаграмме. Давайте загрузим и зададим несколько вопросов об этом PDF-файле. Я просто перетащу его сюда. Вам нужно будет подождать, в зависимости от мощности вашей локальной машины, одну-две минуты, даже для этого PDF-файла на одной странице, я бы сказал, потому что он делает много вещей: обрабатывает изображения, извлекает текст, разбивает текст на части. Давайте подождём.
Совершенно верно. Загрузка PDF завершена. Теперь вы видите поле для ввода чата, и мы можем общаться с нашей моделью. Я собираюсь сначала задать очень простой вопрос, например, давайте спросим: «Какова численность населения Германии?» Какова численность населения Германии? Окей. Наш ответ говорит, что, согласно предоставленным данным, численность населения Германии составляет около 80 миллионов, что совершенно верно. Как видите, оценка модели составляет около 80, и это довольно хорошо. Я также задам немного более сложный вопрос. Я спрошу: «Какая страна имеет большее население: США или Египет?» И вопрос… давайте просто спросим: «Какая страна имеет большее население: США или Египет?» Давайте отправим. Это хорошо, потому что мы спрашиваем об одной из стран из таблицы и об одной из стран с графика, и мы хотим убедиться, что модель правильно обрабатывает как таблицу, так и изображение. Окей, модель говорит, что численность населения США составляет 332 миллиона, а Египта – 104 миллиона. Поэтому у США большее население, чем у Египта. И снова это правильно. Модель оценила численность населения Египта примерно как 104 миллиона, а США – как указано здесь. Она смогла корректно извлечь всю эту информацию и сравнить её, что удивительно.
Итак, вот и всё, ребята. Надеюсь, вам понравилось это видео. Пожалуйста, поставьте ему лайк, а также подпишитесь на мой канал, чтобы увидеть больше контента. Увидимся!