- BrainTools - https://www.braintools.ru -

DeepSeek-OCR + LLama4 + RAG = Революция в мире агентного OCR

DeepSeek-OCR + LLama4 + RAG=Революция в мире агентного OCR - 1

В выходные я просматривал Твиттер, чтобы узнать, что происходит в сфере ИИ. И снова DeepSeek привлек внимание [1] всего мира.

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

Любой, кто пользовался большой языковой моделью (LLM), сталкивался с такой проблемой:

Когда вы просите модель обобщить десятки тысяч слов из конспектов конференций или научных статей, она начинает терять память [2].

Это происходит потому, что квадратичная сложность длины последовательности по своей сути ограничивает GPT, Gemini и Claude – чем длиннее входные данные, тем больше вычислительной мощности требуется.

Люди устроены иначе. Мы можем взглянуть на заметку или диаграмму и мгновенно вспомнить целый отрывок.

Традиционно, чтобы ИИ понял длинные документы, весь документ должен быть преобразован в цифровой текст. Этот процесс потребляет большое количество токенов (единицы, используемые ИИ для обработки информации), что приводит к низкой вычислительной эффективности.

DeepSeek-OCR использует другой подход. Сначала он преобразует текст в изображения, а затем использует визуальные токены для сжатия этой информации. Представьте, что у вас есть статья на 10 000 слов – вместо того чтобы заставлять ИИ читать ее слово за словом, он может просто взглянуть на изображение, чтобы понять и восстановить исходный текст.

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

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

Я задам чат-боту вопрос: «Каковы основные выводы?» Если вы посмотрите, как чат-бот генерирует ответ, вы увидите, что агент извлекает текст с каждой страницы. Но если страница содержит менее 50 символов или не имеет встроенного текста, он преобразует эту страницу в изображение с высоким разрешением и отправляет его в DeepSeek-OCR на Replicate. Там используется подход «Контекстного оптического сжатия», при котором документ преобразуется в визуальные токены, а информация сжимается – по сути, позволяя ИИ взглянуть на изображение, а не читать слово за словом, что может превратить статью из 10 000 слов в гораздо более эффективный сжатый формат.

Как только весь текст извлечен, система разбивает его на фрагменты по 500 символов с перекрытием в 50 символов для сохранения контекста, преобразует каждый фрагмент в математические векторы с помощью эмбеддингов OpenAI и сохраняет их в векторной базе данных Chroma, которая сохраняется на диске для будущего использования.

Когда вы задаете вопрос, агент ищет в этих векторах 5 наиболее семантически похожих фрагментов документа, собирает их в контекстный промпт вместе с вашим вопросом и инструкциями по цитированию номеров страниц, а затем отправляет все это модели Llama 3.1 405B, работающей через потоковый API Replicate. Модель обрабатывает промпт и генерирует интеллектуальный ответ фрагмент за фрагментом в реальном времени.

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


Делегируйте часть рутинных задач вместе с BotHub! [3] Для доступа к сервису не требуется VPN и можно использовать российскую карту. По ссылке [4] вы можете получить 100 000 бесплатных токенов для первых задач и приступить к работе с нейросетями прямо сейчас!


Что делает DeepSeek-OCR уникальным?

DeepSeek-OCR — это сквозная модель OCR и парсинга документов, разработанная для достижения оптического контекстного сжатия.

DeepSeek-OCR + LLama4 + RAG=Революция в мире агентного OCR - 2

Эта модель состоит из двух основных компонентов: DeepEncoder, который сжимает входное изображение высокого разрешения в небольшое количество визуальных токенов, и декодера DeepSeek-3B-MoE (языковая модель Mixture-of-Experts), который восстанавливает исходный текст из последовательности визуальных токенов.

DeepEncoder (примерно 380 миллионов параметров) включает механизм оконного внимания на основе SAM для извлечения локальных признаков изображения. Вставив между ними двухслойную CNN с 16-кратным сжатием, он значительно сжимает изображение размером 1024×1024 пикселей с 4096 патчей до примерно 256 токенов.

