Недавно написал статью о проблемах использования ИИ (Иллюзии Интеллекта) при разработке программного обеспечения / Хабр, и решил не ждать у моря погоды, когда (и если) провайдеры исправят ситуацию на своей стороне, а попытаться самостоятельно выработать приемлемый алгоритм работы с ИИ, который был бы экономически выгодным и целесообразным при разработке ПО хотя бы лично для меня.
Данная статья - это очередной Хабрахак с подведением итогов и получением обратной связи об использовании ИИ-помощников при разработке программного обеспечения с примерами кода и итоговыми выводами о целесообразности использования ИИ в том или ином проекте.
А также поделюсь неожиданным инсайдом, который я случайно обнаружил в процессе работы над ИИ-кодом, который будет очень полезен матёрым программистам, которые до сих пор скептически относятся к использованию ИИ в своих проектах.
И чтобы было проще использовать ИИ-модели как инструмент при разработке ПО, крайне желательно решить проблему воспроизводимости (повторяемости) результатов, хотя бы в рамках одной версии модели, чтобы пользователь на один и тот же запрос мог получать один и тот же ответ (неважно, правильный он или нет).
Но так как добавление подобной функциональности требует переделок уже используемых систем и может быть неинтересно массовому пользователю (например, при работе с обычным текстом), мне захотелось попробовать, если не обойти данную проблему, то хотя бы максимально её нивелировать, чтобы ИИ-помощник можно было использовать при разработке программного обеспечения с гарантированным положительным результатом (который обычно заключается в экономии времени на выполнение задачи).
Для написания кода я использую VSCode с плагином Cline и MCP-сервером Context7.
До этого пробовал использовать плагин RooCode (это форк Cline с расширенным набором режимов работы и улучшенной кастомизацией промптов), но, как по мне, делать несколько режимов работы (архитектор, программист, тестировщик и т. д.), которые различаются только дополнительными промптами, - это неоправданно сильно усложняет настройку подобных инструментов и отнимает много времени и сил от непосредственного написания кода, так как приходится отлаживать промпты режимов работы вместо решения своей основной задачи.
Выбор конкретной модели для работы не принципиален. По крайней мере меня устроило качество и Qwen, и GPT, и Gemini, и все они генерируют примерно одно и то же, но так как из-за отсутствия воспроизводимости результатов их между собой сравнивать не получится (только статистика), и, на мой личный взгляд, результаты работы гораздо больше зависят от правильной постановки задачи, чем от выбора версии нейросети, поэтому я остановился на qwen3-coder как самой дешёвой.
Эксперименты ставил на своём проекте Trusted-CPP, (бывший Memsafe), который реализует безопасную работу с памятью для C++, но сейчас я решил расширить исходную концепцию и реализовать безопасное программирование на основе гарантий для C++ с сохранением обратной совместимости.
Решалась задача по переводу системы сборки проекта с NetBeans на CMake, которая должна выполнять сборку плагина для Clang в виде динамической библиотеки и исполняемого файла для юнит-тестов с использованием библиотеки Google Test Framework. Причем в процессе выполнения тестов несколько раз вызывается компилятор Clang с загрузкой плагина статического анализатора. Другими словами, задача не надуманная и по сложности далеко не Hello World.
Важная принципиальная особенность всех рассуждающих моделей заключается в их способности генерировать последовательные, логически связанные шаги для решения сложных задач. Однако подобные рассуждения являются лишь имитацией размышлений, лишены реального понимания задачи и потому подвержены различным ошибкам и галлюцинациям. Логика модели может легко "сломаться" даже от незначительного изменения формулировки, а один и тот же вопрос, заданный разными словами, может привести как к правильному ответу в одном случае, так и к полной бессмыслице - в другом.
Формирование цепочки шагов (Chain-of-Thought) организовано как итеративный цикл, который завершается в следующих случаях:
Логическое завершение (генерация стоп-токена) - модель обучалась на миллионах текстов, которые заканчиваются специальным невидимым токеном [EOS] (End-of-Sequence), и когда модель генерирует полный ответ, вероятность того, что следующим токеном должен быть [EOS], становится очень высокой - выше, чем у любого другого токена.
Достижение цели - это похоже на логическое завершение, но только в контексте текущего цикла рассуждений: когда есть описание задачи, ее пошаговое решение и финальный ответ, статистическая вероятность продолжения той же цепочки рассуждений резко падает, поэтому модель с большей вероятностью сгенерирует [EOS].
Технические (внешние) прерывания цепочки рассуждений:
Достижение максимального количества токенов, которое может сгенерировать модель. Даже если логическое завершение не наступило, а лимит достигнут, цикл рассуждений прерывается принудительно, что защищает LLM от зацикливания и бесконечной генерации.
Стоп-последовательности (stop_sequences) - это конкретные слова или фразы, при генерации которых цикл должен немедленно остановиться; их часто используют в диалоговых системах, чтобы модель не начала генерировать ответ за пользователя.
Из-за того, что LLM строит рассуждение в итеративном цикле, где каждый последующий шаг опирается на все предыдущие, самым важным условием корректной работы является своевременный выход из этого цикла.
Причем я считаю, что ошибки первого рода вполне допустимы, тогда как ошибки второго рода следует всячески избегать, то есть остановка цикла рассуждений без достижения положительного результата значительно лучше, чем галлюцинации или генерация ответа, основанная на неверных исходных данных, полученных на одном из предыдущих этапов.
В связи с этим для более качественного применения LLM в разработке ПО я считаю принципиально важным сделать следующие настройки:
Примеры (описание) настроек приведены для плагина Cline в среде VSCode.
Установить параметр Reasoning effort (reasoning_effort) на самый минимальный уровень, чтобы уменьшить глубину и сложность рассуждений, которые модель использует при генерации ответов. Это не только повышает скорость работы LLM и экономит токены, но, что самое важное, модель значительно меньше галлюцинирует.
Включить Focus Chain и установить для него минимальный интервал напоминаний (Remind Cline Interval) - в этом случае Cline будет генерировать список задач и периодически добавлять его в контекст с указанным интервалом, чтобы поток рассуждений не забывал текущий шаг решаемой задачи.
Можно еще включить Automatic Context Summarization, но у меня ни разу не было ситуации, когда я превысил бы окно контекста. Но для больших проектов эта настройка может быть критически важна.
Выглядят эти настройки вот так:
Эти опции значительно уменьшают "креативность" LLM и позволяет максимально концентрироваться на изначально поставленной цели. Генерируемые ответы перестали "зацикливаться" при поиске правильного решения и устранении несуществующих ошибок (как в этом примере), хотя иногда рассуждения стали останавливаться даже при наличии ошибки, как в этом случае:
Но это значительно экономит время и деньги, ведь не приходится искать в истории, в какой момент все пошло не так, чтобы откатить внесенные изменения, а заодно и не "кушает" денежки провайдеров на бесполезные запросы. И если раньше часто бывало, что LLM "зацикливалась" и останавливалась только по достижению ограничения на количество повторных запросов, то сейчас "зацикливания" не возникло ни разу.
И такое поведение в тысячу раз лучше, чем в случае генерирования бесполезного мусорного кода, так как сразу понятно, что проблема ИИ была идентифицирована ошибочно, и достаточно вручную уточнить источник ошибки, чтобы направить дальнейшие рассуждения ИИ в правильном направлении.
Хоть их и немного, но все они очень важны! И самое важное правило при программировании с ИИ - всегда в обязательном порядке в самом начале задачи использовать режим планирования!
Это значительно экономит время, так как не требуется откатывать неправильные или ненужные изменения (например, неправильное определение причины ошибки и последующее исправление работающего кода).
Также рекомендую в режиме планирования несколько раз прогнать один и тот же промпт, чтобы понимать, на какие шаги LLM разбивает поставленную задачу. Это бывает особенно полезно, когда разработчик имеет мало опыта в текущей задаче, так как её декомпозиция на более мелкие этапы помогает лучше понять предметную область, например, как в моем случае для промпта упрости и оптимизируй систему сборки:
И только после уточнения всех деталей текущей задачи можно переключаться в режим выполнения (Act).
Через несколько итераций или подходов вы заметите, что часто приходится вводить одну и ту же информацию, например, о стиле кодирования, добавлять те или иные ограничения или уточнять назначение папок. Эта информация - кандидат для файла AGENTS.md, которую можно добавлять в контекст запроса буквально нажатием пары клавиш.
В самом начале пришлось немного туго, так как приходилось реально шаманить с промптами в надежде случайно получить положительный результат. По нескольку раз откатывал сделанные изменения, чтобы повторить один и тот же промпт с разными настройками и оценить их влияние на качество кода.
На всякий случай сохранил в истории коммитов несколько этапов (итераций) для оценки прогресса.
Первичная версия система сборки проекта на cmake с помощью LLM / GitHub
Упрощение системы сборки cmake с помощью LLM · GitHub
Оптимизация системы сборки cmake с помощью LLM · GitHub
Ручное исправление тестов после добавления опции компилятора -O3 · GitHub
Итоговая версия системы сборки с помощью CMake · GitHub
Ручное исправление тестов потребовалось после того, как ИИ на команду для упрощения и оптимизации системы сборки добавил ещё и оптимизацию по скорости -O3, после этого из-за более быстрого выполнения цикла стал фейлиться один тест с конкурентным доступом к одной и той же переменной из разных потоков (циклы стали выполняться очень быстро, и для их завершения стало хватать одного кванта системного потока). Пришлось увеличить на порядок число итераций цикла, чтобы поведение теста осталось прежним, как и до оптимизации по скорости.
Последние четыре (хотя по факту три) коммита, это проверка модели на способность рефакторинга существующего кода. Перед каждым из этапов оптимизации сборки вся история общения полностью удалялась и анализ перед рефакторингом начинался "с чистого листа".
В конечном итоге всё устаканилось, и я для себя сформулировал следующие эмпирические правила разработки с помощью ИИ:
Всегда использовать режим планирования - это значительно экономит время, так как не требуется откатывать неправильные или ненужные изменения (например, неправильное определение причины ошибки и последующее исправление работающего кода).
Один и тот же промпт в режиме планирования запускать несколько раз. Это позволяет выявить потенциально проблемные места, которые могут остаться незамеченными. Данный пункт принципиально важен в случае слабого погружения разработчика в тему конкретной задачи.
ИИ должен работать только с одной задачей, либо ему требуется в явном виде указывать приоритеты исправления проблем и сразу прерывать рассуждения, чтобы исправить нужное утверждение (цель), не надеясь на самостоятельное разрешение ситуации LLM.
По факту выходит, что вайб-кодинг, это то же самое программирование, но только не непосредственное написание кода, а программирование алгоритма решения задачи (создание промпта), чтобы в результате получить правильное поведение ИИ с ожидаемым результатом.
В результате мне всё-таки удалось словить вайб, когда компьютер работает за тебя, а ты только периодически смотришь статус выполнения поставленной задачи и параллельно читаешь статьи в интернете, переписываешься или занимаешься чем-то ещё.
И хотя основную часть времени я потратил на выбор оптимальных настроек плагина, что заключалось в анализе неудачных запросов и попытке разобраться в причинах их возникновения, чтобы минимизировать вероятность появления подобного в будущем. Но даже с учетом этого мне удалось существенно сэкономить время на данную задачу (вручную я бы точно потратил несколько дней, а тут всё удалось сделать за пол дня, причём в расслабленном режиме с параллельной фиксацией материалов для данной статьи).
Плюсы:
Задача была успешно сделана (переделка системы сборки)
Время на выполнение задачи было потрачено на порядок меньше, чем в случае ручной настройки (так как я в CMake не разбираюсь)
Приобрёл опыт настройки ИИ-помощника, который обобщён, письменно зафиксирован и опубликован в виде статьи :-)
Мнусы:
Раньше я не разбирался в настройке CMake, и сейчас не разбираюсь в этом инструменте. Наверное, если бы я потратил время на ручную доработку системы сборки, то получил бы некоторый опыт, но это разовая работа, которую вряд ли мне потребуется делать в будущем. А даже если и потребуется, то 300-500 рублей на оплату запросов к облачной LLM - не такие уж большие деньги, чтобы не забивать голову лишней информацией, которая не помогает в достижении основной цели проекта.
За более чем три десятка лет в разработке ПО я успел пообщаться со многими программистами, и многие (включая меня) немного перфекционисты. В этом нет ничего удивительного, так как хороший код должен быть обязательно красивым и понятным, но из-за этого любые, даже правильные и аргументированные замечания во время проведения Code Review очень часто воспринимаются авторами в штыки.
И совсем другое дело, когда автором кода является ИИ (естественно, имеется в виду, что код полностью рабочий). Лично я, как программист, вообще не чувствую эмоциональной привязанности к коду, созданному ИИ, и любая критика в его адрес мне безразлична. И даже в случае получения отрицательной обратной связи она будет являться только дополнительным уточнением для промпта, но не вызывает какого-либо эмоционального дискомфорта, так как по факту будет обсуждаться сгенерированный код, к которому разработчик имеет лишь опосредованное отношение.
Конечно, это вовсе не означает, что код-ревью будет проходить проще и быстрее, но будет всегда психологически легче. Поэтому, хотя бы только ради душевного комфорта, иногда стоит использовать ИИ при написании кода (чтобы эмоционально отдохнуть от возможных наездов коллег по проекту).
Источник


![[Перевод] Как «приватные» VPN-расширения слили переписки 8 миллионов пользователей с ChatGPT и Claude](https://mexc-rainbown-activityimages.s3.ap-northeast-1.amazonaws.com/banner/F20250611171322266npMCv2GXbcEBQv.png)