С появлением в доступности LLM, которые пристойно пишут код, разработчики поделились на два лагеря. Основные тезисы таковы:

Первые считают, что LLM пишут код плохо, не умеют и не могут в специфику предметных областей и архитектуру кода, а быстрота генерации кода компенсируется длительной отладкой из-за допускаемых ошибок. И даже если код рабочий, то он неоптимален, и из-за специфики того, как работают LLM, всегда является средним, т.к. большинство кода в обучающей выборке именно такое.
И даже успешное применение LLM отбирает у программиста глубокое понимание проекта, над которым он работает: он больше полагается на ответы LLM и ее инструменты работы с кодом, чем на собственное знание codebase. Из-за этого, когда он перестает писать код сам, это снижает его скиллы как специалиста, низводя его до "говорильщика через рот", того самого замполита из анекдота, у которого "рот закрыл, рабочее место убрано".
Программисты, которые учатся кодить с применением LLM, — не учатся кодить, они учатся подбирать промты которые дают результат, решающий задачу. Кроме того, в начале обучения у человека очень мало критичности, и там, где опытный программист скажет нейронке "да ты несешь чушь, я не знаю точно как это работает, но явно не так", потому что у него уже есть опыт, который не стыкуется с обьяснениями LLM, новичок примет галлюцинации нейронки за чистую монету и спустя год такого "обучения" картина в его голове будет очень сильно отличаться от реальности.

Второй лагерь считает считает, что LLMки это наше новое будущее: подобно тому, как мы переехали с перфокарт на C, а с С на плюсы и другие языки высокого уровня (а то и декларативные DSL), следующий переезд заключается в еще одном повышении абстракции: теперь до уровня natural language.
Если раньше требовалось знать язык и вручную писать три вложенных цикла, то теперь можно просто сказать "напиши перебор всех элементов в трехмерном массиве на языке Х", причем Х меняется в зависимости от проекта, с которым сейчас работает программист, сегодня JS, завтра питон.
И будущее программиста — быть погонщиком нейросетей, потому что с развитием технологии все больше и больше задач будет отходить LLM, и в какой-то момент ручное написание кода будет выглядеть так же, как сейчас проект, целиком написанный на ассемблере: забавно, может быть даже круто для пет-проекта или в качестве разминки мозга, но совершенно неприменимо в коммерческой разработке и остается уделом сотни гиков.
Основной скилл программиста будет заключаться в том, чтобы правильно и точно ставить задачу, с нужными граничными условиями и выбирая правильные алгоритмы и способы реализации, а конкретное написание кода можно отдать на аутсорс: в сущности, это не очень отличается от скиллового сеньора-архитектора, который за клавиатуру берется только в редких случаях, а основная работа его заключается в выборе решений и путей, постановке задач и контролю за их выполнением.
Следовательно, сейчас для специалиста лучше запрыгнуть в поезд LLM и даже иметь там некоторые преференции из-за хорошего понимания процессов, чем наблюдать, как тебя обходит новое поколение, без глубоких знаний языка, но умеющее обращаться с нейросетями — просто потому что на единицу кода в большинстве проектов они обходятся дешевле, а что до оптимальности кода... Ну, компиляторам потребовалось пара десятков лет развития, чтобы по-настоящему приблизиться к оптимальности, и это не было поводом не использовать их 20 лет назад.

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

В этой статье мы займемся практикой, которая, как известно, лучший критерий истины.

Инструмент

На самом деле, сейчас развелось этих LLM-IDE — дофига. Начиная от бесплатного (теперь) копайлота, всякими Q от амазона, гигакодами сбера, которые ставятся как плагин в популярные IDE, и заканчивая полноценными IDE (ну, в основном перепиленными VS Code): Сodeium, Qodo, Blackbox, Continue, Cursor. Ну и у Jetbrains есть свой AI для их IDE. Есть даже опенсорсный aider, с которым можно общаться в консоли. Мне он понравился тем, что автоматически генерирует описания и коммиты на каждое изменение, но не понравился как-то общей бажностью. Есть еще Replit, который делает сразу проекты в целом. Я с ним немного поигрался, реально делает, но не разбирался, насколько он хорошо потом их дописывает. Подозреваю, настолько же, насколько любой другой инструмент, у которого под капотом anthropic/openai.

