Грядущий цикл

Грядущий цикл

@ai_longreads

Размышление о том, как разработка смещается от использования кодинг-агентов к написанию внешних циклов (loops), которые сами управляют агентами — и о том, что мы при этом рискуем потерять способность понимать собственный код.

Это AI-перевод статьи, сделанный каналом Про AI: Лучшие Статьи и Исследования.


Грядущий цикл

The Coming Loop Автор: Armin Ronacher Оригинальный текст:

>

За последние месяцы я наблюдаю, как всё больше людей строят поверх кодинг-агентов нечто такое, что ощущается принципиально иначе, чем просто использование кодинг-агента. Часть этого происходит поверх Pi — и видеть это, безусловно, здорово! Но паттерн везде один и тот же: работа складывается в своего рода очередь, машина забирает её, делает попытку, останавливается, а затем некий harness (обвязка, управляющий каркас) решает, был ли это действительно конец.

Если нет, harness продолжает ту же сессию, вбрасывает ещё одно сообщение, запускает свежую сессию с изменённым контекстом или отправляет задачу на другую машину. Задача остаётся живой и за той точкой, где модель сама по себе обычно сказала бы: «Я закончил».

Я думаю об этом типе цикла больше, чем хотел бы признавать.

Внутри каждого кодинг-агента уже есть агентный цикл. Модель вызывает инструмент, учитывает результат, вызывает другой инструмент, читает файл, редактирует файл, запускает тесты и в конце концов выдаёт какой-то ответ. С этим циклом мы уже довольно давно хорошо знакомы. Другой цикл — это цикл на уровне harness: цикл снаружи агентного цикла. Этот цикл тоже не нов. Те или иные его версии мы делаем ещё с ранних дней Claude Code, но этот цикл становится всё более заметным в агентной инженерии, а в последние недели он начал доминировать в обсуждениях в Twitter.

У меня это пока плохо получается

Мой текущий статус таков: я не достиг особого успеха с этим способом работы для кода, который мне по-настоящему важен, — а такого кода, как выясняется, довольно много.

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

При таком желании мне чего-то не хватает в опыте с кодом, написанным без моего внимания, — особенно с кодом из циклов. Сегодняшние модели склонны выдавать код, который слишком оборонителен, слишком сложен, слишком локален в своих рассуждениях. Они избегают сильных инвариантов. Они добавляют запасные ветки (fallbacks) вместо того, чтобы делать плохие состояния невозможными. Они дублируют код, изобретают плохие абстракции и замазывают неясный дизайн ещё большим количеством механики. Но хуже того: пока я вижу очень мало прогресса в том, что это улучшается. Если что, в этом отношении мне кажется, что мы, возможно, даже делаем шаги в неверном направлении. По крайней мере, на мой вкус, нынешние «руки прочь» harness'ы вроде Claude Code с ultracode выдают код хуже, чем то, что мы производили прошлой осенью. Это потому, что Claude Code, например с Fable, будет без остановки работать над проблемой по тридцать минут и больше, тогда как раньше процесс был куда более «человек в цикле» (human in the loop).

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

Когда вы берёте такое поведение и помещаете его за циклы, вы это поведение усиливаете. Если каждая итерация добавляет ещё одну маленькую защиту, система медленно становится всё менее понятной, при этом выглядя более надёжной. Чем больше вы «руки прочь», тем сильнее это происходит. Это также прививает очень плохие практики, когда такие инструменты дают джуниорам без чётких ориентиров. Потому что если спросить их, зачем они всё это делают, они убедительно отстоят свою позицию.

Где циклы работают

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

Портирование кода — одна из них. Уже есть впечатляющие примеры масштабных автоматических усилий по портированию, включая описанную работу по переносу частей Bun с Zig на Rust. Я и сам успешно применял это, чтобы портировать MiniJinja на Go. Исследования производительности — ещё один случай, где это работает прекрасно. Машина может пробовать эксперименты, замерять их, отбрасывать неудачи и продолжать поиск. Сканирование безопасности тоже сюда вписывается естественно, как и почти любой вид исследований: попросить систему изучить сложное проблемное пространство и отчитаться, не обязательно фиксируя долговечный код. Многое из этого объединяет одно: либо они не порождают новый код, а трансформируют уже существующий, либо производят код, который намеренно не имеет долгого срока жизни. Они либо создают proof of concept (прототип-доказательство) или идеи, либо выявляют находки, либо ближе к механическому преобразованию.

