Если вайб‑кодинг это гусеница, а харнесс это куколка, то что дальше? Я называю следующую стадию имаго‑кодингом (имаго: взрослая бабочка).

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

Давайте посмотрим, как моя система разработки дошла до имаго.

Пенетрация ИИ-моделью процессов разработки: холст, масло, слезы разработчиков и обманутые ожидания.
Пенетрация ИИ‑моделью процессов разработки: холст, масло, слезы разработчиков и обманутые ожидания.

Вначале я делал так же, как все: брал нейросеть и встраивал в существующие процессы разработки. Сначала это были чаты, затем плагины для IDE, затем собственный плагин под любимую IDE с MCP/SKILLS/TOOLS/AGENTS и локальной моделью, первые попытки написать харнесс, появление общедоступных харнессов и переход на них, дальнейшее улучшение харнесса плагинами.

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

В конечном итоге качество перестало расти, а скорость перестала быть целевой метрикой для улучшения. Тогда я понял, что для того, чтобы двигаться дальше, придется переосмыслить и поменять весь жизненный цикл разработки, от постановки задачи до сопровождения: этапы, их порядок и мою роль в них как человека. Так, от постоянных попыток улучшить старый процесс (вайб‑кодинг/харнесс) я начал менять сам процесс разработки (имаго‑кодинг).

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

Это в свою очередь бьет по безопасности поставки продукта, так как так же быстро и качественно принимать результат работы ИИ еще не научились, а обмазывание тестированием со всех сторон, конечно, полезно, но скорее маскирует проблему, чем исправляет ее.

Почему фронтирная модель не подходит

ИТ-разработчик в процессе: экран, платные токены, неполный контекст, усредненное решение.
ИТ‑разработчик в процессе: экран, платные токены, неполный контекст, усредненное решение.

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

В моем случае проблема стоит наиболее остро, потому что я ML‑разработчик, и на задачах машинного обучения это особенно заметно. В 2024 году, когда вышел бенчмарк MLE‑bench (75 соревнований Kaggle), сильная на тот момент модель в связке с харнессом AIDE получала хотя бы бронзовую медаль лишь примерно в 17% случаев.

За два года результат вырос: специализированные агентные системы сообщают уже о 65–70% (бронза означает попадание в top 40%). Но это публичные, хорошо описанные задачи с чистой постановкой, и высокий балл на них мало говорит о том, справится ли модель с закрытым проектом, где нет готовых решений и описанного контекста. Корень проблемы не в общей силе модели, а в том, что она не знает именно этот конкретный проект.

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

Как я до этого дошел

Озарение диффузорами: раздумья, когнитивные искажения, LoRA-адаптация
Озарение диффузорами: раздумья, когнитивные искажения, LoRA‑адаптация

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

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

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

И тут меня накрыло озарение: LoRA изначально создавали для языковых моделей, но массовое распространение она получила в адаптации diffusers‑архитектур, где сдвигает генерацию в нужную сторону. Так почему бы не вернуть ее в transformers и не создать адаптер для генерации кода, который будет смещать знания LLM в нужную проекту сторону?

Таким образом, LoRA стала следующим шагом. RAG стал приносить строителю (системе разработки) знания о проекте, а адаптер должен был принести привычки. Это два крыла имаго‑кодинга, необходимые для полета: без RAG адаптеру не за что зацепиться, а без адаптера строитель каждый раз заново учится писать так, как принято в конкретном проекте или отрасли.

Почему все говорят о харнессе и RAG, но не об адаптации модели, ведь у многих разработчиков уже есть достаточные GPU‑мощности для этого? Я считаю, что это еще одно когнитивное искажение, ведь рисовать картинки и генерировать слова внешне абсолютно разные действия и архитектуры, хотя внутри те же слои, нейроны и веса.

Меня уже спрашивали, не является ли имаго‑кодинг вариантом spec‑driven development, то есть разработки, ведомой спецификациями, которая сейчас набирает популярность вместе с харнессами. Это не так, главное отличие в том, что именно дорабатывается. SDD улучшает запрос: агент общего назначения получает подробное структурированное описание того, что нужно сделать. Имаго‑кодинг улучшает исполнителя: меняется сама модель и ее представление о том, как в этой теме решают задачи.

Схема строителя: харнесс, RAG, LoRA

Непорочное зачатие модели-строителя: заметки в Obsidian, LLM-критик, сотни тестов
Непорочное зачатие модели‑строителя: заметки в Obsidian, LLM‑критик, сотни тестов

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

Второй слой это RAG. При его построении я использую контекстуальный чанкинг с векторными эмбеддингами, BM25 и RRF. Эту идею я подсмотрел у Anthropic.