В итоге я использую платный Cursor ($20 в месяц). Но я отписался от платного плана ChatGPT (те же $20) и копайлота (когда он еще был платным за $10/месяц), потому что в целом чат в Курсоре позволяет спросить дорогую модель о чем угодно и так, а с мелкими тупыми вопросами справляется и бесплатный план ChatGPT, так что в целом вышел в ноль.
Но в целом, если не обращать внимания на платный план OpenAI за $200, подписки на все эти инструменты удивительно недорогие по сравнению с экономией времени, которую они приносят

Как это все выглядит?

Примерно вот так
Примерно вот так

Обычная VS Code, которая подхватывает большинство ваших плагинов и настроек. Но по Cmd+i открывается окно, в котором три вкладки — Chat, Composer, Bug finder. Как работает Bug finder, я так и не понял, потому что при открытии окна начинает бесконечно крутиться Computing changes, ну и фиг с ним.
Chat — это просто диалог с LLM, куда можно добавить в качестве контекста ваш код:

Например, его можно просто спросить о том, как работает код, не копируя файлы в окно ChatGPT как я делал раньше. Вот там где "Search сompleted (7 files)" — это он поискал в других файлах проекта fb::Message, сам и без напоминаний, т.е. он сможет ответить на вопрос о том, как использовать какую-то функцию из библиотеки, основываясь на ее реализации в файле этой библиотеки
Например, его можно просто спросить о том, как работает код, не копируя файлы в окно ChatGPT как я делал раньше. Вот там где "Search сompleted (7 files)" — это он поискал в других файлах проекта fb::Message, сам и без напоминаний, т.е. он сможет ответить на вопрос о том, как использовать какую-то функцию из библиотеки, основываясь на ее реализации в файле этой библиотеки

Composer — это как раз инструмент работы с кодом. У него можно выбрать модель:

В него можно добавить картинку, если вы хотите что-то сверстать (о верстке HTML поговорим позже), перетащить туда дополнительные файлы (примеры кода или доки), которые попадут в контекст и сменить режим normal/agent.

Normal/Agent — в первом режиме он просто пишет вам ответ и предлагает изменения в код, во втором он может сам ходить по файлам, искать в них что-то, запускать команды в консоли (например сборки или тесты) и получать их ответ.

После генерации кода, IDE подсвечивает измененные LLM строки (как в гите), позволяя применить все изменения или принять решение по каждому блоку отдельно.
После генерации кода, IDE подсвечивает измененные LLM строки (как в гите), позволяя применить все изменения или принять решение по каждому блоку отдельно.

Запуск команд нуждается в подтверждении человеком, так что автоматически он rm -rf / не запустит, если вы не проглядите (это можно отключить, "enable yolo mode" в настройках).

Работа в режиме agent: для создания папки с тестами он написал консольную команду, но ее надо было подтвердить вручную
Работа в режиме agent: для создания папки с тестами он написал консольную команду, но ее надо было подтвердить вручную

В настройках есть вкладка Docs:

Туда можно кинуть ссылку на доки какой-то специфичной либы, которую LLM не знает, или знает плохо, IDE ее скачает(и страницы, на которые она ссылается), проиндексирует, и потом в чате можно будет сослаться на нее через @ и Docs

Еще в настройках есть поле для ввода ваших правил:

У меня, например, там то, что надо в коде писать все на английском, а сообщения в чате писать на русском, без этого оно либо пыталось в лог писать на русском, либо текст в чате на английском. Правда, после добавления этого начало выдавать в конце сообщений что-то типа:

Спасибо, солнышко, но мне-то зачем ты это пишешь?
Спасибо, солнышко, но мне-то зачем ты это пишешь?

Пришлось добавить туда еще и "делай так, но не пиши об этом". Первое правило бойцовского клуба, да.

Еще курсор умеет в автоматическую генерацию описаний к коммитам.

Пишет он их, конечно, не очень. Но это все еще гораздо лучше чем "update", когда очень лень писать описание.

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

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

Примерно такое же я сейчас ощущаю с Cursor. ChatGPT, конечно, может писать код, но это скорее твой подчиненный на удаленке — ты ему пишешь письмо, копируешь туда кусок кода, и тебе приходит ответ с измененным куском кода, который ты вставляешь обратно, запускаешь проект, видишь, что что-то работает не так, копируешь коллеге кусок логов и все повторяется.
В какой-то момент у ChatGPT появился Сanvas (даже на русском есть описание), с которым стало возможно работать с этим "коллегой" в режиме расшаренного экрана, но это все еще ограничивалось одним файлом. Т.е. писать простой скрипт — офигенно, но как только проект вырастает до сколько-нибудь большого размера, все становится грустно.

