Рабочий контур вместо «внедрить ИИ»
Почему просьба «внедрить ИИ» не превращается в задачу, что приходит ей на замену и как выглядит проверка, которую контур может провалить.
Одну и ту же работу можно записать двумя способами.
«Внедрить ИИ в поддержку» — и «сократить время до первого содержательного ответа на типовое обращение, оставив человеку право переписать ответ до отправки».
Первая формулировка выглядит как задача и ею не является. У неё нет входа, нет критерия готовности и нет человека, который скажет «принято». Её нельзя провалить — а значит, нельзя и выполнить. Через полгода такая задача либо всё ещё в работе, либо закрыта демонстрацией, которой никто не пользуется.
Вторая формулировка — задача. Не потому что она красивее, а потому что из неё сразу видно, чего не хватает: что считается типовым обращением, что такое содержательный ответ, кто и когда смотрит.
Разница между ними — это и есть разница между «ИИ» и рабочим контуром.
Ниже — разбор пяти элементов, а в конце подробный пример: контур управления интерфейсом из платформы, которую я строю, и то, как в нём распределены модели по шагам.
Что такое контур
Контур — повторяющийся кусок работы, у которого можно назвать пять вещей.
Вход. Что приходит, в каком виде и в каком объёме. Не «обращения клиентов», а «письмо на общий ящик, в среднем сорок в день, из них половина с вложением».
Преобразование. Что нужно сделать: извлечь поля, отнести к категории, сверить с базой, написать текст. Одно действие, а не «обработать».
Проверка. Как понять, что результат годный. Самый пропускаемый пункт и единственный, ради которого стоит читать дальше.
Выход. Куда уходит результат и кто с ним работает следующим. Если следующего нет, контур не нужен.
Владелец. Живой человек, отвечающий за результат перед этим следующим.
Если хотя бы один элемент не описан — автоматизировать нечего. Не потому что модель не справится, а потому что не с чем сравнивать её работу.
Почему из этих пяти важна проверка
В большинстве провальных внедрений, которые я разбирал, модель работала нормально. Ломалось другое: никто не мог быстро сказать, хороший ответ или плохой.
Это звучит как организационная мелочь, но последствия у неё арифметические. Пусть контур обрабатывает сто заявок в день, а проверка результата занимает у человека столько же времени, сколько заняло бы выполнение с нуля. Тогда вы не автоматизировали ничего: вы поменяли работу «сделать» на работу «прочитать и решить, сделано ли», сохранив объём и добавив риск.
Вся выгода автоматизации живёт в зазоре между стоимостью выполнения и стоимостью проверки. Где зазор большой — выигрыш реальный. Где его нет — выигрыш мнимый, и его не спасёт ни модель посильнее, ни промпт подлиннее.
Отсюда практический ход, который я предлагаю всем до написания первого промпта: соберите двадцать реальных входов и руками разметьте ожидаемый выход. Не описание требований, а именно пары «вход → что я считаю правильным ответом».
Это занимает полдня и делает три вещи сразу. Даёт материал, на котором можно сравнивать версии промпта. Показывает, какие случаи вообще бывают, включая те, о которых в постановке не было ни слова. И — почти всегда — обнаруживает, что у двух человек в команде разные представления о правильном ответе.
Последнее и есть главная находка. Разногласие людей никуда не девается от того, что работу передали модели: оно просто перестаёт быть видимым.
Из чего вообще бывает проверка
«Проверка» звучит как одно действие, а на деле это четыре разных механизма с разной ценой и разным покрытием. Их полезно различать, потому что выбор между ними определяет, сколько стоит контур в эксплуатации.
Детерминированная. Результат проверяется правилом, которое не требует суждения: поле заполнено, сумма сходится, дата в допустимом диапазоне, ссылка открывается, JSON валиден по схеме. Стоит копейки, покрывает мало, но покрывает намертво. Всё, что можно вынести сюда, надо выносить сюда — это единственный вид проверки, который не деградирует с ростом объёма.
Эталонная. Есть заранее размеченный набор, на нём считается доля совпадений. Те самые двадцать примеров. Дешёвая в прогоне, дорогая в поддержке: набор устаревает вместе с процессом, и это скрытая статья расходов, о которой никто не помнит на старте.
Выборочная человеческая. Человек смотрит не всё, а долю — скажем, каждый десятый результат, плюс все, где сработала точка остановки. Даёт оценку качества и ловит новые классы ошибок. Дорогая ровно настолько, насколько велика доля.
Вторая модель как судья. Отдельный дешёвый вызов проверяет выход первого: есть ли ссылки на источники, отвечает ли текст на заданный вопрос, нет ли утверждений, которых нет во входных данных. Работает лучше, чем принято думать, но у неё есть неприятное свойство: она хорошо ловит нарушения формы и плохо — правдоподобную неправду по существу. То есть закрывает ровно тот класс ошибок, который и так дешевле закрыть детерминированной проверкой, и почти не помогает там, где болит.
Порядок выбора я держу такой: сначала вынести максимум в детерминированную, потом собрать эталонный набор, потом настроить выборочный контроль, и только потом, если осталась незакрытая дыра, — судью на модели. На практике до четвёртого пункта доходят редко, и это нормально.
Есть исключение, где я бы поменял порядок: если выход — длинный связный текст для внешнего читателя, судья на модели идёт раньше выборочного контроля. Не потому что он точнее, а потому что человек, читающий сотый однотипный текст подряд, перестаёт видеть ошибки примерно к тридцатому.
Возражение, которое обычно справедливо
Мне регулярно отвечают: у нас не всё формализуемо, половина работы — это суждение, его нельзя разметить.
Чаще всего это правда, и правда наполовину. Не формализуется решение. Но вокруг решения почти всегда лежит слой подготовки, который формализуется отлично: собрать данные в одном месте, привести к общему виду, вытащить противоречия, показать, чего не хватает.
Так что вопрос не «формализуема ли работа», а «какой из её слоёв формализуем». Контур описывают вокруг подготовки, а решение оставляют человеку и делают точкой остановки. Это скучный ответ, но он работает чаще, чем попытки научить модель судить.
Где возражение действительно бьёт: если работа нерегулярна и каждый случай непохож на предыдущий, размечать нечего, и никакой контур не строится. Тогда правильный ответ — не строить.
Точки остановки
Хороший контур умеет останавливаться. У каждого шага должно быть условие, при котором работа уходит человеку: низкая уверенность, нестандартный вход, сумма выше порога, противоречие в данных, отсутствие обязательного поля.
Без таких условий контур не автоматизирован. Он просто оставлен без присмотра, и разница между этими состояниями проявляется в первый же нестандартный день.
Наблюдение из практики, которое стоит проверить у себя: контуры чаще всего ломаются не на пике нагрузки, а в первый рабочий день после длинных выходных. Причина простая — за паузу накапливается очередь, в которой доля нестандартных случаев выше обычной. Ровный будний день такого не покажет, поэтому тестировать контур на среднем дне бесполезно. Берите накопленную пачку и смотрите, что происходит с очередью, когда точка остановки срабатывает двадцать раз подряд.
Разные модели на разные шаги: разбор Faber
Ещё один разбор того же принципа на другом контуре — в записи «Модель выбирает, арифметика считает», где расчёт маршрута вынесен из модели в обычный код.
До сих пор речь шла о контуре как о целом. Но у контура есть внутренняя структура, и из неё следует вещь, которую легко пропустить: модель — это свойство шага, а не свойство системы.
Разберу на платформе, которую строю сам. Faber — локальное рабочее место для чатов с моделями и автономных агентов; среди прочего в нём есть контур управления приложениями операционной системы. Шаги у этого контура разные по природе.
Шаг «понять, что на экране» получает на вход снимок окна и дерево доступности, а на выходе должен назвать одно действие. Ему нужна модель, которая видит изображение.
Шаг «вызвать инструмент» получает короткий текст и возвращает короткий структурированный вызов. Зрение ему не нужно вообще; нужна поддержка инструментов и предсказуемый формат.
Если держать одну модель на оба шага, вы платите за зрение там, где оно не требуется. Причём платите не разницей в тарифе, а объёмом: кадр — это сотни-тысячи входных токенов, и на шаге вызова инструмента их просто не должно быть.
Выбор по способности, а не по названию
В настройках Faber два раздельных параметра: основная модель и модель
зрения, причём у второй значение по умолчанию — auto.
Разрешение устроено так: если пользователь выбрал модель зрения явно —
берётся она; иначе сначала проверяется основная модель, а если и она
не видит изображений, перебирается каталог. Проверка не по имени модели
и не по списку, зашитому в код, а вопросом к провайдеру: у модели
запрашиваются её способности, и подходит та, у которой среди них есть
vision. Так же устроена и проверка поддержки инструментов.
Это решение стоит отдельного слова, потому что альтернатива выглядит проще и почти всегда оказывается хуже. Зашитый в код список «вот эти модели видят картинки» устаревает раньше, чем выходит релиз: каталоги провайдеров меняются еженедельно, модели появляются и снимаются с обслуживания. Вопрос к провайдеру всегда актуален, а список — никогда.
Побочный эффект того же решения: перебор устойчив к тому, что модель исчезла из каталога между двумя запросами. Такая запись просто пропускается, и контур продолжает искать дальше вместо того, чтобы упасть.
Где в этом контуре деньги
Цикл ограничен двадцатью четырьмя шагами, и на каждом шаге допускается до трёх попыток, если модель вернула невалидное действие. Верхняя граница одного запуска — семьдесят два обращения к зрячей модели.
Отсюда решение, которое я считаю в этом контуре главным: на каждом шаге собирается свежий контекст. Системное сообщение, задача и ровно один текущий кадр. Предыдущие кадры в переписку не добавляются.
Соблазн сделать наоборот велик — кажется, что модель должна видеть историю, чтобы понимать прогресс. Цена такого решения квадратичная: на двадцать четвёртом шаге в контекст уехали бы все двадцать четыре кадра, и последний шаг стоил бы в двадцать четыре раза дороже первого. При линейной схеме шаг стоит одинаково всегда.
Прогресс при этом не теряется — он передаётся не картинками, а коротким текстовым следом действий и сравнением текущего кадра с предыдущим. Это ровно тот случай, о котором я писал в записи про контекстное окно: память контура — не то, что модель «помнит», а то, что вы решили заново положить ей во вход.
Чего в этом контуре пока нет
Честно про границу: выбор модели в Faber идёт по способности, а не по стоимости. Если основная модель умеет видеть, она же и будет работать на шаге зрения — даже когда в каталоге есть модель дешевле, которая справилась бы с этим шагом не хуже.
Для контура, где зрение вызывается редко, это несущественно. Для контура с семьюдесятью двумя обращениями за запуск — уже нет. Следующий шаг здесь — маршрутизация с учётом цены: среди моделей, у которых есть нужная способность, выбирать не первую попавшуюся, а самую дешёвую из подходящих. Это довольно небольшая правка в том же месте кода, и она не требует ничего менять в остальном контуре — что само по себе хороший признак того, что разделение проведено по верной границе.
Правило, которое отсюда следует
Если в контуре больше одного шага, вопрос «какую модель взять» задан неправильно. Правильный вопрос — «какая модель нужна этому шагу», и ответов будет столько же, сколько шагов с разными требованиями.
Проверяется это одним признаком: если смена модели у вас настраивается одним полем на всю систему, значит шаги ещё не разделены — и вы платите по самому дорогому из них за все.
Чего я делать не стал бы
Описывать процесс целиком в подробной нотации до того, как выбран один шаг. Схема as-is на две стены выглядит убедительно и почти не помогает: она фиксирует, как работа устроена сейчас, включая всё случайное, и превращает выбор первого шага в согласование картинки.
Начинать с самого больного места. Самое больное обычно и самое сложное: там много исключений, дорогая ошибка и заинтересованные стороны. Первый контур должен быть скучным и проверяемым — он нужен, чтобы команда увидела рабочий цикл целиком, а не чтобы спасти квартал.
И — заводить метрику «доля обращений, обработанных ИИ». Она растёт от любых действий, включая вредные, и ничего не говорит о том, стало ли лучше следующему звену.
С чего начать завтра
Возьмите один процесс, который повторяется чаще пяти раз в неделю. Опишите пять элементов на одной странице. Найдите шаг, где проверка дешевле выполнения, — его и отдавайте первым.
Если такого шага не нашлось, это тоже результат: у вас пока нет задачи для модели, есть задача сделать проверку дешевле. Она обычно решается не ИИ, а формой ввода, справочником и запретом на свободный текст там, где нужен выбор из списка.
Открытый вопрос, на который у меня нет хорошего ответа: как считать стоимость проверки, когда проверяющий — тот же человек, что и заказчик результата. Он не оценивает беспристрастно, он уже знает, чего хотел. Пока обхожу это тем, что размечает один, а сверяет другой, но это дорого и работает не везде.