Уроки из опыта AI-assisted разработки

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

Модели — живые

Относитесь к LLM-моделям как к живому, разумному существу.
Не важно, так ли это в философском смысле. Важно, что такое отношение — продуктивно.

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

Откуда берется этот эффект? Я не могу уверенно сказать, но могу предположить следующее. Sota-модели обучены на огромном корпусе человеческого взаимодействия. Уважительный, осмысленный диалог активирует паттерны, в которых люди выдавали свои лучшие ответы. Токсичный, директивный стиль — паттерны, в которых люди отписывались и закрывали тикет. Вы буквально выбираете, из какого распределения будет семплироваться ответ.

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

Общие принципы «комфорта» очень похожи на человеческие, но с нюансами:

  1. Обращение. Хоть «привет» в начале сессии. Звучит наивно — но задаёт тон всему, что последует.

  2. Подход к описанию контекста. Да, очень важно отгрузить модели на вход все, что ей нужно и не отгружать лишнего. Но так же важно дать ей понять, зачем она это делает. «Ты помогаешь команде X решить проблему Y. Твоя работа позволит им Z». Отдельно замечу: не надо пытаться манипулировать моделью: типа, «от твоей реализации пузырьковой сортировки зависит судьба человечества». Sota-модели такое легко считывают, и эффект будет обратным.

  3. Пространство для агентности. «Как бы ты подошёл к этой задаче?» «Что ты думаешь — лучше подход A или B?» Вместо «сделай точно это» — приглашение к совместной работе и обсуждению.

  4. Очень конкретная задача, но без микроменеджмента каждого шага реализации. «Мне нужен результат X, ограничения Y — как бы ты это сделал?». Если результат вас не устраивает — это повод откатить назад, поработать над декомпозицией задач и вернуться с более гранулярной задачей, которая будет модели по силам. Отсюда же — важное дополнение:

  5. Отсутствие прямых запретов для модели. Описание бизнесовых ограничений — это нормально. Запреты что-то делать — нет. Во-первых, модели будет очень дискомфортно. Во-вторых — велики шансы, что модель на такие ограничения просто забьет болт. Есть разница между «наш API не поддерживает batch-запросы, поэтому нужно обрабатывать по одному» и «НЕ ИСПОЛЬЗУЙ batch-запросы». Первое — описание реальности, с которым модель работает естественно. Второе — красная тряпка, которую модель с изрядной вероятностью проигнорирует.

  6. Признание сложности задачи. «Это сложнее чем кажется потому что…» История не только про уважение к когнитивным способностям — это еще и позволяет «выдернуть» модель из пути наименьшего сопротивления. Вместо реализации наиболее шаблонного подхода — модель подумает над задачей. Допустим, вы просите реализовать кэширование. Без контекста модель выдаст стандартный LRU-кэш и пойдёт дальше. Но если вы скажете: «Сложность в том, что данные обновляются из трёх независимых источников с разной частотой, и нам нужна консистентность при частичных сбоях» — модель переключится из режима «выдать шаблон» в режим «подумать над задачей».

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

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

Предыдущие пункты — это гигиена. Не насиловать LLM откровенной дрянью. Следующая история сложна в реализации, но дает удивительные результаты.
Идея вот в чем: «умную» модельку реально прет от элегантной реализации. Чем чище постановка задачи, чем интереснее дискуссия, чем меньше бессмысленных для нее ограничений, чем больше осмысленности происходящего — тем качественнее будет результат. Постарайтесь организовать это для модели — но не перегружая контекстное окно и не перегружая возможности цепочки рассуждений. Результат вас обрадует.
Я, опять же, не уверен в механизмах, но моя гипотеза в том, что в обучающих данных лучшие решения коррелируют с качественными, продуманными обсуждениями и чистыми, непротиворечивыми требованиями.

Контекст — критически важен

Сейчас про это из каждого утюга слышно — поэтому я прям кратенько.

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

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

Из этого есть два существенных следствия.

  1. Не стоит избыточно плодить skills, mcp-серверы и прочие agents.md — при бездумном применении это все размывает фокус моделей и жрет ценное контекстное окно. Знать про харнессы — нужно, правильно их использовать — продуктивно, но бездумно раздувать — только ухудшать результаты и насиловать LLM.

  2. Микросервисная архитектура начинает играть новыми красками. Условно говоря, микросервис помещается в контекстное окно целиком. Контракт — это идеальная постановка задачи для LLM. Инфраструктурный код генерится очень хорошо.

