Кожна компанія обробляє документи, які хтось передруковує в систему: рахунки постачальників, видаткові накладні, акти виконаних робіт, договори, банківські виписки, митні декларації. Класичний OCR із шаблонами працював для кількох масових форматів і ламався щоразу, коли постачальник змінював макет. Мовні моделі з підтримкою зображень змінюють економіку: один пайплайн читає сотні макетів українською та англійською — від чистих PDF до фото з телефона. У гайді описуємо, як ми будуємо такі пайплайни для продакшену і чому модель видобування — найпростіша частина.

Пайплайн з першого погляду

Пошта / завантаження / сканер
   │
   ▼
1. Приймання       → дедуплікація, визначення типу, розділення багатодокументних PDF
2. Підготовка      → текстовий шар або зображення сторінок, поворот, покращення сканів
3. Видобування     → LLM зі схемою (structured output)
4. Валідація       → бізнес-правила, звірка з даними ERP
5. Рішення         → автопроведення / ручна перевірка / відхилення
6. Інтеграція      → створення чернеток в ERP, прикріплення оригіналу
7. Навчання        → виправлення поповнюють набір evals і промпти

Саме кроки 4–7 визначають, чи система економить час, чи створює нову категорію помилок.

Кроки 1–2: Приймання й підготовка

Спершу класифікуйте. Перед видобуванням визначте тип документа (рахунок, кредит-нота, акт, договір) дешевим викликом класифікації. Різні типи потребують різних схем і правил.

Використовуйте текстовий шар, якщо він є. Цифрові PDF містять текст; його видобування (з макетом) дешевше й точніше за OCR. Бібліотеки на кшталт Docling перетворюють PDF, включно з таблицями, на структурований Markdown чи JSON, який моделі добре читають.

Надсилайте зображення для сканів і фото. Сучасні моделі приймають зображення й PDF напряму та читають і текст, і візуальний макет (підтримка PDF в Anthropic; vision). Для сканів поганої якості базове покращення — вирівнювання, контраст, достатня роздільна здатність — помітно поліпшує результати. Дуже довгі документи розбивайте за діапазонами сторінок.

Обробляйте файли з кількома документами. Один сканований PDF часто містить кілька рахунків. Визначайте межі до видобування або просіть модель повертати масив документів із діапазонами сторінок.

Крок 3: Видобування за схемою

Точно опишіть цільові дані схемою й використовуйте structured output, щоб відповіді завжди розбиралися:

from datetime import date
from decimal import Decimal
from pydantic import BaseModel, Field

class Line(BaseModel):
    description: str
    quantity: Decimal
    unit: str | None = Field(None, description="e.g. шт, кг, год, послуга")
    unit_price: Decimal = Field(description="Price per unit excluding VAT")
    vat_rate: Decimal | None = Field(None, description="VAT rate in percent, e.g. 20")
    amount: Decimal = Field(description="Line total excluding VAT")

class SupplierInvoice(BaseModel):
    supplier_name: str
    supplier_edrpou: str | None = Field(None, description="8-digit EDRPOU or 10-digit RNOKPP, digits only")
    invoice_number: str
    invoice_date: date
    currency: str = Field(description="ISO code, e.g. UAH, EUR")
    lines: list[Line]
    total_without_vat: Decimal
    vat_amount: Decimal | None
    total_with_vat: Decimal
    iban: str | None = Field(None, description="UA + 27 digits if present")
    evidence: dict[str, str] = Field(
        default_factory=dict,
        description="For key fields, the exact text from the document they were taken from",
    )

Застосовуються принципи зі статті структурований вивід LLM: nullable-поля для інформації, якої може не бути, чіткі формати в описах і поле evidence, що цитує вихідний текст. Цитати значно пришвидшують ручну перевірку й зменшують кількість вигаданих значень, бо модель мусить вказати, звідки взято значення.

Поради щодо промптів, специфічні для документів:

  • Поясніть локальні домовленості: «В українських рахунках суми часто пишуть з комою як десятковим роздільником і пробілом між тисячами».
  • Скажіть моделі, що робити з рукописним текстом, печатками й закресленими значеннями.
  • Просіть повертати null, а не вгадувати, і ніколи не обчислювати суми, яких немає в документі, — обчислення робить код.

Крок 4: Валідація — звідки береться надійність

Вивід моделі — це пропозиція. Чи вона правдоподібна, вирішує код:

Перевірка Приклад
Арифметика Сума рядків дорівнює total_without_vat; ПДВ дорівнює ставка × база з точністю до округлення
Формат Довжина й контрольна сума ЄДРПОУ; контрольна сума IBAN; дати в правдоподібному діапазоні
Довідники Постачальник є в ERP за ЄДРПОУ; IBAN збігається з відомими рахунками постачальника
Бізнес-правила Рахунок посилається на відкрите замовлення; суми в межах допуску замовлення
Дублікати Той самий постачальник + номер + дата вже оброблені

Окремої уваги заслуговує перевірка IBAN: змінений банківський рахунок у звичайному на вигляд рахунку — класична схема шахрайства. Ніколи не оновлюйте банківські реквізити автоматично з документа.

Крок 5: Рішення — автоматизація з людиною в циклі