Сторона декодера, которая получает эти визуальные токены, имеет в общей сложности 3 миллиарда параметров (примерно 570 миллионов эффективны во время инференса) и имеет структуру MoE, которая динамически использует 6 экспертов на шаг из 64 экспертов, обеспечивая легкую, но эффективную реконструкцию текста.

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

PaddleOCR-VL против DeepSeek-OCR:

Посмотрите видео PaddleOCR-VL:

Когда я тестировал обе модели OCR, я обнаружил кое-что интересное – PaddleOCR-VL, которая на самом деле меньше (0,9 млрд параметров), превосходила гораздо более крупные модели на 3 млрд параметров в реальных тестах.

Я давал ей сложные задачи: чтение вертикального текста в правильном направлении, понимание сложных математических формул и обработка документов с несколькими колонками – и PaddleOCR-VL справилась со всем этим блестяще, в то время как DeepSeek-OCR делала ошибки [5] в порядке чтения и формулах, несмотря на свои крутые функции сжатия.

Затем я обнаружил кое-что забавное в исследовательской статье DeepSeek-OCR – они на самом деле поблагодарили PaddleOCR и признали, что использовали ее для разметки своих обучающих данных. Это заставило меня понять, почему такие компании, как Baidu, DeepSeek и Shanghai AI Lab, выпускают модели OCR: они не делают инструменты OCR своей основной работой, они создают их для очистки огромных объемов данных для обучения [6] своих моделей ИИ, а мы получаем эти мощные инструменты OCR в качестве бесплатных бонусов.

Протестировав все, я пришел к выводу, что если вы создаете что-то для реальной работы и вам нужно читать печатный текст, формы, таблицы или документы на разных языках, PaddleOCR-VL – это то, что нужно. В то время как DeepSeek-OCR лучше подойдет, если вы исследователь, пытающийся сжать данные, чтобы сэкономить деньги на затратах на ИИ.

Текстовые токены против визуальных токенов

В традиционных LLM текст разбивается на дискретные текстовые токены (обычно слова или части слов). Каждому токену присваивается фиксированный ID в словаре, и он отображается в вектор через большую «таблицу поиска» (слой эмбеддинга). Хотя этот процесс эффективен, его сила ограничена словарем.

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

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

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

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

Давайте начнем кодить

Прежде чем мы погрузимся в наше приложение, мы создадим идеальную среду для работы кода. Для этого нам нужно установить необходимые библиотеки Python.

pip install requirements

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

import os  
import replicate  
from langchain_openai import OpenAIEmbeddings  
from langchain_core.prompts import ChatPromptTemplate  
from langchain_core.runnables import RunnablePassthrough  
from langchain_core.output_parsers import StrOutputParser  
from langchain_chroma import Chroma  
from langchain_text_splitters import RecursiveCharacterTextSplitter  
from langchain_core.documents import Document  
from langchain_core.language_models.llms import LLM  
from typing import List, Optional, Any  
import fitz  
from pathlib import Path  
from dotenv import load_dotenv  
  
load_dotenv()

Я разработал этот пользовательский класс Llama, унаследовав его от базового класса LLM LangChain и настроив его с идентификатором модели Llama 3.1 405B, лимитами токенов и настройками температуры.

Я реализовал обязательное свойство llmtype для возврата идентификатора, затем создал основной метод _call, который принимает промпт, упаковывает его с конфигурацией в словарь, отправляет в потоковый API Replicate и проходит через фрагменты ответа, чтобы объединить их в полный ответ.

class Llama(LLM):  
    model: str = "meta/meta-llama-3.1-405b-instruct"  
    max_tokens: int = 1024  
    temperature: float = 0.7  
  
    @property  
    def _llm_type(self) -> str:  
        return "replicate_llama"  
  
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:  
        input_data = {  
            "prompt": prompt,  
            "max_tokens": self.max_tokens,  
            "temperature": self.temperature  
        }  
  
        output = ""  
        for event in replicate.stream(self.model, input=input_data):  
            output += str(event)  
  
        return output

Я создал этот класс OCRPDFLoader для извлечения текста из PDF-файлов, сначала пытаясь извлечь текст, а при необходимости переключаясь на OCR. Я инициализировал его с путем к файлу, необязательным флагом OCR и порогом текста (по умолчанию 50 символов), чтобы определить достаточно ли текста на странице.

