Один плохой файл уронил распознавание всех трёх документов — и бот соврал курьеру

Я строю конвейер, который принимает новых курьеров в парк: человек присылает фото паспорта, водительского удостоверения и техпаспорта на машину, а нейросеть их распознаёт и заполняет карточку сама. Работает так почти год, я привык, что к этому месту можно не возвращаться.
Я строю конвейер, который принимает новых курьеров в парк: человек присылает фото паспорта, водительского удостоверения и техпаспорта на машину, а нейросеть их распознаёт и заполняет карточку сама. Работает так почти год, я привык, что к этому месту можно не возвращаться.

20 сентября в очередь встал курьер из Дубны. Через минуту после загрузки фото бот прислал ему: «Не удалось распознать фото: паспорта, водительского удостоверения, техпаспорта. Перезагрузите фото». Следом второй бот, который ведёт диалог дальше, добавил от себя: «Кажется, вы прислали не ту сторону техпаспорта».

Проблема в том, что оба сообщения были неправдой. Я открыл фото из заявки — паспорт нормальный, права нормальные, техпаспорт нужной стороной, ничего не размыто. Человек прислал ровно то, что просили.

Где искал не там

Первая мысль — плохое освещение или блик на фото, бывает. Проверил разрешение снимков — норм. Проверил, не перепутан ли порядок загрузки — тоже норм. Минут двадцать я разглядывал картинки глазами, пытаясь понять, что в них не так, — и ничего не находил, потому что искать нужно было не в фото.

Причину нашёл, только когда открыл сырой лог запроса к модели распознавания. Там лежал ответ провайдера: `400 Failed to load image: cannot identify image file`. Не «фото плохое», а «файл не открылся» — и это была ошибка не на одно фото, а на весь запрос целиком.

Как это работает и почему один файл топит всех

Конвейер собирает все документы курьера — паспорт, права, техпаспорт — в один запрос к модели и отправляет разом, чтобы не тратить три вызова вместо одного. Экономия оправдана, пока все вложения — обычные фотографии. Курьер из Дубны один документ прислал не фотографией, а PDF — так у него сохранял снимки встроенный сканер в телефоне. Для модели PDF — не картинка, она его открыть не смогла, вернула ошибку на весь запрос, и все три документа получили один и тот же вердикт: не распознано. А второй бот, который ведёт диалог с курьером, увидел флаг «техпаспорт не распознан» и — за неимением другой причины в своём словаре — предположил самую частую: не та сторона. Соврал уверенно, потому что для него это выглядело как обычный случай.

Фикс без нового провайдера

Переписывать конвейер на три отдельных вызова не хотелось — это и медленнее, и дороже на каждой заявке, а ломается формат файла редко. Решение оказалось проще: PDF со скана телефона внутри почти всегда обычный JPEG, обёрнутый в PDF-контейнер. Я скачал файл курьера как бинарные данные и поискал в нём последовательность байт, которой начинается и заканчивается JPEG — нашёл ровно один кусок, 582 килобайта картинки внутри 586-килобайтного PDF. Вытащил его, обернул в data-URL как обычное изображение — и отправил в модель уже как фото.

Дальше — на случай, если внутри окажется что-то, что так просто не вытащить: если извлечь картинку не получилось, из запроса исключается только этот один документ, а не вся пачка. Остальные распознаются как обычно, а курьеру приходит просьба перезагрузить именно тот файл, который не открылся, — а не выдуманное объяснение про сторону документа.

Что осталось открытым

Второй бот — тот, что придумал про сторону техпаспорта, — я пока не трогал. У него есть отдельная проверка: если распознавание техпаспорта не удалось, он считает это признаком неправильной стороны фото. До сих пор это было разумное предположение, потому что раньше распознавание действительно падало в основном по этой причине. Но сбой запроса к модели — по любой причине, не только PDF, — выглядит для него точно так же, и он снова соврёт с той же уверенностью. Разделить «фото плохое» и «сервис не смог открыть файл» на стороне этого бота я пока не сделал: правка живёт в том месте, где бот решает, что писать человеку, а там уже работают три десятка других сценариев, которые не хочется задеть впопыхах.

Курьеру фото пересобрали руками в тот же день, заявку он прошёл. А правило для себя я вынес простое: если бот две минуты подряд говорит явную ерунду про то, что человек прислал, — первым делом смотреть не на присланные файлы, а в сырой ответ модели. Спор с фотографией отнял двадцать минут; ответ модели рассказал всё за десять секунд.