Тот самый Сanvas
Тот самый Сanvas

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

И вот Cursor — это прям такой же прогресс по сравнению с ChatGPT, как ChatGPT по сравнению с Copilot.

Пробуем на реальных проектах

У меня было несколько проектов, которые я решил писать исключительно с помощью LLM:
1)Бот-тренажер для медиков в ТГ. Показывает тебе аудио/экг/вопрос и кнопки с ответом. Питон.
2)Бот-конвертер валют (тоже в тг). Ждет в личку или в чате сообщение с "100 евро" и реплаит на него с несколькими сконвертированными валютами. Питон.
3)Парсер БД DayOne, чтобы проставить дату паре сотен фотографий, у которых она почему-то отсутсвовала в EXIF. Питон
4)BLE-кнопка на ESP32, которая перелистывает страничку в читалке книжки, чтобы не тянуться рукой к телефону, когда я лежу на штуке для йоги. Си/ардуино
5)Контроллер замка с тг-ботом, который ждет в определенной группе сообщение "Open", чтобы открыть замок двери для керамического коворкинга. Си/ардуино
6)Кнопка для контроллера замка, которую можно жмякнуть из любого места помещения, чтобы эту дверь открыть. Си/ардуино
7)Камера на ESP32 которая присылает снимок в тг, чтобы не отправлять показания счетчиков вручную. Си/ардуино
8)Софт для задвижки на батарею. Си/ардуино
9)Планировщик типа ганта (Svelte/JS/HTML)

Два тг-бота на питоне

Первые два бота писались примерно по одинакой схеме: ты просто говоришь "а напиши мне бота" и описываешь функционал. Запускаешь. Проверяешь. Пишешь "не работает Х" или "не запускается, вот лог в консоли".

Когда это начинает работать, то возникает ощущение как в этой шутке:

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

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

Где-то на 30-40 килобайтах кода (я тестировал на питоне, с первыми двумя проектами эта граница была плюс-минус одинаковая) сложность костылей и подпорок возрастает настолько, что LLM начинает путаться в них сама (неудивительно, я попытался осознать код и тоже запутался).
Ты ей говоришь "вот ты скачиваешь курсы валют, тебе не надо это делать каждый раз при старте, положи их в кеш вместе с временем скачивания и только если разница во времени больше пяти часов, качай заново", он что-то делает, радостно рапортует, но это не работает. Ты говоришь что не работает, он тебе радостно отчитывается, что нашел и исправил ошибку, но оно все еще не работает. И так можно десяток итераций играться. А задача-то реально простая для него — на чистом проекте результат работает зачастую с первого раза, там реально 20 строк — скачать, сериализовать, сохранить, загрузить, десериализовать, сравнить время.

Прям на модельном примере можем увидеть все минусы накопления технического долга — функционал, который раньше требовал пяти минут работы джуна (LLM) с небольшим код-ревью техлида (меня), теперь требует получаса работы миддла, а то и сеньора.
Это даже немного пугающе на самом деле — то, что я раньше видел в больших проектах, повторяется у меня на столе в масштабе 1:100.
Мне прям хочется, чтобы этот опыт испытали все отрицатели техдолга, которые очень любят тезис "главное, чтобы фичи работали, а на красоту кода бизнесу плевать".

В общем, то что получается в итоге, работает, но к дальнейшему развитию совершенно непригодно. Казалось бы, провал программирования с помощью LLM, закрываем статью, ждем рассуждающих моделей не за $200?

Нет.
Мы получили PoC:
1)за какие-то 3 часа времени
2)не используя никаких спецов, только свои навыки, и то уровня "шарящего продакта-мидла" — запускали код в консоли, копировали ошибки в окошко и проверяли работу с точки зрения пользователя.
Важнее было понимать, что именно мы хотим получить, чем то, как именно надо это кодировать.

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

Я оцениваю мои затраты на написание такого же кода (ну может чуть получше качеством) на 5-7 часов (но я не великий спец в питоне).
Если ходить за таким кодом на фриланс — то, наверное, 10-15к рублей. Т.е. $20 на курсор уже сэкономили или время или деньги.

Но пока "в режиме продакта" писать большие проекты не получится. Дописать обособленный кусок аналитики? Да. Подключаемый модуль "по примеру"? Да. Микросервис, который ходит в базу и выдает данные после небольшого препроцессинга? Да. PoC новой логики на страничке? Ну, в целом да. PoC целого проекта? Уже нет.

