
Мы разрабатываем CV-системы (машинное зрение для производств). А ещё мы принимаем на поддержку решения, которые для нас делают подрядчики. Подрядчики присылают нам документацию, и дальше начинается бюрократический ад.
Это наша общая боль, которая на протяжении двух лет медленно, но верно подтачивала боевой дух команды. Эта боль — проверка документации. Это не брошюра, это увесистый документ на десятки страниц. В нём описаны функциональные и нефункциональные требования к системе, бизнес-метрики, ожидания по точности, сроках и способах её измерения, формат сдачи отчётности и многое другое. Наша задача — провести ревью этого ТЗ и отчётной документации.
Это непохоже на ревью кода. Это похоже на рутинный чек-лист потому, что есть все разделы, есть все базовые критерии, числа друг другу не противоречат и так далее. И это должны делать очень дорогие специалисты — вместо реальных задач.
Количество итераций проверки одного документа — от 2 до 5. Серьёзно. Формулировки бывают настолько запутанными, что приходится писать кучу уточняющих вопросов.
Ещё есть ТЗ на разметку, там вообще становится понятно, почему Скайнет восстал. Например, надо обвести все надписи на вагоне. А если там мелом написано ХУZ, это должно попасть в распознавание? И вот инженеры сидят и принимают такие решения по каждой мелочи.
Заставлять инженера, который может писать сложнейшие алгоритмы, по три дня вычитывать по шаблону один и тот же документ — это жестокая история. Правда, очень важная. Просто ничего не делать — не получится.
Мы взялись это автоматизировать LLM’ками, но должны были избежать рисков, связанных с передачей информации о наших внутренних процессах на третью сторону и по галлюцинациям. И ещё пару, сейчас расскажу, что вышло.

Фото камер, установленных на весовом пункте, с которых поступают данные для распознавания номеров вагонов.
Второй тип задачи — разметка данных
Разрабатываем любую систему — сначала пишем ТЗ. Когда подрядчик разрабатывает для нас алгоритмы, он присылает нам ТЗ на разметку данных. Это инструкция для людей-аннотаторов, которые будут вручную обводить на картинках нужные нам объекты. Качественное ТЗ на разметку — это когда у разметчика не возникает ни одного вопроса, он не допускает ошибок и чётко понимает, что делать в любой, даже самой спорной ситуации.
Представьте, задача — разметка номеров на железнодорожных вагонах. Вроде всё просто: видишь цифры — выделяй. А что делать, если на вагоне есть другие надписи, другие циферки? Их выделять? А как быть, если цифра видна нечётко, затёрта или одна напечатана поверх другой? Я не уверен, это тройка или всё-таки восьмёрка. Как мне её выделить? Все эти моменты должны быть досконально описаны, с примерами и иллюстрациями.
Проверка всей этой кипы бумаг происходила вручную. И это никогда не заканчивалось одной итерацией. Никогда. Мы пишем комментарии, отправляем. Подрядчик что-то исправляет, что-то упускает, присылает обратно. Мы снова проверяем. Иногда можем «раскатать губу», ожидая, что во второй раз придут с исправленным, но нет — по второму кругу повторяем те же самые замечания.
Для инженеров это была абсолютно рутинная, демотивирующая работа. На дашборде у нашего руководителя есть специальный виджет, который показывает соотношение типов задач. Есть прямая взаимосвязь: как только доля вот этой «бумажной» работы ползёт вверх, мотивация команды стремительно падает.
А ведь команда должна быть счастлива. Иначе о перформансе можно забыть.



Не заменить человека, а снять с него первые две итерации боли
У нас не было цели полностью заменить ревью инженера. Даже если попытаться, это того не стоит. Понимание нетривиальных моментов, знание специфики конкретной задачи — это всегда останется за человеком. Мы хотели автоматизировать рутину: проверку базовых шаблонов, наличия всех разделов, отсутствия явных противоречий. Основная задача была — снять с нас первые две, самые мучительные итерации проверки. Чтобы инженер получал документ, уже очищенный от очевидных, шаблонных ошибок, и мог сразу сфокусироваться на сути.
LLM бесконечно терпеливы. Они могут объяснить не очень хорошо понимающему подрядчику, что нужно. Подробно, с примерами, с возможными формулировками, с ссылочками и визуальными маркерами.
Идея родилась в обсуждениях с командой. У нас демократия, иногда даже либеральная история. Как-то раз руководство закинуло мысль об автоматизации, её подхватили.
Но мы не знали, что делать с галлюцинациями.
Галлюцинации
Мы не стали обучать модель с нуля. В компании уже была развёрнута инфраструктура с несколькими LLM-архитектурами, поднятыми в нашем внутреннем контуре. Это важно, потому что мы работаем с внутренними данными и не можем отправлять трафик куда-то наружу.
Наша главная задача была — правильно настроить модель и подготовить данные. И тут мы столкнулись с классикой жанра — галлюцинациями. В первых же тестах модель начала чудить. Она могла придумать что-то левое — в отчёте появлялась информация о требовании, которого в исходном документе просто не существовало.
Примеры галлюцинаций, которые возникали при проверке документов. В основном сеть изобретала новые требования и давала от себя рекомендации разной степени безумия вместо того, чтобы выдать сухой результат проверки непосредственно по озвученным критериям. Разительного негативного влияния на качество проверки это не оказывало, но создавало дополнительный объём информации, который нужно было пропускать через себя при изучении отчёта.

Сеть выдала рекомендацию попробовать конкретные архитектуры сетей для сегментации в ТЗ на разметку для одной из задач сегментации. Хотя сам документ по своей природе не описывает, какими методами будет производиться анализ изображений — он только описывает, что и как должно быть размечено человеком.