Третий слой это LoRA/QLoRA. Веса модели‑строителя класса 27–35B замораживаются, обучаются только небольшие добавки к матрицам. При таком подходе число обучаемых параметров можно сильно сократить на выбранном спектре задач, поэтому дообучение под каждый проект стало доступным индивидуальному разработчику без большого GPU‑кластера (в моем случае достаточно 48GB). Обучающие пары я беру из истории самого проекта и родственных проектов, например из GitHub‑репозиториев. Идею я заимствовал у разработчиков OctoCoder, которые придумали, как превращать историю публичных Git‑репозиториев в источник размеченных учебных данных.

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

Совместная работа этих слоев и есть имаго‑кодинг. LoRA обучается не отдельно от RAG, а вместе с ним: примеры уже содержат найденные куски контекста. Так модель учится не только «писать как я», но и пользоваться найденным, в том числе игнорировать лишнее. Этот подход я взял из развития идеи RAFT, где модель обучали на вопросах вместе с релевантными и отвлекающими документами. К этой схеме я пришел далеко не сразу, перебрав и протестировав несколько десятков различных идей и методик.

Самое сложное в имаго‑кодинге это правильный сбор датасета для модели‑строителя, и здесь я напрыгался на граблях когнитивных искажений.

Первое большое искажение, на преодоление которого ушло огромное количество времени, касалось размера датасета. Оказалось, что больше не значит лучше. В первых версиях я собирал выборку по принципу «взять все, что есть»: вся история репозиториев, все статьи и ноутбуки, все сгенерированные примеры и так далее. Строитель от этого только ухудшался, а мне казалось, что данных просто недостаточно. Выяснилось, что небольшой набор хороших данных дает больше, чем большой набор усредненных.

С тех пор я вычищаю несколько вещей. Во‑первых, примеры, которые учат фактам, а не привычкам (почему это важно, расскажу ниже). Если ответ опирается на знание, которого у модели нет, такой пример я либо убираю, либо перевожу в RAG. Во‑вторых, код, который не прошел тесты или проверку на реальной версии языка. В‑третьих, повторы: коммиты вида «поправил опечатку» и десять его копий слишком сильно учат одному и тому же. В‑четвертых, старые решения, которые я сам уже считаю плохими: адаптер закрепит их с той же уверенностью, что и хорошие. В‑пятых, утечку между обучением и проверкой: если задачи для проверки строителя пересекаются по времени с обучающими коммитами, я делю их по дате. И в‑шестых, я обязательно слежу за балансом по типам задач. Если семьдесят процентов выборки это мелкие правки, строитель отлично правит мелочи и теряется, когда нужно спроектировать новый модуль. Поэтому я смотрю на состав выборки так же внимательно, как на ее размер.

Второе большое искажение было в понимании того, что LoRA умеет, а что нет. Я думал, что дообучение вкладывает знания в модель. Оказалось, что это не так: новые факты модель при дообучении усваивает медленно, а по мере усвоения растет склонность к галлюцинациям.

Что же тогда делает моя LoRA? Судя по моим наблюдениям и найденным исследованиям, она учит поведению. Примерно от 500 до 1000 аккуратно подобранных примеров хватает, чтобы задать модели стиль и формат ответов, потому что знания в основном закладываются на предобучении. Мне это и нужно: чтобы строитель писал код в структуре моего репозитория, используя существующую логику и интерфейсы, вызывал мои утилиты, соблюдал мои проверки и не изобретал свои. В итоге факты приносит RAG, а привычки дает LoRA.

Третье большое искажение: я слишком доверял научным статьям, препринтам на arXiv, а также прикладным работам по узким темам. Когда харнесс начал собирать статьи с arXiv, я столкнулся с тем, что примерно у половины статей, на выводы которых я мог бы опереться, нет кода, и проверить их заявления нельзя. А там, где код был и я запускал его на своих данных, результат обычно получался заметно хуже заявленного.

Оказалось, что об этом уже известно: по оценке различных исследований, у статей с открытым кодом и данными воспроизводится около 80% результатов, а у статей, где открыты только данные, около 33%. Чаще всего это проявляется на новых архитектурах и методах, поэтому их приходится проверять вручную, то есть фокус работы смещается в R&D.