В методе load я открыл PDF с помощью PyMuPDF, прошел через каждую страницу для извлечения текста, затем проверил, было ли включено OCR или извлеченный текст был ниже порога – если да,

Я вызвал свой метод ocrpage, который я создал для преобразования страницы в PNG-изображение высокого разрешения, отправки его в API DeepSeek-OCR на Replicate, получения текста OCR обратно, очистки временного изображения и возврата извлеченного текста.

Наконец, я упаковал текст каждой страницы в объекты Document LangChain с метаданными (исходный файл, номер страницы, имя файла) и вернул их в виде списка, получив умный загрузчик, который автоматически обрабатывает как цифровые, так и отсканированные PDF-файлы.

class OCRPDFLoader:  
    def __init__(self, file_path: str, use_ocr: bool = False, text_threshold: int = 50):  
        self.file_path = file_path  
        self.use_ocr = use_ocr  
        self.text_threshold = text_threshold  
  
    def load(self) -> List[Document]:  
        doc = fitz.open(self.file_path)  
        documents = []  
  
        for page_num in range(len(doc)):  
            page = doc[page_num]  
            text = page.get_text()  
  
            if self.use_ocr or len(text.strip()) < self.text_threshold:  
                print(f"OCR: page {page_num + 1}")  
                text = self._ocr_page(page, page_num)  
  
            if text.strip():  
                documents.append(Document(  
                    page_content=text.strip(),  
                    metadata={  
                        'source': self.file_path,  
                        'page': page_num + 1,  
                        'filename': Path(self.file_path).name  
                    }  
                ))  
  
        doc.close()  
        return documents  
  
    def _ocr_page(self, page, page_num, temp_dir='./temp_ocr'):  
        os.makedirs(temp_dir, exist_ok=True)  
  
        pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))  
        img_path = f"{temp_dir}/page_{page_num}.png"  
        pix.save(img_path)  
  
        with open(img_path, "rb") as image_file:  
            input_data = {  
                "image": image_file,  
                "task_type": "Free OCR"  
            }  
  
            output = replicate.run(  
                "lucataco/deepseek-ocr:cb3b474fbfc56b1664c8c7841550bccecbe7b74c30e45ce938ffca1180b4dff5",  
                input=input_data  
            )  
  
        os.remove(img_path)  
        return output

Далее я создал класс LangChainPDFRAG – это главный оркестратор, который связывает все вместе в полноценную систему RAG. Я инициализировал его, настроив свою пользовательскую модель Llama для генерации ответов, эмбеддинги OpenAI для преобразования текста в векторы, разделитель текста, который разбивает документы на фрагменты по 500 символов с перекрытием в 50 символов для сохранения контекста между фрагментами, и векторную базу данных Chroma, которую я настроил на сохранение на диске, чтобы она могла перезагружать существующие данные между сеансами.

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

Наконец, я реализовал метод query, где я настроил ретривер для поиска 5 наиболее релевантных фрагментов документа, создал цепочку LangChain, которая принимает вопрос пользователя, извлекает релевантный контекст, форматирует его в шаблон промпта с просьбой к LLM цитировать номера страниц, передает все моей модели Llama для генерации и возвращает как сгенерированный ответ, так и исходные документы с их номерами страниц – по сути, создавая полноценную систему вопросов и ответов, которая может интеллектуально искать по PDF-файлам и предоставлять точные ответы со ссылками.

