Автоматизация обработки счетов-фактур (Accounts Payable) часто упирается в качество OCR. Традиционные методы теряют структуру, а крупные мультимодальные модели (LMM) требуют огромных ресурсов. В этом руководстве мы разберем lift-pdf — специализированную библиотеку для schema-guided document understanding. Она позволяет извлекать структурированные данные (JSON) из PDF-документов, используя заданную схему, что критично для интеграции с ERP-системами.
011. Подготовка окружения и установка зависимостей
Для работы требуется GPU с поддержкой CUDA. Библиотека lift-pdf имеет зависимости от transformers и bitsandbytes. Критический момент: версия библиотеки Pillow. В средах типа Google Colab часто возникает конфликт версий между Pillow, Torchvision и Transformers. Рекомендуется явно фиксировать версию Pillow (в примере используется 11.3.0).
Установка выполняется через pip. Обратите внимание на флаг -q для тихой установки и обработку ошибок при перезагрузке модулей.
# Установка основных пакетов
pip install -q -U reportlab pypdfium2 pandas matplotlib
# Установка lift-pdf с поддержкой HuggingFace
pip install -q -U "lift-pdf[hf]"
# Установка для квантования (опционально, но рекомендуется для экономии VRAM)
pip install -q -U bitsandbytes accelerate
# Фиксация версии Pillow для избежания конфликтов
pip install -q -U "pillow==11.3.0"022. Настройка GPU и квантование моделей
Модель datalab-to/lift весит значительно в полном формате BF16. Для видеокарт с меньшим объемом VRAM или для ускорения инференса необходимо использовать 4-bit квантование (NF4). Скрипт автоматически определяет доступную VRAM и вычислительную способность (Compute Capability) GPU.
Логика выбора режима:
- Full Precision (BF16/FP16): Требует GPU с большим объемом VRAM (A100/H100) или явное принудительное включение.
- 4-bit NF4: Автоматически включается, если VRAM ограничена и не задан флаг полной точности. Использует
bitsandbytesдля снижения потребления памяти.
Код инициализации с патчингом HuggingFace для поддержки квантования:
import torch
import os
# Определение GPU
if not torch.cuda.is_available():
raise SystemExit("✗ No CUDA GPU found. Use A100, L4 or T4.")
gpu_name = torch.cuda.get_device_properties(0).name
vram = torch.cuda.get_device_properties(0).total_memory / 1e9
cc = torch.cuda.get_device_capability()
# Настройка квантования
use_4bit = (vram < 34) # Пример логики
compute_dtype = torch.bfloat16 if cc[0] >= 8 else torch.float16
if use_4bit:
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=compute_dtype
)
# Патчинг AutoModel классов для применения bnb_config...
# (См. полный код в исходнике для patching transformers)
os.environ.setdefault("MODEL_CHECKPOINT", "datalab-to/lift")
# Загрузка модели
from lift.model import InferenceManager
MODEL = InferenceManager(method="hf")
print(f"Model loaded. VRAM: {vram:.1f} GB")033. Определение схемы извлечения (Schema)
Главное преимущество lift-pdf — работа со строгой схемой. Мы определяем, какие поля извлекать: поставщик, клиент, номер счета, строки товаров, налоги, суммы. Модель будет возвращать JSON, соответствующий этой структуре, включая обработку отсутствующих значений (null) и вычисление итогов.
Пример схемы для счета-фактуры:
{
"invoice_number": "string",
"invoice_date": "date",
"vendor_name": "string",
"bill_to_name": "string",
"line_items": [
{
"description": "string",
"unit_price": "float",
"quantity": "int",
"line_total": "float"
}
],
"subtotal": "float",
"tax": "float",
"total": "float",
"amount_paid": "float",
"balance": "float",
"is_paid": "boolean"
}Система также умеет вычислять производные поля. Например, is_paid рассчитывается как balance <= 0.005, а balance выводится из разницы между общей суммой и оплаченной.
044. Генерация тестовых данных и извлечение
Для отладки пайплайна используются синтетические PDF-счета, сгенерированные через reportlab. Это позволяет контролировать ground truth (истинные значения) и тестировать edge-кейсы: например, счета с частичной оплатой или отсутствующими полями (ship-to address).
Процесс извлечения выглядит так:
from lift import extract
# Путь к PDF файлу
pdf_path = "invoice_001.pdf"
# Выполнение извлечения
result = extract(
pdf_path,
schema=schema,
model=MODEL,
page_range=None # Обрабатывать все страницы
)
# Получение результата
extraction = result.get("extraction")
print(json.dumps(extraction, indent=2, ensure_ascii=False))Модель lift-pdf справляется с типичными ловушками бухгалтерии:
- Различие между
bill-to(плательщик) иship-to(получатель). - Корректное выделение налога (tax) от субтотала (sub
Источник: MarkTechPost ↗