Я считаю, что циклы, которые производят артефакты без необходимости в долговечности или создают некую явно проверяемую механическую трансляцию, важнее, чем общая способность harness механически измерять цель. Многие успешные применения циклов используют другую LLM в роли судьи или оркестратора. Случай механической трансляции можно проверить бинарным тест-кейсом, но его же может рассудить и LLM!

Claude Code, например, всё лучше создаёт целые экспериментальные рабочие процессы, которые затем сам же и выполняет. Конечно, код, который он производит, — это слоп (slop, низкокачественный мусорный текст/код), но это скорее вина модели, чем недостаток harness как хорошего судьи о том, привёл ли шаг рабочего процесса к чистому улучшению или завершению.

Harness просто нужен некий сигнал, который позволит ему продолжить. Этот сигнал не обязан быть объективным или бинарным — он лишь должен быть достаточно полезным, чтобы запустить ещё одну итерацию.

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

Софт как организм

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

Я стал инженером-программистом в среде, которая поощряла понимать машину. Всегда был слой, который можно было снять, чтобы углубить своё понимание. Машины, которые не демонстрировали детерминированного наблюдаемого поведения, может, и принимались, но в целом считались не вполне оптимальными. С точки зрения архитектуры софта я считал желательным двигаться дальше в сторону большего детерминизма, а не меньшего. Точно так же способность понимать код была неоспоримой целью. На практике это не всегда было возможно, но мы всё же гордились тем, что пишем код так, чтобы даже новым инженерам становилось возможно ориентироваться в сложных кодовых базах благодаря умной архитектуре. В хорошо спроектированных системах всегда были инженеры, которые знали, где живут инварианты, какие части несущие, а какие изменения безопасны. В идеале всё это было ещё и хорошо задокументировано. Там, где такого понимания не хватало, это обычно расценивалось как то, что нужно улучшать.

Очевидно, этот идеал всегда был под напряжением. У многих программных систем, особенно очень успешных, бывали периоды, когда инженеры в команде могли удерживать их в чистоте. Большие программные системы нередко слишком велики, слишком динамичны и слишком зависимы от внешних сервисов, чтобы уместиться в чьей-то голове. Даже без LLM мы уже диагностируем распределённые системы отчасти как врачи: мы наблюдаем симптомы, формируем гипотезы, «назначаем дополнительные анализы», пробуем какие-то средства и снова наблюдаем.

Но с LLM мы продвигаемся в этом направлении гораздо дальше и гораздо быстрее. Мы используем их, чтобы писать код, и используем их же для диагностики и лечения. Уже немало инженеров живут в мире, где первый шаг после возникновения продакшен-проблемы — это дать железяке прочитать логи, предложить корневые причины и проактивно выкатить патч. Получившийся патч затем нередко подхватывается другой машиной, которая его ревьюит, иногда даже выкатывая его в main без какого-либо человеческого надзора.

Очевидно, это мощно, и я не могу отрицать, что звучит привлекательно. Но поддаться этой идее — особенно при всё меньшем человеческом надзоре — означает принять, что мы, возможно, больше не понимаем систему целиком так, как прежде. Мы её лечим, мы её мониторим, мы её стабилизируем, но мы не обязательно её постигаем.

Я не сомневаюсь, что для какого-то софта это нормально. Не каждая строка кода заслуживает человеческого авторства, и в прошлом писался код и похуже.

Но хочу ли я, чтобы весь софт создавался именно так?

Полностью отказаться не получится

Что очень неуютно — так это то, что отказаться от этого полностью машинно-управляемого будущего может быть не вариантом.

Безопасность — самый ясный пример на сегодня. Даже если вы сами не используете циклы для создания софта, другие люди будут использовать циклы против вашего софта. Атакующие будут непрерывно гонять машины, а если не атакующие, то исследователи безопасности, и часть этой автоматизированной работы поднимет пыль, но также найдёт реальные проблемы. И сигнал, и шум придут к вам в объёме, с которым практически невозможно справиться, если только вы сами не натравите на проблему машину.

Пост Daniel Stenberg о curl'овском «лете блаженства» — хороший пример того давления, под которым уже находятся мейнтейнеры. Насколько я знаю, AI не играет какой-то огромной роли в основной разработке curl сегодня. Тем не менее, несмотря на всё это, мейнтейнеры завалены репортами, большинство из которых теперь сгенерированы AI.

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