Не кожен документ варто проводити автоматично. Маршрутизуйте залежно від валідації й ризику:

  • Автоматично створюйте чернетку, коли всі перевірки пройдені й постачальник відомий.
  • Ручна перевірка, коли будь-яка перевірка не пройшла, поле порожнє, постачальник новий або сума перевищує поріг. Показуйте документ поруч із видобутими полями й підсвіченими цитатами.
  • Відхилення чи ескалація, коли документ нечитабельний або підозрілий.

«Впевненість» моделі погано відкалібрована; будуйте маршрутизацію на детермінованій валідації, а не на запитанні моделі, наскільки вона впевнена. Відстежуйте частку документів, оброблених без виправлень, — це ваш реальний рівень автоматизації. Для складних винятків, як-от невідомий постачальник чи розбіжність із замовленням, агент з інструментами лише на читання може підготувати рішення для перевіряльника; див. workflow чи агенти.

Крок 6: Інтеграція з ERP

Створюйте чернетки, а не проведені документи, і прикріплюйте оригінальний файл і результат видобування для аудиту. В Odoo зовнішній API дозволяє створювати рахунки постачальників із рядками, прив'язувати контрагентів за податковим номером і прикріплювати PDF; наші патерни інтеграції — у статті інтеграція AI з Odoo через JSON-2 API, а локальні інтеграції платежів і логістики — у статті Odoo з Новою поштою і monobank. В Odoo Enterprise є й власні функції оцифрування документів; порівняйте їх із власним пайплайном перед розробкою — див. Odoo Community чи Enterprise.

Робіть інтеграцію ідемпотентною: ідентифікатор документа чи хеш вмісту запобігає дублюванню рахунків при повторному запуску задачі; див. надійність LLM API.

Крок 7: Вимірювання й покращення

Зберіть розмічений набір із 200–500 реальних документів від різних постачальників і різної якості та міряйте:

  • Точність полів для кожного поля (точний збіг після нормалізації).
  • Точність на рівні документа: частка документів, де всі критичні поля правильні.
  • Recall для null: коли значення немає, чи повертає модель null замість вигадки?
  • Частку наскрізної обробки: скільки документів проходить валідацію без ручних правок.
  • Час на документ для перевіряльників — до і після.

Кожне виправлення людини — це розмічений приклад. Щотижня додавайте вибірку в набір evals і перезапускайте його на кожну зміну промпту чи моделі; див. evals для LLM.

Вартість і пропускна здатність

  • Видобування з типового рахунку на одну-дві сторінки коштує від частки цента до кількох центів залежно від моделі й того, чи надсилаєте текст, чи зображення.
  • Використовуйте дешевшу модель для класифікації й чистих цифрових PDF; сильнішу — для сканів, рукописного тексту й складних таблиць.
  • Обробляйте через чергу з обмеженням конкурентності; для нетермінових накопичень використовуйте batch API — див. оптимізація витрат на LLM.
  • Порівнюйте з базовою лінією: повна вартість ручного введення зазвичай вимірюється доларами за документ, а не центами.

Приватність і відповідність вимогам

Рахунки й договори містять персональні дані (імена й податкові номери ФОП, підписи) і комерційну таємницю. Використовуйте провайдерів із відповідними умовами обробки даних і нульовим чи обмеженим зберіганням, тримайте оригінали у власному сховищі, обмежуйте доступ до інтерфейсу перевірки й встановлюйте строки зберігання. За суворих вимог видобування можна запускати на self-hosted моделях із підтримкою зображень. Деталі — у статті приватність LLM-застосунків. В ЄС перевірте, чи не підпадає якесь подальше рішення (наприклад, кредитна перевірка) під високоризикові категорії AI Act.

План впровадження

  1. Тижні 1–2: зберіть 300 показових документів, розмітьте 100, визначте схеми й правила валідації.
  2. Тижні 3–4: побудуйте пайплайн лише з чернетками й інтерфейсом перевірки; виміряйте точність на розміченому наборі.
  3. Місяць 2: пілот з однією командою; усі документи перевіряються; збирайте виправлення.
  4. Місяць 3: увімкніть наскрізну обробку для відомих постачальників за умови проходження всіх перевірок; залиште вибірковий аудит.

FAQ

Чи потрібен досі OCR? Для цифрових PDF використовуйте текстовий шар. Скани моделі з підтримкою зображень читають напряму; окремий крок OCR допомагає переважно для дуже поганих сканів або коли потрібен архів із текстовим пошуком.

Наскільки це точно? На чистих документах і з добре спроєктованими схемами точність полів зазвичай дуже висока; скани, рукописний текст і незвичні макети її знижують. Міряйте на власних документах — універсальної цифри немає.

Чи впорається з українськими й змішаними документами? Так, сильні багатомовні моделі обробляють українські, англійські й російські документи та змішані макети. Включіть приклади кожного типу в набір evals.

А договори й довгі документи? Видобувайте конкретні поля (сторони, строк, суми, умови розірвання) з цитатами й обробляйте довгі документи порозділово. Юридичну інтерпретацію розглядайте як підтримку рішень, а не автоматизацію.

Джерела

  1. Anthropic. PDF support і vision.
  2. OpenAI. Structured outputs.
  3. Docling — перетворення документів для AI.
  4. Kim et al. (2022). OCR-free Document Understanding Transformer (Donut).
  5. Huang et al. (2022). LayoutLMv3: Pre-training for Document AI with Unified Text and Image Masking.
  6. Odoo. Документація зовнішнього API.