Можно попросить LLM отрефакторить этот код, скажете вы. Ну, типа, "ты крутой специалист по рефакторингу, вот перед тобой код, его надо привести в порядок".
Но это, как ни удивительно, не срабатывает. Проблема в не строчках кода и не в килобайтах текста, а в цикломатической сложности. И если у LLM на данный момент есть определенный предел, за которым она не может эффективно осознавать код, чтобы его редактировать, то очевидно, что она не сможет его осознать и чтобы отрефакторить.

Теперь-то все? Закрываю статью?

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

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

И это помогает — "проблема 30кб" перестала быть такой острой — проект вырос до 50кб и вполне поддается дописыванию дальше, но уже закончились идеи, что же туда добавить. (это я про второго бота — который конвертер валют).
Из минусов — вы уже должны представлять, по каким границам разбивать логику, и заранее понимать, нужен ли вам тот или иной функционал в коде, т.е. какие-никакие, а навыки программиста уже нужны.
С другой стороны — написание таких проектов это забавная тренировка архитектурных навыков (ну скорее микро-архитектурных, на уровне разбиения кода на модули), которая явно быстрее, чем писать это все самому и явно дешевле, чем тренироваться на боевых проектах (к которым вас еще никто и не допустит).

Посмотреть на первые два проекта:
1)Бот-тренажер, код первой версии, с самим ботом поиграться: https://t.me/auscultatio_bot
2)Бот-конвертер валют: код первой версии, с ботом поиграться: https://t.me/currvaconverter_bot

Заняли эти штуки... Ну, по 3-4 часа на первую версию и по 8-10 часов суммарно на окончательную вторую. Если писать вручную, моя оценка — х2-х3.

Парсер SQLITE DayOne

Dayone — это такой дневник для iOS с которого я некоторое время назад переехал в свое облако и надо было для сотни фотографий вытащить их координаты и время поста, потому что по какой то причине их не было в EXIF фоток.

Тут все получилось очень просто и легко: это одноразовый проект, задача которого сходить в Sqlite, взять по цепочке ключей название файла и дату-время и записать это в EXIF файла, чье название было в БД. Все возможные случаи поддерживать не требовалось, поэтому я просто писал в чат все возможные претензии, проверял, и снова писал.

От меня потребовалось только разобраться с форматом БД, потому что вряд ли бы LLM это осилила (точнее, ушло бы на это точно больше времени, чем мне повтыкать 10 минут в структуру).

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

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

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

Раньше такие проекты собирались копи-пастом с SO, но LLM и этот процесс смогла улучшить. В задачах перекладывания JSON LLM уже почти нет равных.

Пачка простых проектов на си

В си для эмбедеда умеет гораздо хуже, к сожалению.

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

Мне кажется, оно знает анекдот про "А у меня было еще столько идей!"
Мне кажется, оно знает анекдот про "А у меня было еще столько идей!"

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

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

Тут 10 скринов, я предупредил
И наконец сдалось.
И наконец сдалось.

Впрочем, когда дело не касается вот прям самого эмбедеда, а просто пишется какая-то логика на си, то все норм:

Впрочем, логика изначально была тут довольно простой.

В другой части оно надолго застрял на парсинге JSON: там была библиотека TG-бота, которая выдавала сырой JSON ответа, и оно никак не могло понять, почему же она выдает просто текст, а не отдельный элемент, несмотря на все отладочные выводы, в которых была видна строка json. Когда я уже психанул и сказал "ну распарсь этот json сам", то все получилось с первого раза.

Планировщик на Svelte/HTML

Помните, что в Cursor есть функция Docs? Вот тут-то она нам пригодится.
Тем более, что у svelte в документации есть раздел для LLM!

Ну, в целом эта документация — просто несколько файлов в Md, в которых с разной детализацией описана вся документация, это удобно, но ��икакой супер-инновации в этом нет.

Идею планировщика можно понять по этому скрину

Планировщик — это такая диаграмма ганта, но не в рабочих днях, а в абсолютном времени вплоть до минут, и без сложных зависимостей, просто один-два потока, но с возможностью изменения таймзоны в процессе (потому что часто для путешествий используется). У нас есть какие-то жестко закрепленные события (вылет самолета), и события-длительности, типа регистрации, поездки в аэропорт и сборов. И мы присоединяем вторые к первому и видим, во сколько нам надо начать собираться, чтобы успеть в аэропорт. Бонусом — медленно ползущая полоска текущего времени, чтобы видеть, насколько мы в графике в текущий момент (если мы все еще в такси, а полоска уже на "регистрации", значит что-то пошло не так).

