⚡️ Кратко: ключевые факты и быстрый ответ
- Пункт 1: Парсинг чеков нейросетью — это связка из двух слоев: OCR (или QR-код фискального чека) отдает сырой текст, а LLM из семейств Gemini Flash, Claude Sonnet или DeepSeek раскладывает его в поля — сумма, дата, магазин, позиции, категория.
- Пункт 2: Главное отличие 2026 года — переход от «самопильных» регулярных выражений к схемам структурированного ответа: модель заполняет заданный JSON, а не свободный текст, и это дает точность выше на мятых, косых и засвеченных фото.
- Пункт 3: Начинайте с QR-кода фискального чека там, где он есть: он дает сумму и дату без распознавания картинки, а модель подключайте только для строк товаров и категоризации — так стоимость обработки падает в разы.
- Пункт 4: Подводный камень — тихая ошибка: модель может вернуть правдоподобную, но неверную сумму или перепутать дату. Без сверки суммы позиций с итогом чека и контроля баланса по выписке такой трекер опаснее таблицы вручную.
- Почему ручной ввод чеков съедает вечер: считаем потери
- Под капотом: как нейросеть читает чек, QR и PDF-выписку
- Сравнение подходов: Gemini Flash, Claude Sonnet, DeepSeek и специализированные API
- Банковские выписки: парсинг таблиц без потери структуры
- Категоризация расходов: правила, эмбеддинги и ручные исключения
- Сборка конвейера: схема ответа, валидация и контроль качества
- Инженерная безопасность: маскирование, локальные модели и контуры изоляции
- Типичные ошибки: где распознавание ломается и как это лечить
- Часто задаваемые вопросы (FAQ)
- Насколько точно нейросеть читает мятые чеки с фото — и сколько всё равно придётся править руками?
- Облачная LLM или локальная модель на своём сервере — что выгоднее для парсинга чеков?
- Как не слить лишнего: что из чека реально нужно отправлять в сторонний API?
- Банк не даёт API. Как вытащить операции из выписки?
- Как автоматизировать категории трат, чтобы не переписывать их каждый месяц вручную?
- 💡 В сухом остатке: главное
Почему ручной ввод чеков съедает вечер: считаем потери
Ручной ввод одного чека отнимает 40–60 секунд, а вместе с ежемесячной сверкой выписки — почти два часа в месяц. За год набегает 21–30 часов, то есть три-четыре полных рабочих дня.
Секунды на чек выглядят безобидно, пока не начнёшь их складывать. Пятьдесят секунд — округлённая цифра для простого чека из магазина: дата, сумма, продавец, категория. Если хочется разобрать позиции, счёт сразу идёт на минуты.
И самое неприятное: печатаете вы не так уж много. Основное время съедает не набор текста, а возвращение в контекст. Что за покупка на 2 347 ₽ три недели назад? Бытовая химия или продукты? Ответа в чеке уже нет.
| Этап | Время на операцию | В месяц (≈43 чека) |
|---|---|---|
| Ввод чека вручную | 40–60 с | 29–43 мин |
| Разбор выписки по карте и счёту | 60–90 мин | 60–90 мин |
| Правка категорий и поиск забытых покупок | 15–20 мин | 15–20 мин |
| Итого | — | ≈1 ч 45 мин – 2 ч 30 мин |
Цифры в таблице — бытовой сценарий: 8–10 покупок в неделю, часть из них онлайн, плюс пара поездок на транспорте. У семьи с детьми поток выше в полтора-два раза, у одного человека ниже, но порядок величин тот же.
Дальше включается накопление. Первые две-три недели человек честно вносит каждую покупку, потом появляется «потом разберу» — и стопка уезжает в ящик. По нашим наблюдениям, порог, после которого архив перестаёт разбираться вручную, наступает примерно на двух-трёх сотнях необработанных записей: восстановить по ним картину месяца уже дороже, чем начать заново.
Есть и физический дедлайн. Большинство чеков печатают на термобумаге, а она теряет контраст: в шкафу — за 6–18 месяцев, у окна или над обогревателем заметно быстрее. QR-код спасает только сумму, дату и продавца, построчного состава покупки в нём нет.
⚠️ Подводный камень: оцифровка чека через полгода после покупки — это уже не восстановление данных, а реконструкция по памяти. Позиции к тому моменту не читаются ни глазом, ни сканером, и аналитика «на что уходят деньги» остаётся мечтой.
Что меняет ИИ-разбор? Связка оптического распознавания и языковой модели сжимает обработку одного чека до 3–5 секунд и, главное, вытаскивает позиции, а не только итог. Модели семейств Gemini Flash, Claude Sonnet или DeepSeek тянут такую задачу уверенно, если снимок сделан ровно и не под углом.
Готовые сценарии такого конвейера описаны, например, у AI-сканера чеков OpenKlo: агент принимает фото или PDF, вытаскивает сумму, дату, магазин и товары, проставляет категорию и отправляет запись в систему учёта.
Что при этом происходит под капотом — токены, контекст, вызовы инструментов — мы разбирали в материале про устройство ИИ-агента. Спойлер: магия там заканчивается ровно на этапе распознавания, дальше начинается аккуратная инженерия.
💡 Инсайт: экономия не в секундах распознавания. Настоящее узкое горлышко — категоризация и сверка с выпиской. Автоматизируйте сначала их, иначе быстрый ввод чеков просто ускорит накопление мусора в таблице.
Под капотом: как нейросеть читает чек, QR и PDF-выписку
Чтение чека — это конвейер из трёх ступеней: детекция и выравнивание документа, распознавание текста либо декодирование QR, а затем извлечение полей языковой моделью по заранее заданной схеме.
Начинается всё с детекции. Фотография из-под пальца, с бликом от лампы и перспективным искажением — это ещё не документ, а просто кадр. Детектор находит четыре угла чека, отсекает фон и делает перспективное выравнивание, чтобы строки стали горизонтальными.
Дальше полезно привести изображение к чёрно-белому виду с адаптивной бинаризацией. Термобумага выцветает, а тени по краям дают серые пятна, которые сбивают распознавание. Простой порог здесь не работает — нужен локальный, по участкам.
Вторая ступень зависит от того, что именно пришло на вход. Скан или фото — идём в OCR (Tesseract, PaddleOCR и их аналоги). PDF-выписка из банка — сначала проверяем, есть ли текстовый слой: если он есть, распознавать нечего, поля вытаскиваются по координатам и ключевым словам, и это в разы быстрее.
А вот с фискальным QR всё интереснее. В квадратике зашиты дата и время, итоговая сумма, номер фискального документа и фискальный признак. Никаких позиций «хлеб 45 ₽» там нет — только шапка.
⚠️ Подводный камень: QR-код — самый дешёвый путь (ноль токенов), но он даёт только сумму и дату. Если нужна разбивка по товарам и категориям, придётся всё равно читать бумагу целиком. Разработчик SplitMe описывает ровно этот момент: чек по сути таблица, и соблазн решить всё нейросетью велик, но дешевле сначала попробовать QR.
Третья ступень — самая интересная. Сырой текст из OCR похож на кашу: обрезанные названия, слипшиеся цены, случайные символы. Здесь в дело входит языковая модель, и работает она не «как получится», а по схеме.
На вход подаём распознанный текст и строгое описание полей: дата, магазин, итог, список позиций с ценой и количеством. На выходе ждём валидный JSON, который сразу проверяется валидатором. Не прошло — повторяем запрос, а не правим руками.
💡 Инсайт: температура строго в ноль и жёсткая схема ответа дают больше, чем смена модели. Модель семейства ChatGPT с форматом ответа по схеме уже не «фантазирует» поля, а выбирает из того, что реально видит в тексте.
И да, длинный чек на 40 позиций ощутимо раздувает контекст — механика та же, что в любом агентском сценарии, мы её разбирали в материале про токены, контекст и MCP на пальцах. Дешёвый лайфхак: резать документ на блоки по 10–15 строк и склеивать результат, а не гнать простыню целиком.
Что это даёт на практике? Три ступени разделяют ответственность: геометрия отвечает за качество картинки, OCR — за символы, модель — за смысл. Когда что-то ломается, вы сразу видите, на какой ступени, а не гадаете, почему в отчёте за февраль оказался чек из июля.
Сравнение подходов: Gemini Flash, Claude Sonnet, DeepSeek и специализированные API
Короткий ответ: массовые фото чеков выгоднее отдавать Gemini 3.8 Flash, мятые и залитые кофе квитанции — Claude 5.5 Sonnet, текстовые PDF-выписки — DeepSeek-V4, а специализированные API берут фиксированной схемой полей и предсказуемым счётом.
Сразу оговорюсь про деньги: универсальной цены «за чек» не существует. Универсальные модели тарифицируются за токены, а картинка чека превращается в сотни–тысячи визуальных токенов в зависимости от разрешения. Поэтому в таблице ниже — не рубли, а относительный порядок затрат, который стоит перепроверить по актуальному прайсу вендора.
| Подход | Стоимость обработки | Мятые чеки, блики, плохой свет | PDF-выписки | Где силён |
|---|---|---|---|---|
| Gemini 3.8 Flash | ≈1× (базовая точка отсчёта) | Средне: спасает пачка из 10–20 фото в одном запросе | Читает нативно, включая сканы | Пакетная ночная обработка архива чеков |
| Gemini 3.1 Pro | ≈3–5× | Заметно выше Flash | Нативно, тянет длинные документы | Многостраничные выписки, где важна связность строк |
| Claude 5.5 Sonnet | ≈5–8× | Лучшая устойчивость к геометрии заломов и рукописным пометкам | Принимает PDF, длинные файлы приходится резать на части | Сложные квитанции и строгий JSON на выходе |
| DeepSeek-V4 | ≈1–2× | Слабее на фото: нужен предварительный OCR | Хорошо работает с текстовым слоем | Дешёвая нормализация названий магазинов и категорий |
| Специализированные API извлечения | За документ, а не за токены | Заявлена обработка заломов и теней | Да, «из коробки» | Фиксированная схема полей: сумма, дата, продавец, позиции |
Что это даёт на практике? Универсальная модель всегда отвечает текстом, и этот текст ещё надо привести к структуре. Специализированный сервис возвращает готовые поля, но взамен требует доверия к чужому конвейеру и плохо терпит нестандартные документы.
💡 Инсайт: не выбирайте одну модель на всё. Дешёвый Flash или DeepSeek делает первый прогон, а на эскалацию к Claude Sonnet уходят только те чеки, где не сошлась контрольная сумма позиций с итогом. На типичном архиве личных расходов так улетает в дорогой контур не больше 10–15% документов.
Про мятые чеки есть отдельный нюанс, который редко пишут в маркетинговых материалах. Термобумага выцветает, а тень от пальца на сумме читается моделью как цифра. Наш опыт подтверждает: сжатие фото до 1024–1280 пикселей по длинной стороне почти не влияет на точность, зато кратно снижает расход токенов и время ответа.
⚠️ Подводный камень: любой провайдер может тихо обновить модель, и ваша схема ответа поедет. Держите валидацию на своей стороне: сумма позиций плюс скидка должны сходиться с итогом, дата не может быть из будущего, ИНН продавца — фиксированной длины.
Если хочется совсем убрать внешние вызовы, распознавание поднимают локально на квантованной модели — мы разбирали этот путь в материале про квантование LLM и запуск крупных моделей на домашнем железе. Для тех, кто хочет понять, откуда в счёте берутся эти самые токены, пригодится разбор о токенах, контексте и MCP на пальцах.
В сухом остатке: универсальные модели гибче и дешевле на старте, специализированные API предсказуемее в проде. Подробный разбор того, где именно ломается распознавание чеков, есть в материале на Хабре — полезно для калибровки ожиданий.
Банковские выписки: парсинг таблиц без потери структуры
Банковская выписка сложнее чека тем, что это не одиночная картинка, а многоколоночная таблица с переносами строк, несколькими валютами и промежуточными остатками — ИИ здесь нужен как сборщик структуры, а не только распознаватель текста.
Чек живёт по принципу «одна транзакция — один документ». Выписка за месяц — это сотня операций в общем полотне, где дата, контрагент и назначение платежа легко перетекают между строками. Нейросеть, которая хорошо читает фото чека, на такой вёрстке начинает склеивать соседние операции в одну.
Практика показывает: надёжный конвейер здесь строится не на одной модели, а на трёх независимых каналах данных, которые потом сверяются между собой.
| Канал | Что даёт | Где ломается |
|---|---|---|
| Текстовый слой PDF | Полные реквизиты, назначение платежа, ИНН | Колонки склеиваются, теряется знак минуса |
| CSV-экспорт | Готовые поля и суммы без разбора вёрстки | Кодировка, разделитель, десятичная запятая |
| Балансовая сверка | Контроль корректности всей выборки | Не работает без начального остатка |
Первый канал — текстовый слой. У выписок из интернет-банка он обычно есть, и вытаскивать его лучше не «в лоб», а с сохранением геометрии: инструменты вроде pdfplumber или pdftotext с ключом -layout держат координаты слов. Дальше модель получает уже не поток букв, а подобие таблицы, и ей остаётся привести колонки к схеме.
Если текстового слоя нет, документ пришёл сканом или защищён паролем, включается распознавание по изображению. Здесь точность падает заметно, и именно на таких файлах всплывают дубли: одну и ту же страницу легко загрузить дважды. Спасает хеш файла и хеш пары «дата + сумма + контрагент».
⚠️ Подводный камень: в PDF расход часто подан как «−1 250,00», а в CSV тот же расход лежит положительным числом в отдельной колонке типа операции. Если не нормализовать знак и не распарсить десятичную запятую с неразрывным пробелом внутри суммы, бюджет молча поедет в противоположную сторону.
Второй канал — CSV. Он скучнее, зато почти всегда точнее: банк сам отдаёт поля. Беда в мелочах — cp1251 вместо UTF-8, точка с запятой как разделитель, сумма в кавычках. Эти три строки настройки экономят часы ручной правки.
Третий канал — сверка по балансу, и это главный трюк. В выписке есть остаток до и после каждой операции, а значит работает инвариант: начальный остаток плюс приходы минус расходы равно конечному. Не сошлось — парсер где-то потерял строку или перепутал знак. Такой контроль ловит ошибки, которые визуально незаметны.
💡 Инсайт: считайте не «сколько распозналось», а сколько операций прошло балансовую проверку. Расхождение в 1–2 рубля почти всегда означает не округление, а скрытую строку с комиссией, которую модель не увидела.
Логику распределения задач между моделью и кодом мы подробнее разбирали в материале Как работает ИИ-агент: токены, контекст и MCP на пальцах — там же объясняется, почему детерминированные проверки стоит держать вне модели.
В сухом остатке: нейросеть приводит хаос вёрстки к схеме, код нормализует единицы и знаки, а баланс говорит, можно ли этому верить. Уберите любой из трёх слоёв — и выписка превратится в лотерею.
Категоризация расходов: правила, эмбеддинги и ручные исключения
Категоризация работает как конвейер из трёх ступеней: сначала жёсткие правила по коду торговой точки и названию мерчанта, затем семантическая близость через векторные представления, а на верхнем уровне — ручные исключения, которые перекрывают всё остальное.
Порядок именно такой, и он неслучаен. Дешёвые детерминированные проверки должны отсекать основную массу чеков ещё до того, как вы отправите запрос в модель. Иначе каждый поход в магазин будет стоить денег и секунд ожидания.
Первая ступень — справочник мерчантов. В банковской выписке почти всегда есть MCC, четырёхзначный код категории торговой точки, и это самый надёжный сигнал. Проблема в том, что в QR-чеке такого кода обычно нет, зато есть название продавца в свободной форме: «ООО РОМАШКА», «Romashka LLC», «Ромашка ТД».
Поэтому название нормализуют: срезают организационную форму, приводят к нижнему регистру, убирают лишние кавычки и юридические хвосты. После нормализации три варианта выше склеиваются в один ключ. Дальше — точное совпадение со словарём, и категория присваивается без всякого ИИ.
Вторая ступень нужна там, где точного совпадения нет. Здесь в дело идут эмбеддинги: имя мерчанта превращается в вектор, и мы ищем ближайшие соседи среди уже размеченных названий по косинусной близости.
Тут и вылезает главная боль. «Магнит» у дома и «Магнит Косметик» семантически почти неразличимы, а категории у них разные. То же с «ВкусВилл» и «Вкусвилл» в разном регистре, с «Перекрёстком» и «Перекресток-Экспресс».
⚠️ Подводный камень: векторная близость не различает вывеску и сущность. Два магазина одной сети с разным профилем товаров дают почти одинаковые векторы. Спасает комбинация трёх сигналов: MCC, адрес точки и сумма среднего чека. По отдельности каждый врёт, вместе они работают устойчиво.
Как выбирать порог? Универсального значения нет, но эмпирическое правило такое: высокая близость — присваиваем автоматически, средняя зона — помечаем «под вопросом» и спрашиваем пользователя, низкая — считаем мерчанта новым. Точные числа подбираются на вашей же истории разметки, а не берутся из статьи.
Третья ступень — ручные исключения. Это обычная таблица «мерчант → категория» с приоритетом выше модели. Пользователь один раз сказал, что кофейня у офиса относится к «Рабочим расходам», и правило живёт годами.
| Ступень | Источник решения | Когда срабатывает | Приоритет |
|---|---|---|---|
| Ручное исключение | Пользователь | Всегда для конкретного мерчанта | Наивысший |
| Справочник | Нормализованное имя + MCC | Точное совпадение | Высокий |
| Эмбеддинги | Косинусная близость | Близость выше порога | Средний |
| Модель | LLM с таксономией в промпте | Мерчант неизвестен | Низкий |
Новый мерчант, которого нет в справочнике, уходит на четвёртую ступень: LLM получает список ваших категорий и название продавца, а на выходе отдаёт одну из них либо честное «не знаю». Ответ попадает в очередь на подтверждение человеком.
💡 Инсайт: храните уверенность рядом с категорией и показывайте её в интерфейсе. Молча отсортированный чек с ошибкой пользователь найдёт через месяц, а тот, что помечен «проверьте», поправит сразу. И каждое такое исправление автоматически становится новым ручным исключением.
Аккуратно стоит обойтись и с правами на эти правила. Массовое редактирование исключений через API агента — это ровно та история, где важно разграничение доступа: подробный разбор механики мы делали в материале про права доступа ИИ-агента.
В сухом остатке: правила дают скорость и предсказуемость, эмбеддинги закрывают вариативность написаний, ручные исключения страхуют всё остальное. Модель здесь — не главный судья, а последний резерв на незнакомых мерчантах.
Сборка конвейера: схема ответа, валидация и контроль качества
Конвейер обработки чека держится на трёх уровнях защиты: жёсткая схема ответа от модели, детерминированная проверка суммы и даты в коде и журнал отбраковки, куда падают все сомнительные записи для ручного разбора.
Первый уровень — схема. Не парсите свободный текст регулярками, это дорога в ад: модель сегодня вернёт «1 234,50 ₽», завтра «1234.5», а послезавтра добавит пояснение в скобках. Просите строгий JSON с фиксированным набором полей, ограничениями длины и перечислением допустимых валют.
Сумму держите строкой с регуляркой на формат, а не числом с плавающей точкой. Классический баг: 0.1 + 0.2 вdouble даёт хвост, и позиции перестают сходиться с итогом. Валидируем через Decimal.
import datetime
from decimal import Decimal
SCHEMA = {
"type": "object",
"required": ["merchant", "total", "currency", "purchased_at", "items"],
"additionalProperties": False,
"properties": {
"merchant": {"type": "string", "minLength": 2, "maxLength": 120},
"total": {"type": "string", "pattern": r"^\d{1,7}\.\d{2}$"},
"currency": {"type": "string", "enum": ["RUB", "USD", "EUR", "KZT"]},
"purchased_at": {"type": "string", "format": "date"},
"items": {"type": "array", "minItems": 1,
"items": {"type": "object", "required": ["name", "price"],
"properties": {"name": {"type": "string"},
"price": {"type": "string"}}}}
}
}
class Rejected(Exception):
def __init__(self, code, detail):
self.code, self.detail = code, detail
def verify(payload, today=None):
today = today or datetime.date.today()
total = Decimal(payload["total"])
if total <= 0:
raise Rejected("SUM_NON_POSITIVE", payload["total"])
items_sum = sum(Decimal(i["price"]) for i in payload["items"])
drift = abs(items_sum - total)
if drift > Decimal("0.05") * len(payload["items"]): # 5 копеек на позицию
raise Rejected("SUM_MISMATCH", f"{items_sum} vs {total}")
d = datetime.date.fromisoformat(payload["purchased_at"])
if d > today:
raise Rejected("DATE_FUTURE", d.isoformat())
if (today - d).days > 365 * 3:
raise Rejected("DATE_TOO_OLD", d.isoformat())
return payload
💡 Инсайт: сверка суммы позиций с итогом ловит выдуманные строки дешевле любого повторного прохода модели. Расхождение больше копеек на позицию — почти всегда признак галлюцинации, а не скидки.
Второй слой — контроль качества. Каждый отказ не выбрасываем, а пишем в журнал: файл-источник, сырой ответ модели, код ошибки, название модели и дата. Позже по этой таблице видно, что чинить: промпт, качество фото или конкретный банк с нестандартной вёрсткой.
| Код | Причина | Что делать |
|---|---|---|
| SUM_MISMATCH | Позиции не бьются с итогом | Повторный проход с обрезанным фото |
| DATE_FUTURE | Модель приняла срок годности за дату покупки | Подсказка в промпте с областью даты |
| DATE_TOO_OLD | Чек старше трёх лет | Ручная проверка, не автоприём |
| SCHEMA_INVALID | Ответ не прошёл по JSON-схеме | Повтор с температурой 0 |
Долю отбраковки держите как метрику здоровья конвейера. Ориентир — 2–5 %: выше значит проблема с промптом или качеством снимков, ноль значит валидатор слишком мягкий и мусор уже течёт в базу.
⚠️ Подводный камень: не просите модель самой считать итог, НДС и скидки. Арифметику делает код, модель только извлекает напечатанные числа — иначе получите красивые, но неверные суммы.
Как устроены сами вызовы модели и зачем здесь ограниченный контекст, мы разбирали в материале как работает ИИ-агент: токены, контекст и MCP на пальцах. Практика показывает: жёсткая схема плюс журнал отказов экономят больше времени, чем любая попытка «умнее попросить» модель.
Инженерная безопасность: маскирование, локальные модели и контуры изоляции
До отправки во внешний API из документа вырезают всё, что прямо идентифицирует человека и платёжное средство: ФИО, номер карты, адрес, телефон, номер счёта. Модели отдают только сумму, дату, название точки и список позиций.
Логика простая: распознавание строки «Магнит, 12.10, 843,50 ₽» не требует знания, чья это карта. Значит, лишнее в запрос не идёт. Работает это как конвейер обезличивания на входе в контур: сначала нормализация текста после OCR, потом замена чувствительных сущностей на плейсхолдеры вида <PERSON_1> или <CARD_4>, и только потом запрос к модели.
Ключевая деталь — словарь обратных подстановок. Соответствие «плейсхолдер → исходное значение» живёт в локальной базе и наружу не уходит никогда. Модель вернула JSON с <PERSON_1> — на нашей стороне он разворачивается обратно. Такой подход даёт бонус: по одному и тому же чеку можно прогнать несколько моделей и сравнить результат, не раскрывая данные повторно.
⚠️ Подводный камень: регулярка на номер карты не ловит номер, разбитый пробелами или переносами строк в PDF-выписке. Перед маскированием текст нужно склеить и нормализовать, иначе часть идентификаторов уедет в запрос как есть.
Первый контур изоляции — локальный OCR и детерминированный парсер. Tesseract или PaddleOCR снимают текст с картинки на своём железе, дальше регулярки и шаблоны достают 70–80% полей вообще без нейросети. LLM подключается только к тому, что не разобралось: нестандартная вёрстка, слипшиеся позиции, рукописные правки.
Что это даёт на практике? Отправляется не фотография на 2–3 МБ, а килобайт текста. Объём запроса падает на два порядка, а вместе с ним и поверхность утечки: изображение чека с адресом и последними цифрами карты остаётся в локальном хранилище.
Теперь про «держать распознавание у себя». Тысяча чеков после OCR — это порядка 0,7–1 млн входных токенов, то есть совсем немного. На таких объёмах облачные Gemini 3.8 Flash или Claude 5.5 Sonnet стоят копейки, и экономить на своём железе смысла нет.
Считать надо не цену токена, а объём архива и требования к приватности. Когда на входе десятки тысяч документов в месяц или выписки на 60–100 страниц, картина меняется: модель на 8–14 млрд параметров в квантовании Q4 укладывается в 6–10 ГБ видеопамяти и уверенно тянет извлечение полей из готового текста. Как это разворачивается на потребительской видеокарте, мы разбирали в материале про квантование LLM: GGUF и AWQ для запуска 70B на домашнем ПК.
Честная оговорка: на структурном извлечении из чистого текста разрыв между локальной моделью и флагманами невелик, а вот на грязных фотографиях и мятых чеках он заметен сразу. Поэтому гибридная схема обычно выгоднее крайностей.
💡 Инсайт: заведите флаг «документ содержит чувствительные сущности» и роутинг по нему. Обычные продуктовые чеки уходят в облако за скорость, а зарплатные ведомости и медицинские счета автоматически обрабатываются только локально. Один флаг закрывает большую часть рисков без потери качества.
Последний слой — сетевой. Исходящий трафик идёт через прокси с белым списком доменов, телеметрия SDK отключена, ключи лежат в секрет-хранилище и подставляются как YOUR_API_KEY из переменных окружения, а не из кода. Логи запросов хранят хеши, а не тела документов. Правовые нормы динамичны и требуют предварительной проверки юристами компании.
Типичные ошибки: где распознавание ломается и как это лечить
Распознавание ломается на четырёх вещах: бликах и засветке на фото, выцветшей термобумаге, расхождении в копейках между позициями и итогом, а также на потерянных строках в длинных чеках. Лечится это предобработкой снимка, жёсткой схемой ответа и обязательной сверкой баланса.
Начнём с самой частой беды. Человек фотографирует чек под лампой, глянцевый слой бликует, и половина строки «наименование» превращается в белое пятно. Модель не ошибается — она просто не видит символов и достраивает по смыслу, а это уже выдумка.
⚠️ Подводный камень: нейросеть почти никогда не отвечает «не разобрал». Она подставляет правдоподобное значение с уверенным видом, и поймать подмену можно только сверкой арифметики чека. Поэтому в схеме ответа всегда должно быть поле «уверенность» по каждой позиции — и правило «ниже порога → на ручную проверку».
Отдельная история — термобумага. Она выцветает за месяцы, а от нагрева в кармане или на торпеде просто чернеет. Скан такой бумаги даёт серый фон и рваный контраст, поэтому перед отправкой в модель стоит прогнать снимок через обесцвечивание и повышение контраста. Дешевле и надёжнее, чем гонять повторные запросы.
Копейки — самая коварная категория. Скидки, округления и налог считаются на кассе по своим правилам, и сумма позиций почти никогда не совпадает с «ИТОГО» до копейки. Прикинем на пальцах: тридцать восемь строк набежали на 2 314,90 ₽, а итог в чеке — 2 314,88 ₽. Разница в 2 копейки выглядит мелочью, но она ломает любой автоматический контроль и плодит ложные срабатывания.
Потерянные позиции обычно приходят из длинных чеков. Лимит контекста никто не отменял, и модель либо обрезает хвост, либо склеивает две строки в одну — подробнее про то, как работает контекст, мы разбирали в материале про токены и контекст ИИ-агента. Симптом простой: позиций меньше, чем строк в чеке, а итог сходится только на бумаге.
| Симптом | Причина | Лечение |
|---|---|---|
| Белые пятна в наименованиях | Блик, съёмка под лампой | Переснять без вспышки, рассеянный свет, обрезка фона |
| Серый фон, «шумные» символы | Выцветшая термобумага | Обесцвечивание, контраст, бинаризация до отправки |
| Расхождение на 1–5 копеек | Скидки и округления на кассе | Поле «итог» брать как есть, позиции не подгонять |
| Позиций меньше, чем в чеке | Обрезка контекста, склейка строк | Резать чек на блоки по 20–25 строк и собирать результат |
Наш опыт показывает: работает не «умная модель», а правило баланса. Считаем сумму позиций, прибавляем скидку, сверяем с итогом — и если расхождение больше пары копеек, чек уходит на ручную проверку вместе с исходным снимком. Хранить оригинал обязательно: без него спор с самим собой о потерянной строке не выиграть.
Часто задаваемые вопросы (FAQ)
Насколько точно нейросеть читает мятые чеки с фото — и сколько всё равно придётся править руками?
Точность зависит не от модели, а от качества входной картинки. Выцветшая термобумага, блик от лампы, чек, снятый под углом на коленке, — вот где начинаются потери. Модели семейств Gemini Flash, Claude Sonnet или GPT-6.x на чистом скане или PDF с текстовым слоем выдают структуру почти без ошибок, а на смятом фото в тёмном подъезде — уже нет.
Рабочая схема — два контура. Сначала быстрый OCR (Tesseract, PaddleOCR или встроенный OCR облака) вытаскивает текст, затем LLM приводит его к структуре: дата, магазин, итог, позиции. Если OCR уверен в символах, модель не гадает по картинке, а работает с чистым текстом — ошибок заметно меньше.
Второй контур — арифметическая проверка. Сумма позиций должна сходиться с итогом, дата не может быть из будущего, ИНН и номер чека проверяются по формату. Несходящийся чек уходит в очередь на подтверждение, а не молча пишется в базу.
Публичных замеров точности под ваш поток чеков не существует — не верьте красивым процентам из лендингов. Соберите контрольный набор из 100–200 своих реальных фотографий, прогоните через кандидатов и посчитайте долю чеков, которые ушли на ручную правку. Это единственная цифра, которая вам что-то скажет.
Облачная LLM или локальная модель на своём сервере — что выгоднее для парсинга чеков?
Считайте не «умность» модели, а стоимость одного чека. Порядок величин такой: изображение чека в визуальной модели съедает примерно 1–2 тысячи токенов, структурированный ответ с 15–25 позициями — ещё 500–800. Итого 2–3 тысячи токенов на документ. Тысяча чеков — это 2–3 миллиона токенов.
Дальше простая формула: (число чеков × токены на чек ÷ 1 000 000) × цена за миллион токенов у провайдера. Тарифы меняются, поэтому берите актуальный прайс на день расчёта, а не цифры из чужой статьи годичной давности.
Локальный контур (открытые визуально-языковые модели плюс OCR на своём железе) окупается в двух случаях: поток большой и стабильный либо данные нельзя выпускать за периметр. Минусы честные — нужен GPU, обновления моделей и инженер, который всем этим занимается.
Компромисс, который чаще всего и выбирают: дешёвая быстрая модель (например, Gemini Flash или DeepSeek) на типовые чеки, дорогая (Claude Sonnet, Gemini Pro, GPT-6.x) — только на те, где дешёвая вернула низкую уверенность или не сошлась сумма.
Как не слить лишнего: что из чека реально нужно отправлять в сторонний API?
В чеке почти никогда не нужны ФИО покупателя, полный номер карты (его там и нет), адрес и прочие идентификаторы. Для учёта расходов хватает суммы, даты, названия магазина и перечня позиций. Всё остальное вырезайте ещё до отправки.
Практика простая: на устройстве или в своём бэкенде обрезаете изображение до области с таблицей позиций, вырезаете QR и служебные поля, а в промпт кладёте только текст. Так модель видит меньше, а риск утечки падает.
Отдельно про маскирование: телефоны, почты и имена из чека заменяйте на плейсхолдеры до вызова внешнего API. Логи запросов храните без сырых изображений — только результаты и хеши. Правовые регламенты здесь динамичны и требуют предварительной проверки юристами компании, но инженерный минимум — минимизация данных — работает всегда.
И не кладите ключи доступа в мобильное приложение. Токен к API живёт на сервере, приложение ходит только к вашему шлюзу — иначе ключ вытащат из apk за вечер.
Банк не даёт API. Как вытащить операции из выписки?
Сначала проверьте, что есть. У большинства банков в интернет-банке лежит выгрузка в CSV или Excel — это самый дешёвый и точный путь, никакая нейросеть там не нужна, достаточно разобрать колонки. Если банк отдаёт PDF с текстовым слоем, хватит pdftotext или pdfplumber.
Нейросеть подключайте на третьем шаге — когда пришёл скан, скриншот или PDF-картинка без текста. Здесь модель работает хорошо: она вытягивает дату, сумму, знак операции и описание, даже если вёрстка у каждого банка своя.
Дальше обязательный шаг, о котором часто забывают: сверка баланса. Сумма всех операций плюс начальный остаток должна дать конечный остаток из шапки выписки. Не сошлось — значит, часть строк потерялась или задвоилась, и партию надо переобработать.
Поступления и списания различайте по знаку и типу операции, а не по цвету в PDF. Перевод между своими счетами не должен попадать в расходы — иначе отчёт поедет в два раза.
Как автоматизировать категории трат, чтобы не переписывать их каждый месяц вручную?
Начните с правил, а не с нейросети. «Пятёрочка», «Магнит», «Перекрёсток» — это «Продукты», и здесь достаточно справочника названий магазинов с нормализацией: убрать кавычки, привести к нижнему регистру, отрезать лишние приставки вроде города в скобках.
На незнакомых мерчантах включайте сравнение векторных представлений названий: «Кофемания» окажется близка к «кофе», «Шоколадница» — к «кафе». Работает лучше, чем точное совпадение строк, и не требует обучения.
Ключевое — порог уверенности. Если модель уверена, категория проставляется сама. Если нет, пользователь видит одну карточку с вариантами на выбор, а не весь список трат. И каждая правка должна запоминаться как новое правило — тогда через пару недель ручной работы станет заметно меньше.
Так учёт расходов, где парсинг чеков нейросетью совмещён с обучаемым справочником мерчантов, перестаёт быть бесконечной ручной работой: модель делает черновую часть, а человек подтверждает только спорные случаи.
💡 В сухом остатке: главное
Рынок технологий движется с бешеной скоростью. Не ведитесь на маркетинговый хайп: всегда тестируйте модели на реальных сценариях вашей команды и замеряйте финальную окупаемость.
Чек-лист для внедрения на практике:
- ✅ Шаг 1: Соберите тестовый набор из 30–50 своих реальных чеков и 2–3 банковских выписок — на мятых, засвеченных и старых документах, а не только на идеальных сканах.
- ✅ Шаг 2: Зафиксируйте схему извлечения (JSON со строгими типами полей: сумма числом, дата в ISO, магазин, список позиций) и запретите модели добавлять поля от себя.
- ✅ Шаг 3: Введите автоматическую валидацию — сумма позиций против итога, дата не из будущего, дубликат по хешу QR или по комбинации дата плюс сумма плюс магазин.
- ✅ Шаг 4: Оставьте человеку кнопку «поправить» и складывайте правки в отдельный журнал: это единственный честный источник данных для дообучения правил категоризации.
Обсудить материал и поделиться своими бенчмарками можно в комментариях к блогу.