class LangChainPDFRAG:  
    def __init__(self,  
                 llm_model='meta/meta-llama-3.1-405b-instruct',  
                 embedding_model='text-embedding-3-small',  
                 persist_directory='./chroma_db'):  
  
        self.llm = Llama(model=llm_model)  
        self.embeddings = OpenAIEmbeddings(model=embedding_model)  
        self.persist_directory = persist_directory  
        self.vectorstore = None  
  
        self.text_splitter = RecursiveCharacterTextSplitter(  
            chunk_size=500,  
            chunk_overlap=50,  
            separators=["nn", "n", ". ", " ", ""]  
        )  
  
        if os.path.exists(persist_directory):  
            self.vectorstore = Chroma(  
                persist_directory=persist_directory,  
                embedding_function=self.embeddings  
            )  
  
    def add_pdf(self, pdf_path: str, use_ocr: bool = False):  
        loader = OCRPDFLoader(pdf_path, use_ocr=use_ocr)  
        documents = loader.load()  
        splits = self.text_splitter.split_documents(documents)  
  
        if self.vectorstore is None:  
            self.vectorstore = Chroma.from_documents(  
                documents=splits,  
                embedding=self.embeddings,  
                persist_directory=self.persist_directory  
            )  
        else:  
            self.vectorstore.add_documents(splits)  
  
        print(f"Added {len(splits)} chunks from {Path(pdf_path).name}")  
        return len(splits)  
  
    def query(self, question: str):  
        if self.vectorstore is None:  
            raise ValueError("No documents.")  
  
        retriever = self.vectorstore.as_retriever(search_kwargs={"k": 5})  
  
        def format_docs(docs):  
            return "nn".join([doc.page_content for doc in docs])  
  
        prompt = ChatPromptTemplate.from_template(  
            "You are a helpful assistant. Answer based on the context provided. Cite page numbers when relevant.nn"  
            "Context:n{context}nn"  
            "Question: {question}nn"  
            "Answer:"  
        )  
  
        chain = (  
            {"context": retriever | format_docs, "question": RunnablePassthrough()}  
            | prompt  
            | self.llm  
            | StrOutputParser()  
        )  
  
        docs = retriever.invoke(question)  
        answer = chain.invoke(question)  
  
        return {  
            'answer': answer,  
            'sources': [  
                {  
                    'filename': doc.metadata.get('filename'),  
                    'page': doc.metadata.get('page'),  
                    'content': doc.page_content[:200]  
                }  
                for doc in docs  
            ]  
        }

Я создал экземпляр системы RAG с Llama 3.1 405B, загрузил PDF в векторную базу данных и запросил его с вопросом. Агент извлек релевантные фрагменты документа, сгенерировал ответ и вернул как ответ, так и ссылки на источники.

if __name__ == "__main__":  
    # Using Llama 3.1 405B from Replicate  
    rag = LangChainPDFRAG(llm_model='meta/meta-llama-3.1-405b-instruct')  
  
    rag.add_pdf('TSLA-Q2-2025-Update.pdf', use_ocr=False)  
  
    result = rag.query('What are the main findings?')  
  
    print("=== Answer ===")  
    print(result['answer'])  
  
    print("n=== Sources ===")  
    for source in result['sources']:  
        print(f"- {source['filename']}, Page {source['page']}")

Заключение:

DeepSeek-OCR – это не просто очередной апгрейд для распознавания текста. Это настоящий прорыв, открывающий новую главу в истории ИИ. Предложенная идея визуально-текстового сжатия – смелое решение одной из главных проблем современных нейросетей: как переварить огромные объемы информации и не подавиться.


А теперь ваша очередь

Как вы думаете, что это означает для будущего?

Настоящий прорыв, который поможет нам создавать ИИ, способных мгновенно понимать любые книги, архивы и научные работы?

Или это просто очередной умный трюк, который останется нишевым инструментом для исследователей, сжимающих данные?

Делитесь своим мнением в комментариях!

Автор: cognitronn

Источник [8]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/22508

URLs in this post:

[1] внимание: http://www.braintools.ru/article/7595

[2] память: http://www.braintools.ru/article/4140

[3] BotHub!: https://bothub.chat/?utm_source=contentmarketing&utm_medium=habr&utm_campaign=news&utm_content=DEEPSEEK-OCR%20+%20LLAMA4%20+%20RAG%20=%20REVOLUTION%20IN%20THE%20WORLD%20OF%20AGENT-BASED%20OCR

[4] По ссылке: https://bothub.chat/?invitedBy=m_aGCkuyTgqllHCK0dUc7

[5] ошибки: http://www.braintools.ru/article/4192

[6] обучения: http://www.braintools.ru/article/5125

[7] восприятие: http://www.braintools.ru/article/7534

[8] Источник: https://habr.com/ru/companies/bothub/articles/971108/?utm_source=habrahabr&utm_medium=rss&utm_campaign=971108

www.BrainTools.ru

Rambler's Top100