После дообучения строителя я столкнулся с небольшим проявлением эмерджентности модели. Она стала сама определять, какие решения из статей стоит брать из RAG‑выборки, а какие нет. Я думаю, что это следствие смещения распределения. Адаптер обучен на примерах, где решения прошли тесты и проверку на отложенной выборке, и у модели складывается внутреннее представление о том, как в этой области выглядят решения, которые работают. Метод из статьи, который в это представление не укладывается, она воспринимает как малоправдоподобный и дает ему меньший вес. Это согласуется с тем, что LoRA учит поведению и предпочтениям, а не фактам: у модели появляется «вкус» по отбору решений, что также относится к поведению.

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

Дообученная локальная модель с LoRA‑адаптером становится специализированной в конкретной теме: вероятность перетекает к тому, что работало именно в этой теме, и путь к решению из одного из тысячи превращается в самый «протоптанный». Я не утверждаю, что такая модель умнее фронтира: в общем смысле фронтир гораздо умнее. Адаптер смещает не столько знания, сколько предпочтения по их выбору, и переставляет приоритеты между тем, что модель и так умеет. RAG дает факты (версии, схемы, статьи), а адаптер выбирает, что из этого важно и в каком порядке действовать.

Это помогает преодолеть распространенный сбой агентных систем в цикле разработки: тест падает, модель чинит, тест падает по‑другому. Модель общего назначения в такой ситуации нередко ходит по кругу: предлагает исправление A, потом B, потом снова A с небольшой переделкой, потому что все три выглядят одинаково разумно. Или уходит в менее релевантные решения: переписывает то, что работает, вместо того чтобы искать причину там, где она в проектах такого типа обычно сидит. Адаптер, обученный на истории проектов, где такие задачи уже решались, смотрит сразу туда, где ответ обычно лежит. В итоге в своей узкой теме модель тратит меньше шагов на рабочее решение, меньше спотыкается и не ходит по кругу.

Смещение распределения также улучшает качество кода. Напомню, универсальная модель пишет усредненный код: он работает, но собран из того, что чаще встречалось в обучающих данных, а не из того, что актуально в конкретном проекте. Вместо существующего хелпера появляется новый, вместо бизнес‑сущности проекта собственная структура, вместо вызова уже написанного сервиса копия его тела. Получается рабочая лапша, которую потом долго разбирает ревьюер (если вообще разбирает).

Это проблема всей отрасли. Отчет с аналитикой GitHub‑репозиториев основан на 211 миллионах измененных строк за 2020–2024 годы. Он зафиксировал восьмикратный рост частоты повторяющихся блоков кода в 2024 году. Доля перемещенных строк (признак рефакторинга и повторного использования) упала с примерно 25% в 2021 году до менее 10% в 2024. По моему мнению, это следствие распространения ИИ‑ассистентов с моделями общего назначения.

Имаго‑модель пишет иначе. Если в проекте есть кодовая база, строитель пишет код так, как принято в ней: использует ее бизнес‑сущности и абстракции, а не сходу изобретает свои. Если кодовой базы еще нет, он пишет так, как принято в этой отрасли, потому что привычки перенял через LoRA из родственных проектов и отобранных примеров из отрасли.

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

Еще одно искажение, от которого я избавился после перехода на имаго‑кодинг: я думал, что со временем потеряю навыки разработчика, ведь если код пишет модель, то разработчик деградирует. В имаго‑кодинге я оказываюсь в петле получения знаний из‑за устройства самого процесса. Чтобы собрать датасет для строителя, мне приходится постоянно заниматься R&D: читать статьи и разбираться в архитектурах, изучать код репозиториев проекта и родственных проектов, решать, какие решения включить в выборку, а какие выбросить и почему. Харнесс помогает: собирает, суммирует, ищет, но решение остается за мной, и принять его, не понимая сути, нельзя. Чтобы отличить хороший коммит от костыля, нужно понимать архитектуру глубже, чем требуется для того, чтобы просто принять сгенерированный код, а это, на мой взгляд, и есть ядро квалификации.

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

Соберу все в одну картину: изменился не только сам процесс разработки, изменилась роль разработчика в процессе: из напарника харнесса он стал архитектором модели‑строителя. Также изменились затраты времени: центр тяжести сместился с разработки на данные и проверку, и сама разработка стала самым коротким этапом.

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

Важное для меня следствие: на такой результат обратили внимание B2B‑интеграторы. Раньше я работал в основном напрямую с клиентами, а теперь все больше работы идет через субподряд и white label‑решения для интеграторов. Они приходят с проектом, где сжатые сроки или сложная специфика. Я делаю ядро системы в виде модели или всю систему, а конечному заказчику она уходит под их брендом.

Изменилась и моя собственная роль. Я все меньше пишу код и все больше занимаюсь тем, что не делегируется: R&D, подготовкой данных для имаго (то есть для строителя), архитектурными решениями, контролем и проверкой результата.

Слабые места