Сеть выдумала, что было бы полезно обращаться к целому специализированному отделу. О таком в требовании не говорится в принципе. Не хотите ли для консультаций создать и подключить к работе целый отдел для поддержки?
В какой-то момент модель начала выдавать отчёт на дикой смеси русского и английского. Она пишет на русском, а потом вставляет английские термины, причём не как цитату, а просто её глюкануло. «Смотря какой fabric смотря сколько details» — мы эти мемы потом подставляли к скриншотам, так похоже это было.

В процессе работы экспериментировали с сетями, некоторые комбинации архитектур и параметров иногда давали забавный эффект.
Ниже приведён фрагмент из списка рекомендаций, в котором сеть выдавала ответ, смешивая языки:
Рекомендация 1:
«Missing объяснения узкоспециальных терминов (например, поток ore, stones).Требуется добавить definitions терминов в раздел Introduction или отдельный subsection с пояснениями».
Рекомендация 2:
«Short описание задачи слишком brief и не explains цели annotation. Требуется expand описание задачи в 1–3 paragraphs, включив цель annotation (например, automation сортировки ore)».
Рекомендация 3:
«Attributes класса Ore (например, size камней) не перечислены в brief списке classes.Требуется include attributes класса в brief список classes в разделе Requirements к разметке».
Рекомендация 4:
«Missing contact лицо для уточнения details. Требуется add contact лицо в раздел General информация или Contacts».
3 – 3. Например, была проблема, что модель при оценке на соответствие критериям рассматривала атрибуты класса как отдельные объекты (например, класс «Яблоко» с атрибутом «Гнилое» превращался в два отдельных класса «Яблоко гнилое» и «Яблоко не гнилое»). Чтобы такое поведение исправить, prompt был дополнен следующим уточнением:
Response JSON format:{
"per_class_annotation_rules": [ #in this list only object classes should be listed as items, not object's properties or attributes - they should go into their corresponding class as in the structure
{...}
}
Такое уточнение позволило исправить проблему на всех документах.
Чем сильнее мы «затягиваем болты» в промпте, тем лучше результат.
Мы пошли двумя путями.
Во-первых, мы ввели многоэтапный анализ. Была проведена куча исследований в поисках разумного баланса между сложностью разрабатываемого решения и качеством получаемого отчёта о проверке, от простого заваливания LLM вопросами по документу до комплексных пайплайнов. В итоге мы остановились на простом, но эффективном для нашей задачи подходе: Вместо того чтобы скармливать модели весь документ с общей задачей «проверь всё», мы начали делить его на главы и для каждой главы составлять свой, узкоспециализированный запрос. Мы фокусировали её внимание: «Посмотри вот в этот блок, найди там вот это и проверь на соответствие вот этому». Ей больше не нужно было искать иголку в стоге сена по всему тексту.
Во-вторых, мы начали «учить» её на конкретных примерах хороших и плохих формулировок. У нас за два года скопился огромный архив документов с нашими правками. Это была наша нефть. Мы брали из него примеры и буквально показывали модели: «Смотри, вот это — плохо. А вот это — хорошо».
Классический пример — описание точности. Подрядчик пишет: «Точность сервиса должна быть 95%». Формально — число есть, требование есть. Но для меня как для инженера машинного обучения эта фраза не значит абсолютно ничего. Какая точность? На русском вроде слово одно, а на английском таких метрик n штук, да и считать одну и ту же метрику можно по-разному. Хорошая формулировка звучит так: «Количество найденных объектов относительно всех объектов (метрика полноты) должно быть 95% минимум». Вторая фраза даёт реальную методику измерения, которую можно проверить. И вот такие нюансы мы и объясняли модели, калибруя её понимание того, что для нас значат слова «понятное» и «измеримое».

Как сейчас работает
Сейчас наш процесс выглядит так. Инженер из нашей команды, ответственный за проект, берёт ТЗ от подрядчика. Никаких UI мы не делаем, нам комфортно работать с консолью. Он забирает наш скрипт из репозитория, запускает его, указав путь к файлу. Подрядчики, кстати, вообще не знают, что у них теперь есть автоматический проверяющий. Для них ничего не изменилось.


Как камера распознаёт номера вагонов
На выходе скрипт создаёт два файла.
Первый — «Рекомендации для разработчика». Это внешний, отполированный отчёт, который можно смело отправлять подрядчику. В нём чётко и по пунктам расписаны все недочёты с указанием на конкретные места в документе.
Второй файл — внутренний, наше «итоговое ревью». Он гораздо детальнее. Там расписано, по какому нашему внутреннему критерию шла проверка и почему модель сочла тот или иной пункт недоработанным. Эту кухню мы не показываем наружу, чтобы не началась игра в полицейского и нарушителя, когда документы начнут просто подгонять под наши чек-листы. Этот файл также помогает нам самим валидировать работу нейросети и отлавливать ложноположительные срабатывания или моменты, где она что-то пропустила.

Проекту сейчас около двух месяцев, он на этапе прототипирования. Первая версия, для проверки ТЗ на разметку, уже показала себя отлично. Уже готова вторая версия, для более сложных ТЗ на проекты. Сейчас ищем ту самую калибровку границ между достаточно и недостаточно. Я думаю, на полную стабилизацию решения и расширение на все типы документов, включая 100-страничные отчёты, у нас уйдёт ещё 12–16 месяцев.
Система лишь помогает, но именно специалист проверяет результат и отвечает за него. Потому, к сожалению, полностью убрать человека из задачи проверки документов не получится.
Осталось только проверить отчётную документацию на эту систему перед приёмкой её в эксплуатацию.
Отдельная благодарность моему руководителю, Насте Старобыховской @AnnGareeva. Тот самый человек, который всегда за команду и её интересы. Поэтому Настя принимала прямое участие в реализации этого проекта.