AI-инжиниринг
Document Processing: PDF, DOCX, HTML, таблицы - извлекаем данные для RAG
Цели урока
- Понять почему парсинг документов - самый трудоёмкий этап RAG pipeline
- Освоить парсинг PDF трёх категорий: текстовый, сложный layout, сканированный
- Научиться извлекать контент из HTML (Readability) и DOCX (mammoth)
- Обрабатывать таблицы для embedding - превращать строки в самодостаточный текст
- Применять multimodal подход (GPT-4o Vision) для документов с графиками и сложными таблицами
90% данных в компании - неструктурированный текст: PDF контракты, Slack переписка, email. LLM умеет их читать. Но сначала нужно достать текст, и это не просто - PDF без слоя текста это просто картинка. Stripe парсит финансовые отчёты из тысяч банков. Harvey AI обрабатывает миллионы судебных документов. У всех одна проблема - первый шаг RAG pipeline.
- Stripe использует document processing для автоматического анализа финансовых отчётов клиентов - PDF разной структуры из тысяч банков мира
- Harvey AI (юридический AI) парсит миллионы судебных документов - PDF со сложными таблицами, сносками, перекрёстными ссылками
- Notion AI обрабатывает импортированные файлы пользователей - DOCX, PDF, HTML из десятков источников
- Google NotebookLM принимает PDF и строит RAG поверх - multimodal LLM парсинг для документов с графиками и формулами
От OCR и PDF к GenAI-native парсингу документов
**Tesseract OCR** начинался как закрытая разработка в Hewlett-Packard в 1985-1994 годах, был открыт HP и UNLV в 2005 году, а в 2006-м его развитие подхватил Google (под руководством Ray Smith) - движок до сих пор остаётся одним из самых популярных open-source OCR. **PDF** создан в Adobe: из предложения сооснователя John Warnock по проекту Camelot (1991) формат вырос в релиз в июне 1993 года; оставался проприетарным до открытого стандарта ISO 32000 в 2008-м. Контейнерная природа PDF (текстовые объекты с координатами либо просто растровое изображение) - именно поэтому его парсинг для RAG до сих пор сложен. **LlamaParse** (LlamaIndex, запуск в марте 2024) обозначил переход к GenAI-native парсингу: вместо чтения только текстового слоя он использует LLM и Vision-модели для таблиц, графиков и нестандартных layout. Вместе с open-source инструментами Unstructured и Docling это превратило парсинг документов в отдельный слой RAG-стека.
Предварительные знания
Почему парсинг документов - самая сложная часть RAG
90% данных в компании - неструктурированный текст: PDF контракты, Slack переписка, email. LLM умеет их читать. Но сначала нужно достать текст, и это не просто - PDF без слоя текста это просто картинка.
RAG pipeline выглядит элегантно на схеме: документ → chunking → embedding → vector DB → LLM. На практике 80% времени первых RAG-проектов уходит именно на первый шаг. PDF, который выглядит как простой текст, внутри может быть набором координат символов без логической структуры. DOCX хранит текст в XML с десятками вложенных тегов. HTML-страница - это 20% контента и 80% шаблонного мусора.
Качество парсинга напрямую определяет качество всего downstream pipeline. Плохой парсинг - плохие embeddings - нерелевантный поиск - галлюцинации LLM. Garbage in, garbage out - буквально.
- **PDF** - самый проблемный формат. Нет стандартной структуры: текст может быть координатами символов, изображением (скан), таблицей без разметки
- **DOCX** - XML внутри ZIP. Структура сохраняется, но стили, таблицы, вложенные объекты требуют обработки
- **HTML** - нужно отделить контент от шаблона (навигация, сайдбар, footer)
- **Таблицы** - в PDF таблица это набор линий и текста без связи ячейка-значение
- **Сканы и изображения** - текст внутри картинки, нужен Tesseract OCR или Vision-модель
| Формат | Сложность парсинга | Типичные проблемы |
|---|---|---|
| Plain text (.txt, .md) | Минимальная | Кодировка, line endings |
| HTML | Средняя | Шаблонный мусор, JavaScript-rendered контент |
| DOCX | Средняя | Вложенные стили, таблицы, headers/footers |
| PDF (текстовый) | Высокая | Порядок символов, колонки, headers/footers на каждой странице |
| PDF (сканированный) | Очень высокая | OCR ошибки, наклон, качество скана |
| Таблицы (XLSX, CSV) | Средняя | Merged cells, multi-header, пустые строки |
**Ловушка новичка:** взять первый попавшийся PDF-парсер, получить «какой-то текст» и считать задачу решённой. Без проверки качества на реальных документах RAG pipeline будет выдавать бессмысленные ответы. Всегда визуально проверяй результат парсинга перед построением индекса.
Почему парсинг документов - критический этап RAG pipeline?
Парсинг PDF: от простого к сложному
PDF - самый распространённый формат деловых документов и самый жестокий для парсинга. Три категории PDF, три разных подхода. Перепутать - потерять данные.
Категория 1: Текстовый PDF (digital-born)
Создан в Word, Google Docs или через программный генератор. Текст хранится в виде символов с координатами. Парсится хорошо стандартными инструментами. PyMuPDF (fitz) и pdfplumber - два самых надёжных варианта: первый быстрее, второй лучше с таблицами.
Категория 2: PDF со сложной структурой
Документы с колонками, таблицами, формулами, встроенными изображениями. Простой pdf-parse извлечёт текст, но **порядок будет нарушен** - колонки перемешаются, таблицы потеряют структуру. Именно здесь Harvey AI, парсящий миллионы судебных документов с footnotes и cross-references, вынужден выстраивать multi-step pipeline.
Категория 3: Сканированный PDF (image-based)
Текст - это изображение. `pdf-parse` вернёт пустую строку или мусор. Нужен **Tesseract OCR** (бесплатно, локально) или **Vision-модель** (дороже, точнее). Tesseract - OpenSource движок Google, обученный на 100+ языках. GPT-4o Vision понимает не просто символы, а структуру документа.
**Стратегия выбора парсера PDF:** сначала попробовать pdf-parse - если текст корректный, достаточно. Если нет (пустой результат, мусор, перемешанные колонки) - Apache Tika. Если PDF - скан - Tesseract OCR для массовой обработки или GPT-4o Vision для важных документов с таблицами.
Для сканированного PDF-документа с таблицами лучший подход извлечения текста:
Парсинг HTML и DOCX: извлечение полезного контента
HTML: отделяем контент от шаблона
Типичная страница документации или блога - 20% полезного контента и 80% шаблона: навигация, сайдбар, footer, реклама, cookie-баннеры, скрипты аналитики. Наивный подход (strip all tags) сольёт весь этот мусор в один поток. Нужен **content extraction** - алгоритм, определяющий, где на странице основной текст.
DOCX: XML внутри ZIP
DOCX - это ZIP-архив с XML-файлами внутри. Основной текст находится в `word/document.xml`. Библиотека `mammoth` конвертирует DOCX в чистый HTML или текст, сохраняя структуру заголовков, списков и таблиц. Notion AI именно так обрабатывает импортированные файлы пользователей - DOCX, PDF, HTML из десятков источников.
**Для RAG рекомендуется** извлекать HTML (а не plain text) из DOCX, а затем конвертировать в Markdown. Markdown сохраняет структуру (заголовки, списки, таблицы), что помогает LLM лучше понимать контекст при ответе на вопрос.
Для извлечения основного контента из HTML-страницы блога лучший подход:
Таблицы, metadata и нормализация текста
Обработка таблиц
Таблицы - особая боль для RAG. Embedding строки таблицы без контекста заголовков бессмысленен. Значение "42" без контекста - числовой шум. "Revenue Q3 2025: 42 миллиона долларов" - уже смысл. Два подхода: Markdown (сохраняет структуру) и денормализация строк (каждая строка самодостаточна для embedding).
Извлечение и использование metadata
Metadata документа (автор, дата, язык, категория) не менее важна, чем содержание. Она используется для **metadata filtering** в vector database - сужения поиска до релевантного подмножества. Запрос "контракты подписанные в 2024" без metadata filtering - это full-scan по всему индексу.
Нормализация и очистка текста
**Не чистить агрессивно.** Цифры, аббревиатуры, специальные символы могут быть критически важны для контекста. Нормализация должна убирать артефакты парсинга (дублирующиеся заголовки, мусорные символы), а не «чистить» контент по собственному усмотрению.
При обработке таблиц для RAG-системы лучший подход:
Multimodal подход: GPT-4o Vision для сложных документов
Традиционный парсинг (pdf-parse, Tika, Tesseract) работает с текстовым слоем документа. Но реальные корпоративные документы - это **графики, диаграммы, формулы, сложные таблицы с merged cells**, которые текстовые парсеры либо ломают, либо пропускают. Именно здесь multimodal LLM меняет правила игры: страница превращается в изображение и отправляется в Vision-модель, которая понимает не просто символы - а смысл.
Стоимость и скорость multimodal подхода:
| Параметр | Текстовый парсинг | Vision-парсинг |
|---|---|---|
| Скорость | 100-500 страниц/сек | 0.3-1 страница/сек |
| Стоимость | ~бесплатно | 0.01-0.03 долл. за страницу |
| Таблицы | Часто ломается структура | Сохраняет связи ячеек |
| Графики/диаграммы | Не извлекает | Описывает данные и тренды |
| Формулы | Часто мусор | LaTeX-нотация |
| Сканы | Нужен отдельный OCR | Работает из коробки |
Гибридная стратегия
**LlamaParse** (от LlamaIndex) и **Docling** (IBM, 2024) - managed и open-source инструменты, комбинирующие текстовый парсинг и Vision-модели автоматически. LlamaParse: бесплатный tier 1000 страниц/день. Docling: локальный запуск, MIT лицензия. Хорошие точки старта без написания собственного pipeline.
**Правило 80/20 для document processing:** 80% документов в типичном корпусе - простые текстовые PDF и DOCX, которые парсятся стандартными инструментами. Не нужно строить Vision pipeline для всего. Сначала - простой парсер, потом - Vision fallback для оставшихся 20% сложных случаев.
Гибридная стратегия парсинга PDF означает:
PDF.parse() вернёт текст из любого PDF
Сканированный PDF - это изображение. pdf-parse вернёт пустую строку или мусор. Нужен Tesseract OCR или Vision-модель
PDF - контейнерный формат, он не хранит «текст». Он хранит либо текстовые объекты с координатами (digital-born), либо растровое изображение (scan). pdf-parse умеет только в первое. Если документ пришёл из сканера или факса - текстового слоя нет вообще. Это обнаруживается просто: `avgCharsPerPage < 100` после парсинга = почти наверняка скан.
Ключевые выводы
- Парсинг документов определяет качество всего RAG pipeline - garbage in → garbage out
- PDF бывает трёх типов: текстовый (pdf-parse/PyMuPDF), сложный layout (Tika/pdfplumber), скан (Tesseract OCR/Vision)
- HTML парсится через @mozilla/readability (автоматическое определение основного контента)
- DOCX парсится через mammoth (XML → HTML/текст с сохранением структуры)
- Таблицы нужно денормализовать - каждая строка с заголовками и контекстом для качественного embedding
- Гибридная стратегия: текстовый парсинг для 80% документов, Vision (GPT-4o / Docling / LlamaParse) для оставшихся 20%
- avgCharsPerPage < 100 после pdf-parse = скан, нужен OCR
Вопросы для размышления
- Какие типы документов есть в типичном корпоративном хранилище? Какая доля из них, скорее всего, сканированные?
- Почему chunking strategy зависит от качества парсинга? Что произойдёт с chunk boundaries если текст перемешан из-за плохого парсинга?
- LlamaParse и Docling абстрагируют сложность парсинга. Когда стоит строить собственный pipeline вместо managed сервиса?
Что дальше
Документы распарсены и очищены. Следующий шаг - разбить текст на чанки оптимального размера, сгенерировать embeddings и собрать полный RAG pipeline, который отвечает на вопросы по документам.
- RAG Fundamentals — Собираем document processing + embeddings + vector DB + LLM в работающий pipeline
- Chunking Strategies — Как разбивать распарсенный текст на чанки для embedding - размер, overlap, стратегии
Связанные уроки
- aie-09-embeddings — Извлечённый текст дальше становится эмбеддингами
- aie-12-rag-fundamentals — Парсинг это стадия загрузки в RAG-пайплайне
- aie-14-chunking-strategies — Распарсенный текст нужно нарезать на чанки до эмбеддинга
- aie-25-multimodal — OCR и таблицы затрагивают мультимодальное понимание документов
- ml-38-image-classification — Определение макета в OCR использует модели компьютерного зрения
- db-28-search