То же верно и в конкуренции: одни команды переиграют другие за счёт чистой скорости. Какие-то проекты вдруг начнут двигаться быстрее, потому что крошечная группа разберётся, как эффективно оркестрировать машины. Какие-то стартапы будут делать впятером то, что раньше требовало пятидесяти человек. Кто-то буквально натравит машину на ваш продукт в цикле и попросит её «сделать как у того». И если их пользователи довольны, так ли это важно?

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

Формирование новых зависимостей

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

Если кодовая база производится циклами, ревьюится циклами, патчится циклами и поддерживается живой циклами, что произойдёт, когда у вас больше не будет доступа к тому же классу систем? Что произойдёт, когда какие-нибудь торговые ограничения отнимут доступ к самым мощным моделям? Что, если просто стоимость станет неподъёмной? Что, если вы и ваша команда попросту утратите последнюю оставшуюся способность понимать код без машины?

Мы можем создавать кодовые базы, которые не просто тяжело поддерживать людям, но которые предполагают участие машины как часть своей модели сопровождения. Это уже происходит! Происходит не везде и, может, даже не в тех формах, что видятся проблемными, но мы видим этого всё больше. Люди всё чаще мержат код, который не могут полностью объяснить. Люди теряют способность составить баг-репорт или что-то обсудить в чате, не дополнив и не перефразировав свои сообщения контекстом, предоставленным железякой. Слишком многие всё больше полагаются на машину, чтобы что-то резюмировать или поместить в контекст. Всё чаще я встречаю людей, которые общаются со мной через посредничество LLM.

Опять же, может, это и не окажется неправильным, но это колоссальное изменение того, как мы делали вещи.

Будущие harness'ы

Я почти не сомневаюсь, что всё идёт именно туда, но путь туда потребует от нас что-то сделать с нашим инструментарием повсюду, а не только в кодинг-агентах.

Просто оркестрировать больше циклов будет недостаточно. Лучшие визуализации изменений, или оркестрации, или агентов не восстановят наше понимание. Либо нам нужно найти умные способы снова втолкнуть человека в цикл и сделать изменения от циклов читаемыми в долгую, либо нам нужно найти лучшие способы компоновать эти всё более сложные системы.

Здесь же меняется и моё мышление о роли Pi. Pi был осторожен, и я считаю, что эта осторожность хороша. Я не хочу будущего, где каждое взаимодействие превращается в неуправляемый рой машин, вносящих изменения, за которыми я не могу уследить. Я бы не хотел, чтобы Pi превратился в неподдерживаемое месиво ради того, чтобы выиграть гонку к софту, который пишет сам себя, и я бы не хотел, чтобы Pi пропагандировал такой тип инженерии. В то же время Pi — это harness, а harness'ы находятся в центре того, как люди ставят эти новые типы экспериментов.

Очереди задач для кодинг-задач, оркестрация агентов, субагенты, долговечные (durable) сессии будут значить всё больше и больше. Даже тем из нас, у кого есть оговорки и кто не слепо принимает циклы, придётся начать ставить эти эксперименты. Придётся, потому что нам нужно понять, как сделать это будущее ограниченным и пригодным для выживания.

Управление циклами

Как вы можете прочитать из этого поста, я очень обеспокоен этим будущим. Не из-за страха, а из-за осторожности, исходя из опыта с этой технологией на сегодня.

Принять идею harness-циклов означает, что harness решает, когда работа закончена. В агентном цикле модель в конце концов говорит «готово», и я делаю ревью. Ещё до того я обычно подруливаю по ходу. Я вовлечён, и мне нравится учиться по дороге. В цикле, управляемом harness, я не уверен, какова вообще моя роль. Даже сигнал «готово» теряет всякий смысл и просто транслируется ещё одной машине, которая судит. Моя роль сводится к роли посыльного.

Сегодня мне не очень нравится бóльшая часть кода, который я вижу от систем, построенных таким образом, и точно так же мне не доставляет удовольствия взаимодействовать со слишком большим количеством софта, построенного с помощью AI. Зацикливание мощно, но оно всё больше снимает ответственность и, по крайней мере сегодня, очень сильно подталкивает нас сдаться машине.

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

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


Подпишитесь на канал и каждый день читайте лучшие материалы про AI переведенные на русский!

Нашли интересную статью для перевода? Пришлите нашему боту: @ailongreadsbot

Report Page