Исцеление слабых мест: холст, темпера, legacy-баги, переобучение адаптеров и вердикт архитектора.
Исцеление слабых мест: холст, темпера, legacy‑баги, переобучение адаптеров и вердикт архитектора.
  1. Адаптер привязан к конкретной версии базовой модели, и при выходе новой базовой модели его приходится обучать заново. Фронтирные модели улучшаются каждые несколько месяцев, обучение адаптера занимает 1–2 дня. В большинстве проектов это не критично, и обновление адаптера можно делать примерно раз в год. Мне же приходится делать это на каждом новом проекте.

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

  3. Необходимо делать отдельный адаптер под каждого клиента: никаких общих обучающих выборок между проектами, максимум общие статьи с arXiv по одной отрасли. Адаптер, обученный на данных клиента А и попавший в проект Б, это не только утечка, но и ухудшение качества работы системы. За 21 год в ИТ‑разработке и комплексной автоматизации предприятий я ни разу не видел два одинаковых проекта в одной и той же сфере.

  4. Считать стоимость токенов в имаго‑кодинге не нужно. Вместо этого нужно считать GPU, электричество и, главное, свое время на подготовку данных и обучение. CAPEX/OPEX тут со своими нюансами. Для больших проектов это окупается, для двухчасовой задачи проще взять модель без адаптации.

  5. Модель, которая знает, что обычно работает, склонна недооценивать по‑настоящему новое. Хорошая идея из статьи без кода или с непривычной формулировкой может получить мало веса. Поэтому в каждом проекте я просматриваю список отвергнутого вручную и запускаю на проверку некоторые перспективные, на мой взгляд, но отвергнутые идеи.

  6. Перестройка процесса стоит времени сама по себе. Для команды, которая делает один короткий проект, это может не окупиться, и тогда лучше использовать ИИ‑модель в харнессе как есть.

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

  8. Несмотря на то, что я использую имаго‑кодинг с начала года, это все еще опыт одного разработчика на ML‑проектах. Он показывает, что подход работает у меня, но это не значит, что он универсален.

Заключение

Крещение в цифровых водах: чистка датасета, крылья RAG и LoRA, освящение архитектуры и изгнание усредненного кода.
Крещение в цифровых водах: чистка датасета, крылья RAG и LoRA, освящение архитектуры и изгнание усредненного кода.

Встроить нейросеть и харнесс в процесс разработки сегодня означает ускорить один этап и упереться в остальные. Настоящий эффект дает смена самого процесса: появляются этапы, которых не было (настройка строителя и данные как отдельная работа), центр тяжести уходит с написания кода на данные и проверку.

Имаго‑кодинг это мой способ так работать: строитель внутри харнесса сам становится частью проекта, у него два крыла: RAG приносит факты, LoRA приносит привычки, а по моим наблюдениям еще и вкус, то есть умение не верить статьям, которые проверить нельзя.

Главное, что дает такой строитель: он смещает распределение знаний в сторону темы проекта и продавливает путь к решению там, где универсальная модель ходила бы по кругу или предлагала бы менее подходящие варианты. Он пишет код проекта, с его бизнес‑сущностями и абстракциями, а не усредненную лапшу. Поэтому такой код быстрее проходит ревью и создает меньше технического долга. А я сам, занимаясь R&D и отбором данных, не теряю квалификацию. При этом данные заказчика, включая коммерческую тайну и персональные данные, не покидают контур.

Главная сложность не в обучении, а в датасете: больше не значит лучше, и выборку для строителя приходится собирать и чистить как продукт, опираясь на собственный опыт. Модели заказчиков, от небольшой 9B до полноценной 35B, обучаются обычным способом, а имаго‑кодинг отвечает за то, как быстро и аккуратно я эти модели строю.

На моих проектах это выглядит как один месяц вместо трех у команды из трех человек при более высоком качестве. Именно поэтому со мной стали работать интеграторы, а сам я все больше занят R&D, данными и контролем. Такой строитель не станет умнее фронтира вообще, но на узкой группе задач, где важно знать версию, схему данных и договоренности проекта, он может оказаться полезнее и не тратит окно контекста на объяснения. Это не разновидность разработки по спецификациям, а соседний прием: спецификация улучшает запрос, адаптер улучшает исполнителя, и вместе они, скорее всего, будут работать лучше, чем порознь, что я сейчас и проверяю.

Если ваша фронтир‑модель постоянно спотыкается и выдает усредненное решение, несмотря на все усилия, попробуйте имаго‑кодинг и решите сами, подходит ли вам такой код будущего. И не верьте на слово красивым метафорам, включая мою про бабочек.