Не так давно я сидел в пятницу вечером, смотрел на pull request, сгенерированный ChatGPT, и думал: ну всё, завтра стаскуют на ревью. К счастью, за год активной работы с LLM я выработал целый набор приёмов, после которых сгенерированный код спокойно проходит в прод. Рассказываю, что именно я делаю и как вы можете повторить то же самое.
Первое, что я научился делать, — это писать промпты не как в документации OpenAI, а как будто я объясняю задачу стажёру, который очень умный, но не знает контекста. Я описываю доменную область, ожидаемое поведение, крайние случаи, ограничения по памяти и времени, стиль проекта. Чем конкретнее промпт, тем меньше приходится переделывать. Раньше я кидал: «Напиши функцию для парсинга CSV». Сейчас я пишу: «Напиши Go-функцию, которая читает CSV с разделителем запятой, пропускает пустые строки, валидирует, что в третьем столбце — ISO-дата, и возвращает слайс структур. Учётный лимит — 5000 строк за раз». Разница колоссальная.
Второй приём — я никогда не беру код из LLM «как есть». Я всегда прошу модель не только написать решение, но и написать к нему юнит-тесты, объяснить, что будет происходить на граничных значениях, и указать потенциальные race conditions или утечки памяти. Обычно после этого у меня уже есть 70-80% того, что нужно, и я просто дорабатываю логику. К тому же тесты, сгенерированные моделью, часто ловят баги, которые я сам бы пропустил в спешке.
Третий важный момент — выбор модели и настройка температуры. Для генерации кода я всегда ставлю температуру на 0.1 или даже 0. Если я пишу бизнес-логику, где важна предсказуемость, я не могу позволить себе «креативность». А вот когда мне нужно придумать название переменной или написать док-комментарий — тогда температура может быть повыше. Я также заметил, что модели с большим контекстным окном (128k токенов) дают значительно лучший результат, если ты подкидываешь им фрагменты соседних файлов, чтобы они видели, какой стиль кода у тебя принят.
Четвёртое — я использую LLM как ревьюера, а не как автора. После того как я пишу код сам, я прошу модель: «Вот мой код, найди все места, где возможны panic, где я забыл закрыть ресурс, где нарушена идиоматика языка». Это работает как второй мозг, который не устаёт и не раздражается. Однажды модель нашла в моём Go-коде то, что я забыл отменить context, и это спасло от утечки goroutine в проде.
Пятое и, пожалуй, самое важное — я никогда не деплою сгенерированный код без человеческого ревью и без полного прогона тестов. LLM отлично справляется с «скелетом» решения, но ей часто не хватает понимания бизнес-контекста, архитектурных ограничений, требований безопасности. Я использую её как очень быстрого джуниора: она быстро пишет черновик, а я решаю, годится ли это в бой. И да, я всегда гоняю статический анализатор поверх сгенерированного кода — linters находят то, что модель может пропустить.
В итоге моя формула такая: конкретный промпт с доменным контекстом плюс запрос на тесты и edge cases, низкая температура, статический анализ, человеческое ревью. После этого сгенерированный код не только не стыдно деплоить, но и он реально экономит мне 30-40% времени на рутинные задачи. LLM — это не волшебная кнопка «напиши код», а мощный соавтор, который требует от тебя дисциплины и понимания того, что ты делаешь.
А вы как работаете с LLM в повседневной разработке? Есть ли у вас свои хитрости, которые реально повышают качество сгенерированного кода до продакшн-уровня? Делитесь опытом, интересно услышать, как другие команды справляются с этой задачей.
Первое, что я научился делать, — это писать промпты не как в документации OpenAI, а как будто я объясняю задачу стажёру, который очень умный, но не знает контекста. Я описываю доменную область, ожидаемое поведение, крайние случаи, ограничения по памяти и времени, стиль проекта. Чем конкретнее промпт, тем меньше приходится переделывать. Раньше я кидал: «Напиши функцию для парсинга CSV». Сейчас я пишу: «Напиши Go-функцию, которая читает CSV с разделителем запятой, пропускает пустые строки, валидирует, что в третьем столбце — ISO-дата, и возвращает слайс структур. Учётный лимит — 5000 строк за раз». Разница колоссальная.
Второй приём — я никогда не беру код из LLM «как есть». Я всегда прошу модель не только написать решение, но и написать к нему юнит-тесты, объяснить, что будет происходить на граничных значениях, и указать потенциальные race conditions или утечки памяти. Обычно после этого у меня уже есть 70-80% того, что нужно, и я просто дорабатываю логику. К тому же тесты, сгенерированные моделью, часто ловят баги, которые я сам бы пропустил в спешке.
Третий важный момент — выбор модели и настройка температуры. Для генерации кода я всегда ставлю температуру на 0.1 или даже 0. Если я пишу бизнес-логику, где важна предсказуемость, я не могу позволить себе «креативность». А вот когда мне нужно придумать название переменной или написать док-комментарий — тогда температура может быть повыше. Я также заметил, что модели с большим контекстным окном (128k токенов) дают значительно лучший результат, если ты подкидываешь им фрагменты соседних файлов, чтобы они видели, какой стиль кода у тебя принят.
Четвёртое — я использую LLM как ревьюера, а не как автора. После того как я пишу код сам, я прошу модель: «Вот мой код, найди все места, где возможны panic, где я забыл закрыть ресурс, где нарушена идиоматика языка». Это работает как второй мозг, который не устаёт и не раздражается. Однажды модель нашла в моём Go-коде то, что я забыл отменить context, и это спасло от утечки goroutine в проде.
Пятое и, пожалуй, самое важное — я никогда не деплою сгенерированный код без человеческого ревью и без полного прогона тестов. LLM отлично справляется с «скелетом» решения, но ей часто не хватает понимания бизнес-контекста, архитектурных ограничений, требований безопасности. Я использую её как очень быстрого джуниора: она быстро пишет черновик, а я решаю, годится ли это в бой. И да, я всегда гоняю статический анализатор поверх сгенерированного кода — linters находят то, что модель может пропустить.
В итоге моя формула такая: конкретный промпт с доменным контекстом плюс запрос на тесты и edge cases, низкая температура, статический анализ, человеческое ревью. После этого сгенерированный код не только не стыдно деплоить, но и он реально экономит мне 30-40% времени на рутинные задачи. LLM — это не волшебная кнопка «напиши код», а мощный соавтор, который требует от тебя дисциплины и понимания того, что ты делаешь.
А вы как работаете с LLM в повседневной разработке? Есть ли у вас свои хитрости, которые реально повышают качество сгенерированного кода до продакшн-уровня? Делитесь опытом, интересно услышать, как другие команды справляются с этой задачей.