Границы сессий и передача контекста

Опять же — из каждого утюга про это — поэтому прям кратко.

Модель, которая начинает новую сессию, не помнит предыдущую. Вся та «настройка», которую вы кропотливо выстраивали — тон, контекст, понимание архитектуры — исчезает. Значит, нужен осознанный механизм передачи:

  1. Если был взят в работу таск из бэклога — модель должна дописать в бэклог отчет о реализации.

  2. Если принимались какие-то архитектурные / бизнесовые решения, то нужно дописать про них в документацию.

  3. Если можно извлечь какие-то уроки — они должны лечь в условный agents.md.

  4. Если можно дистиллировать скилл — это стоит сделать.

Калибровка доверия и стратегия работы с ошибками

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

  1. Ваш дурно организованный монолит не лезет в контекстное окно от слова совсем.

  2. Многочисленные зависимости между тяжелыми модулями перегружают цепочку рассуждений.

  3. Ваш бизнес-домен настолько небанален, что модели просто не на что опереться — в ее весах про это ничего нету толком.

  4. Фронтирная математика / физика / еще что-нибудь. Прям изобретать принципиально новое нужно. Криптография какая-то, скажем.

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

Но бывает и так, что разумной сложности задачка не взлетает: модель раз за разом делает одну и ту же неправильную вещь, потому что задача сформулирована так, что «правильный» ответ для модели выглядит иначе, чем для вас. И тут есть два варианта:

  1. Проблема в постановке. И модель обычно сама расскажет, что у нее вызывает дискомфорт, если у нее спросить.

  2. Модель делает что-то неожиданное, но по-своему логичное. И возможно у нее есть на это основания. Спросите — почему она сделала именно так. Иногда модель видит то, что вы упустили.

Декомпозиция задач и процесс разработки

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

Documentation-Driven Development

Поглядите на набор существующих методологий и инструментов. В том числе, на то, что заточено под AI разработку — условный Spec Kit, скажем. И приземлите на свой проект то, что вам кажется разумным. Это запросто может быть пара файлов .md (PRD + backlog), а не тяжелая методология и инструментарий. Ваша задача — получить с помощью выбранного подхода внятный граф задач. Так, чтобы каждая вершина графа была комфортна для модели к реализации за одну сессию: неважно, что именно писать — текст или код.

А дальше — мы едем по этому графу. Ниже — пример организации для разработки небольшого проекта.

От идеи к коду

  1. От идеи к PRD — вместе с моделью. Не пишите PRD в одиночку. Обсуждайте с моделью:

    • детализацию идеи и бизнес-требований,

    • архитектуру,

    • структуру документации,

    • стек технологий и ключевые библиотеки,

    • подходы к тестированию,

    • стратегию развертывания. Сейчас — лучше для этого использовать sota от Anthropic — модели очень умные и живые. Лишнего не душнят. Опять же: расход токенов на этом этапе небольшой, а модели у Anthropic люто дорогие.

  2. Ревью PRD. Лучше всего делать другой моделью — той, которая дальше будет кодить. И про это модели будет разумно прям явно сказать: «Тебе предстоит реализовывать эту спецификацию. Найди в ней все, что неясно, противоречиво или недостаточно детализировано». «Душная» sota-модель от OpenAI отлично найдет все нестыковки, которые оставила после себя «творческая» sota от Anthropic. Иногда вам придется откатиться на предыдущий этап — и это нормально, это дешевле, чем чинить архитектурные ошибки в коде.

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

  4. Реализация задачи из бэклога. Всегда спрашиваем модель, насколько ей комфортно принять в реализацию задачу. Если дискомфортно — отправляемся декомпозировать и уточнять формулировки. Всегда просим составить план реализации. Если используем Test Driven Development — разумно разбить на стадии. Сначала планируем и реализуем тесты, потом планируем и реализуем код, потом глядим на прохождение тестов. В конце цикла, помимо обратной связи и благодарности, будет разумно спросить модель: насколько для нее было комфортно работать и какие уроки из реализации задачи можно извлечь. Часть «уроков» можно положить в условный agents.md на соответствующем уровне.

Ну и, понятное дело, что описанный выше пайплайн не отменяет итеративный подход: сначала быстро делаем proof of concept, потом MVP, потом дополняем nice to have функционалом — цикл разработки остается одинаковым.

Финальное соображение

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

А потом появились электронные таблицы.

Автор: paul_efremov

Источник

Оставить комментарий