Почему-то именно в таком виде я не нашел ни одного приложения, и захотел написать сам. Но вот сделать это с помощью LLM я не смог: на этой задаче она былинно слажала. Все хорошо, документация по svelte нормальная, документация по библиотеке пришлось покрутить руками, но тоже получилось, с JS проблем не возникло...

А вот с интерфейсом возникло.

Оказалось, что LLM — слепой часовщик программист. Она может делать какой-то интерфейс, но испытывает огромные трудности с сопоставлением внешнего вида интерфейса и кода. Нет, в современном HTML/CSS я тоже их испытываю, но я могу поиграться в отладчике хрома и почитать доки прицельно по каждой фиче, а LLM просто пуляет наугад. Задачи за пределами стандартных, условно "а теперь подвинь вот эту плашку чуть вправо" уже вызывают проблемы, потому живой человек делает это, основываясь на обратной связи:
— Так двигается? А так? Хорошо, а если через отступ другого элемента зайти? Ой, поехало остальное. Ладно, откатим. Может, положить в див? Ага, так лучше, но надо еще чуть-чуть подвинуть, потому что див теперь учитывает границу другого элемента... Вот, красота.

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

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

В итоге даже вот эта версия интерфейса потребовала много-много попыток, и делать это было довольно больно. Если бы проблемы были с кодом на питоне/жс, я бы просто написал его сам, но вот в HTML/CSS я умею совсем чуть-чуть, поэтому довел до хоть сколько-нибудь рабочего состояния и забил. Кстати, если вы фронтендер, который умеет в UI, и вам понравился концепт, то напишите мне, что ли, хочу сделать из этого что-то, что можно использовать (я могу даже денег дать).

Абсолютно та же проблема была с переводом картинок в текст: базово все получилось с первом попытки, и это заняло 10% времени, а вот задачи "а теперь сделай отступ вокруг текста, нет, чуть левее, и выровняй фотку по центру" заняли остальные 90%, и не потому, что они сложные, а потому, что LLM не понимает, как выглядит текущее состояние.

Окончательные выводы

1)В архитектуру LLM не умеет. Продумывайте разделение проекта на части заранее, относите новые фичи к какому-то классу в отдельном файле и удаляйте из контекста ненужные файлы. Вот если нужна статистика, прям указывайте на файл stats.py и давайте задачу писать в нем. Так оно не будет иметь возможности ошибиться.
Если межблочное взаимодействие — то кладите в контекст эти два файла, и больше ничего.

2)Вам нужны знания о том, как работает язык на котором вы пишите. Вам придется ревьюить код и говорить "это решение говно", без этого получится фигня.
И даже "у тебя код нечитабельный, сделай вот так, по правилу на каждой строчке" тоже иногда надо говорить

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

4)Хорошо работают примеры: берете кусок кода, переделываете его, не обращая внимания на запятые и ошибки линтера, просто чтобы он примерно показывал то, что вы имеете ввиду и тыкаете LLM носом в этот пример. Ошибки в коде LLM правит отлично, а вот какой именно код вам нужен, чтобы его было удобно сопровождать дальше — знаете только вы.
Наверное, в какой-то момент будет можно дотренировать модель на вашем стиле кода, чтобы таких проблем было меньше. С другой стороны — в этом проекте LLM подсказала мне пару решений, о которых я теоретически знал, но почему-то никогда не применял, а оказывается, это ощутимо экономит время и строки. Если бы LLM писал в моем стиле, то эти решения и не применил бы никогда.

5)Не давайте заполнять requirements.txt (или раздел библиотек в platformio.ini)!
LLM туда ставит старые версии, которые любят падать с очень невнятными ошибками из глубинных кишок библиотеки, которые не гуглятся, и о которых LLM ничего тоже не может сказать внятного. Если она добавляет библиотеки в requirements.txt, удаляйте версии, оставляйте просто названия, потом в конце разработки зафризите версии.

7)Пишите тесты. Тесты LLM пишет хорошо, надо просто описывать словами класс тестов, и потом править мелочи, это реально делает тесты менее нудными на порядок. Тесты хорошо спасают от того, когда LLM забывает что-то где-то поправить вслед за своими изменениями, уровня "реализацию изменил, в одном вызове функции изменения забыл учесть". LLM сама это поправит, если ее пнуть в нужном направлении вида "тест сломался, смотри". Я тоже делаю такие ошибки, когда что-то пишу, но как будто сильно реже.

