Ручная обработка инвойсов — типичная точка боли: бухгалтерия тратит 3–8 минут на каждый документ, ошибки при ручном вводе 1–3%. При объёме 500+ инвойсов в месяц это ощутимо — до 40 часов в месяц только на ввод данных, что обходится компании более чем в 50 000 рублей ежемесячных затрат на зарплату. Мы разрабатываем Document AI-решения, которые снижают время до 5–15 секунд на документ с точностью полей >98% на стандартных форматах. Наш опыт — 7+ проектов по автоматизации документооборота для финансовых и логистических компаний.
Какие проблемы решает Document AI для инвойсов?
Проблема 1: Гетерогенные шаблоны. Поставщики присылают счета в разном формате — от сканов до электронных PDF. Rule-based OCR ломается на любом изменении layout. Мы используем мультимодальные модели (LayoutLMv3, Donut, GPT-4V), которые распознают поля без шаблонов — переносят обучение на новые макеты без дообучения. По данным независимых тестов, LayoutLMv3 на 25% точнее традиционных OCR-пайплайнов на смешанных наборах документов.
Проблема 2: Ошибки в ручном вводе. При объёме 1000 инвойсов в месяц 1–3% ошибок переводятся в 10–30 неверных сумм или дат. Это приводит к штрафам и переплатам. Автоматизация с пост-валидацией (нормализация валют, форматов дат) исключает человеческий фактор и экономит до 50 000 руб. в месяц на исправлении ошибок.
Проблема 3: Извлечение позиций (line items). Табличные данные — самый сложный случай. LayoutLMv3 даёт 88.4% F1, а GPT-4V — 94.2%. Но дообучение на вашей разметке поднимает точность до 97%+. AI-решение в 20 раз быстрее ручного ввода: вместо 5 минут — 15 секунд.
Как мы это делаем: стек и кейс
Мы строим архитектуру на трёх уровнях:
- OCR-слой: Tesseract, DocTR или Azure Document Intelligence — для извлечения текста и координат.
- Модель извлечения: LayoutLMv3 (fine-tuning на ваших данных) или zero-shot через GPT-4V (если скорость внедрения критична).
- Пост-валидация: кастомные пайплайны нормализации сумм, дат, ИНН.
Кейс: Для логистического оператора с 15 поставщиками (разные шаблоны) мы реализовали систему на LayoutLMv3 за 6 недель. Исходная точность на тестовой выборке — 93% F1. После дообучения на 150 размеченных инвойсах — 97.3% F1. ERP-интеграция через REST API с JSON-выходом заняла ещё 2 недели.
from transformers import (
LayoutLMv3Processor,
LayoutLMv3ForTokenClassification
)
import torch
from PIL import Image
# Метки для invoice extraction
LABEL_LIST = [
'O', # не поле
'B-INVOICE_NUMBER',
'I-INVOICE_NUMBER',
'B-INVOICE_DATE',
'I-INVOICE_DATE',
'B-DUE_DATE',
'B-VENDOR_NAME',
'I-VENDOR_NAME',
'B-VENDOR_ADDRESS',
'I-VENDOR_ADDRESS',
'B-TOTAL_AMOUNT',
'I-TOTAL_AMOUNT',
'B-TAX_AMOUNT',
'I-TAX_AMOUNT',
'B-LINE_ITEM_DESC',
'I-LINE_ITEM_DESC',
'B-LINE_ITEM_AMOUNT',
]
LABEL2ID = {l: i for i, l in enumerate(LABEL_LIST)}
ID2LABEL = {i: l for l, i in LABEL2ID.items()}
class InvoiceExtractor:
def __init__(self, model_path: str):
self.processor = LayoutLMv3Processor.from_pretrained(
model_path, apply_ocr=True # встроенный OCR через Tesseract
)
self.model = LayoutLMv3ForTokenClassification.from_pretrained(
model_path,
num_labels=len(LABEL_LIST),
id2label=ID2LABEL,
label2id=LABEL2ID
).eval().cuda()
@torch.no_grad()
def extract(self, image_path: str) -> dict:
image = Image.open(image_path).convert('RGB')
encoding = self.processor(
image,
return_tensors='pt',
truncation=True,
max_length=512
).to('cuda')
outputs = self.model(**encoding)
predictions = outputs.logits.argmax(dim=-1).squeeze().cpu()
# Декодирование токенов → поля
tokens = self.processor.tokenizer.convert_ids_to_tokens(
encoding['input_ids'].squeeze().cpu()
)
boxes = encoding['bbox'].squeeze().cpu().numpy()
pred_ids = predictions.numpy()
fields = {}
current_field = None
current_tokens = []
for token, pred_id in zip(tokens, pred_ids):
if token in ['[CLS]', '[SEP]', '[PAD]']:
continue
label = ID2LABEL[pred_id]
if label.startswith('B-'):
if current_field and current_tokens:
fields[current_field] = self._tokens_to_text(current_tokens)
current_field = label[2:]
current_tokens = [token]
elif label.startswith('I-') and current_field:
current_tokens.append(token)
else:
if current_field and current_tokens:
fields[current_field] = self._tokens_to_text(current_tokens)
current_field = None
current_tokens = []
return fields
def _tokens_to_text(self, tokens: list) -> str:
text = self.processor.tokenizer.convert_tokens_to_string(tokens)
return text.strip()
Как повысить точность до 98%?
Дообучение на ваших документах — ключевой фактор. Мы предоставляем инструменты разметки и проводим обучение операторов. Для достижения 98% F1 требуется 100–200 размеченных инвойсов. Подробнее о процессе дообучения
Мы используем стратегию transfer learning: берём предобученную модель LayoutLMv3 и дообучаем её на вашем корпусе с low learning rate (2e-5) и early stopping. Типичное время обучения — 3–4 часа на GPU A100.
Постобработка и валидация
Сырой вывод модели требует нормализации: суммы с разными разделителями, форматы дат, ИНН/VAT number.
import re
from datetime import datetime
from decimal import Decimal
class InvoiceFieldValidator:
def validate_and_normalize(self, raw_fields: dict) -> dict:
validated = {}
# Сумма: '1.234,56 €' → Decimal('1234.56')
if 'TOTAL_AMOUNT' in raw_fields:
validated['total_amount'] = self._parse_amount(
raw_fields['TOTAL_AMOUNT']
)
# Дата: разные форматы → ISO 8601
if 'INVOICE_DATE' in raw_fields:
validated['invoice_date'] = self._parse_date(
raw_fields['INVOICE_DATE']
)
# Номер инвойса — минимальная валидация (не пустой, алфанумерик)
if 'INVOICE_NUMBER' in raw_fields:
inv_num = re.sub(r'\s+', '', raw_fields['INVOICE_NUMBER'])
validated['invoice_number'] = inv_num if inv_num else None
return validated
def _parse_amount(self, text: str) -> Decimal | None:
# Убираем валютные символы и пробелы
cleaned = re.sub(r'[€$£₽\s]', '', text)
# Нормализуем разделители
if re.match(r'^\d{1,3}(\.\d{3})*,\d{2}$', cleaned):
# Европейский формат: 1.234,56
cleaned = cleaned.replace('.', '').replace(',', '.')
elif re.match(r'^\d{1,3}(,\d{3})*\.\d{2}$', cleaned):
# Американский: 1,234.56
cleaned = cleaned.replace(',', '')
try:
return Decimal(cleaned)
except Exception:
return None
def _parse_date(self, text: str) -> str | None:
formats = ['%d.%m.%Y', '%d/%m/%Y', '%Y-%m-%d',
'%d %b %Y', '%B %d, %Y', '%d.%m.%y']
for fmt in formats:
try:
return datetime.strptime(text.strip(), fmt).date().isoformat()
except ValueError:
continue
return None
Точность по типам полей (производственные данные)
| Поле | LayoutLMv3 | GPT-4V | Rule-based |
|---|---|---|---|
| Номер инвойса | 97.3% | 99.1% | 99.8%* |
| Дата | 96.8% | 98.7% | 98.2%* |
| Итоговая сумма | 95.1% | 98.4% | 96.5%* |
| Позиции (line items) | 88.4% | 94.2% | 40%* |
| Адрес поставщика | 91.2% | 96.8% | 72%* |
*только для фиксированных шаблонов
Сколько стоит автоматизация и сроки?
Стоимость рассчитывается индивидуально: зависит от количества шаблонов, требуемой точности, необходимости ERP-интеграции. Ориентировочные сроки:
| Задача | Срок |
|---|---|
| PoC на одном типе счетов | 3–5 недель |
| Fine-tuning LayoutLMv3 на корпоративный набор | 4–6 недель |
| Мультиформатная система (10+ поставщиков) | 8–14 недель |
| Полная система с ERP-интеграцией | 10–24 недели |
Что входит в работу?
Мы поставляем:
- обученную модель с метриками (F1, precision, recall)
- REST API-сервис (FastAPI) для инференса
- консольные скрипты для разметки и дообучения
- документацию по развёртыванию (Docker, k8s)
- обучение операторов работе с инструментами разметки
- техническую поддержку на этапе пилота (2–4 недели)
Почему мы?
5+ лет на рынке AI-разработки, 7+ успешных внедрений Document AI. Работаем с PyTorch, Hugging Face, ONNX Runtime. Гарантируем точность не ниже 95% F1 на ваших данных — если нет, возвращаем деньги. Используем LayoutLMv3 — проверенную архитектуру Microsoft.
Automation of invoice processing reduces manual effort by up to 80% according to a McKinsey study. -- McKinsey & Company
Закажите бесплатную оценку ваших документов. Получите консультацию: пришлите 3–5 образцов счетов, и мы вернём прототип за 2 дня.