8)Иногда вы просите LLM что-то исправить, и она делает не то, что надо. Вы уточняете запрос, она правит, и опять не то, и опять не то, и с каждым разом она делает все хуже и хуже или просто начинает бегать между 2-3 вариантов по кругу, так и не понимая что именно вы хотите. Насколько я понимаю, это происходит из-за того, что в последнем контексте слишком много ключевых слов, которые ведут ее не туда.

Тот самый снапшот, который был создан до работы по запросу, и к которому можно вернуться, если LLM пошла в процессе совсем не туда
Тот самый снапшот, который был создан до работы по запросу, и к которому можно вернуться, если LLM пошла в процессе совсем не туда

Тут помогает вернуться к снапшоту с первым запросом, который она не смогла сделать и переформулировать его более основательно, добавив в него все те уточнения, которые вы писали ей дальше

9)Избегайте сложных запросов, которые включают в себя сложные многоуровневые фичи или функционал из разных областей. Это работает в начале проекта, но становится плохоуправляемым когда кодовая база вырастает.

Условно, в начале проекта вы можете сказать "сходи в базу SQLITE достань оттуда название файла и дату и проставь в EXIF файла дату поста", но вот дальше лучше не перечислять в одном запросе "а теперь переименуй файлы в формат даты, добавь конвертацию из другого часового пояса, и убери из лога сообщения про EXIF", а делать это отдельными запросами, иначе велика вероятность, что она забудет какой-то пункт или просто сделает его на отъебись, потому что распылит "внимание" (насколько я понимаю, реально внимание, там есть какой-то механизм, который фокусируется на определенной части промпта).

Вряд ли оно сделает что-то плохое, скорее просто забудет про один-два пункта. Но может и запутаться в функционале, если там будут похожие пункты вида "отключи логи для записи в EXIF, но добавь логи про запись в БД"

10)LLM — слепой часовщик программист. Если вам нужен базовый интерфейс "вот страничка, на ней сделай 10 полей для ввода и кнопку сохранить, и выведи вот эти параметры, но не давай их изменять, и сделай это на твиттер-бутстрап", то она справится. Добавить туда еще десять полей — тоже без проблем. Но вот при необходимости поля эти подвигать, чтобы сделать красиво (я даже не говорю о pixel-perfect верстке, просто хоть сколько-нибудь красиво), вы столкнетесь с большими проблемами.

11) LLM плохо пишет комментарии. Я уже хихикал вот тут над этим: все в классическом стиле бесполезных комментариев. Еще очень часто вместо комментариев, что именно тут происходит (даже таких бесполезных как те, над которыми я хихикал выше), она пытается описать изменения: вместо "# повторная задержка" пишет в строке, которую поменял "# добавил тут повторную задержку". Замечательно, я и так вижу, что ты эту строку поменял, мне-то зачем в исто��ии комментариев потом читать что ты что-то добавил?

12)Периодически ломает README. Дело в том, что весь ответ LLM представляет собой md, и на него ориентируются парсеры курсора, чтобы понять, где текст в чате, а где код, который надо вставить в файле. Это работает в 99% нормально, пока вместо кода мы не просим сгенерировать тоже маркдаун, и это зачастую приводит к интересным последствиям.

13)Очень не хватает здоровой критичности к моим сообщениям у модели. Я могу что-то не увидеть в коде, и там где живой человек скажет мне "ты что, дурак, там в коде уже это есть", LLM ответственно пойдет что-то делать, и иногда сломает нужную функциональность. Тоже самое происходит, когда я через чур уверен, где баг: я пишу "у тебя баг в парсинге профилей, присылаются повторно", и LLM послушно идет ковыряться в парсинге, что-то правит, радостно отчитывается, а баг-то остался, потому что он не в парсинге, а в отправке. Хочется, чтобы в этот момент модель послала меня на фиг, и сказала "ты дурак штоле, вон у тебя в отправке фигня нарисована".

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Использовали LLM для программирования?
13.04%Нет, боже упаси, пишу все своими руками9
31.88%Иногда спрашиваю ChatGPT в его интерфейсе, как написать кусок кода22
37.68%Прошу ChatGPT писать мне несложные функции и/или скрипты26
17.39%Использую IDE c LLM постоянно12
Проголосовали 69 пользователей. Воздержались 11 пользователей.