С появлением в доступности 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, куда можно добавить в качестве контекста ваш код:
Composer — это как раз инструмент работы с кодом. У него можно выбрать модель:
В него можно добавить картинку, если вы хотите что-то сверстать (о верстке HTML поговорим позже), перетащить туда дополнительные файлы (примеры кода или доки), которые попадут в контекст и сменить режим normal/agent.
Normal/Agent — в первом режиме он просто пишет вам ответ и предлагает изменения в код, во втором он может сам ходить по файлам, искать в них что-то, запускать команды в консоли (например сборки или тесты) и получать их ответ.
Запуск команд нуждается в подтверждении человеком, так что автоматически он rm -rf / не запустит, если вы не проглядите (это можно отключить, "enable yolo mode" в настройках).
В настройках есть вкладка Docs:
Туда можно кинуть ссылку на доки какой-то специфичной либы, которую LLM не знает, или знает плохо, IDE ее скачает(и страницы, на которые она ссылается), проиндексирует, и потом в чате можно будет сослаться на нее через @ и Docs
Еще в настройках есть поле для ввода ваших правил:
У меня, например, там то, что надо в коде писать все на английском, а сообщения в чате писать на русском, без этого оно либо пыталось в лог писать на русском, либо текст в чате на английском. Правда, после добавления этого начало выдавать в конце сообщений что-то типа:
Пришлось добавить туда еще и "делай так, но не пиши об этом". Первое правило бойцовского клуба, да.
Еще курсор умеет в автоматическую генерацию описаний к коммитам.
Пишет он их, конечно, не очень. Но это все еще гораздо лучше чем "update", когда очень лень писать описание.
В целом, написанного выше достаточно, чтобы начать что-то делать в курсоре, можете поставить и поиграться, там есть триал, на неделю, что ли.
Я помню появление копайлота, который по сравнению с автокомплитом на базе методов из файлов и библиотек (и даже по сравнению с TabNine) казался какой-то магией: он волшебным образом предугадывал завершение строк настолько хорошо, что возникало ощущение, что эту строку щас написал коллега-программист.
Примерно такое же я сейчас ощущаю с Cursor. ChatGPT, конечно, может писать код, но это скорее твой подчиненный на удаленке — ты ему пишешь письмо, копируешь туда кусок кода, и тебе приходит ответ с измененным куском кода, который ты вставляешь обратно, запускаешь проект, видишь, что что-то работает не так, копируешь коллеге кусок логов и все повторяется.
В какой-то момент у ChatGPT появился С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.
Dayone — это такой дневник для iOS с которого я некоторое время назад переехал в свое облако и надо было для сотни фотографий вытащить их координаты и время поста, потому что по какой то причине их не было в EXIF фоток.
Тут все получилось очень просто и легко: это одноразовый проект, задача которого сходить в Sqlite, взять по цепочке ключей название файла и дату-время и записать это в EXIF файла, чье название было в БД. Все возможные случаи поддерживать не требовалось, поэтому я просто писал в чат все возможные претензии, проверял, и снова писал.
От меня потребовалось только разобраться с форматом БД, потому что вряд ли бы LLM это осилила (точнее, ушло бы на это точно больше времени, чем мне повтыкать 10 минут в структуру).
Удалось даже сделать генерацию картинок с текстом дневниковых записей, потому что я перееезжал, вообще-то, из текстового дневника в облако с картинками. Впрочем, записей там было меньше, чем фоток, поэтому я просто сделал из них картинки, положил им в мету дату и на этом успокоился.
Правда, убил я на это половину времени, потому что... потому что LLM не умеет в графику. Об этом я подробнее расскажу в пункте про HTML-приложеньку.
Если кратко: вот я даю задание "сделай мне картинку с мелким превью фотки записи и текстом записи под ней". LLM делает. Я хочу теперь уменьшить картинку, потому что по бокам много-много свободного места, и трачу следующие десять минут на то, чтобы обьяснить ей, что именно я хочу. Даже картинку скидывал в запрос, все равно не понимает. Быстрее было с самого начала поправить руками, но я же упертый. В итоге поправил сам, конечно.
Исключая вот этот пункт с превью записей, такая задача просто идеальна для LLM: пофиг на качество кода, поддерживать проект не надо, много бойлерплейт-кода (открыть бд, итерироваться, выбрать по ключу в другой таблице, сравнить), который легко описывается естественным языком, много специфичного кода вроде работы с sqlite, который я бы долго гуглил, а модель пишет сходу и правильно, потому что проект популярный, и так далее.
Раньше такие проекты собирались копи-пастом с SO, но LLM и этот процесс смогла улучшить. В задачах перекладывания JSON LLM уже почти нет равных.
В си для эмбедеда умеет гораздо хуже, к сожалению.
Постоянно пытается добавить что-то сверх описанного функционала, переусложняет или иногда вообще несет чушь: способен написать ESP.reboot(), и тут же после этой функции — сохранение конфигурации в файл. Если его спросить, "ты ваще нормальный?", ошибку скорее всего найдет, но изначально допускает.
Со всем, что касается непосредственно железа — лажает. Причем, почему-то постоянно хочет накрутить сверху каких-то дополнительных фич (чем совершенно не страдает в питоне). Просишь сохранить переменную в файле, он туда накрутит каких-то проверок, логов на каждый чих, вывод этой переменной на экран, и всего такого прочего, вплоть до загорания светодиода при чтении этой переменной, хотя первоначальная задача была очень простой и решается в две строки.
Еще оно адски путается в плюсах. В каком-то софте, который я адаптировал под что-то свое, была функция переменной, которая настраивалась в веб-конфигураторе. Я захотел сделать такую же, но для яркости светодиода, просто по образцу какой-то другой переменной. Но сделано это было на плюсах, и оно в нем запуталось (подозреваю, задача решалась проще, но я забил). Благо, оно после генерации умеет проверять ошибки линтера, так что это была история на 15 вариантов, которая шла минут, наверное, пять — оно писало вариант, видела ошибки линтера, писало снова, опять видело ошибки, и так далее. Потом сдалось и сделала без конфигуратор.
Впрочем, когда дело не касается вот прям самого эмбедеда, а просто пишется какая-то логика на си, то все норм:
Впрочем, логика изначально была тут довольно простой.
В другой части оно надолго застрял на парсинге JSON: там была библиотека TG-бота, которая выдавала сырой JSON ответа, и оно никак не могло понять, почему же она выдает просто текст, а не отдельный элемент, несмотря на все отладочные выводы, в которых была видна строка json. Когда я уже психанул и сказал "ну распарсь этот json сам", то все получилось с первого раза.
Помните, что в 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 вариантов по кругу, так и не понимая что именно вы хотите. Насколько я понимаю, это происходит из-за того, что в последнем контексте слишком много ключевых слов, которые ведут ее не туда.
Тут помогает вернуться к снапшоту с первым запросом, который она не смогла сделать и переформулировать его более основательно, добавив в него все те уточнения, которые вы писали ей дальше
9)Избегайте сложных запросов, которые включают в себя сложные многоуровневые фичи или функционал из разных областей. Это работает в начале проекта, но становится плохоуправляемым когда кодовая база вырастает.
Условно, в начале проекта вы можете сказать "сходи в базу SQLITE достань оттуда название файла и дату и проставь в EXIF файла дату поста", но вот дальше лучше не перечислять в одном запросе "а теперь переименуй файлы в формат даты, добавь конвертацию из другого часового пояса, и убери из лога сообщения про EXIF", а делать это отдельными запросами, иначе велика вероятность, что она забудет какой-то пункт или просто сделает его на отъебись, потому что распылит "внимание" (насколько я понимаю, реально внимание, там есть какой-то механизм, который фокусируется на определенной части промпта).
Вряд ли оно сделает что-то плохое, скорее просто забудет про один-два пункта. Но может и запутаться в функционале, если там будут похожие пункты вида "отключи логи для записи в EXIF, но добавь логи про запись в БД"
10)LLM — слепой часовщик программист. Если вам нужен базовый интерфейс "вот страничка, на ней сделай 10 полей для ввода и кнопку сохранить, и выведи вот эти параметры, но не давай их изменять, и сделай это на твиттер-бутстрап", то она справится. Добавить туда еще десять полей — тоже без проблем. Но вот при необходимости поля эти подвигать, чтобы сделать красиво (я даже не говорю о pixel-perfect верстке, просто хоть сколько-нибудь красиво), вы столкнетесь с большими проблемами.
11) LLM плохо пишет комментарии. Я уже хихикал вот тут над этим: все в классическом стиле бесполезных комментариев. Еще очень часто вместо комментариев, что именно тут происходит (даже таких бесполезных как те, над которыми я хихикал выше), она пытается описать изменения: вместо "# повторная задержка" пишет в строке, которую поменял "# добавил тут повторную задержку". Замечательно, я и так вижу, что ты эту строку поменял, мне-то зачем в истории комментариев потом читать что ты что-то добавил?
12)Периодически ломает README. Дело в том, что весь ответ LLM представляет собой md, и на него ориентируются парсеры курсора, чтобы понять, где текст в чате, а где код, который надо вставить в файле. Это работает в 99% нормально, пока вместо кода мы не просим сгенерировать тоже маркдаун, и это зачастую приводит к интересным последствиям.
13)Очень не хватает здоровой критичности к моим сообщениям у модели. Я могу что-то не увидеть в коде, и там где живой человек скажет мне "ты что, дурак, там в коде уже это есть", LLM ответственно пойдет что-то делать, и иногда сломает нужную функциональность. Тоже самое происходит, когда я через чур уверен, где баг: я пишу "у тебя баг в парсинге профилей, присылаются повторно", и LLM послушно идет ковыряться в парсинге, что-то правит, радостно отчитывается, а баг-то остался, потому что он не в парсинге, а в отправке. Хочется, чтобы в этот момент модель послала меня на фиг, и сказала "ты дурак штоле, вон у тебя в отправке фигня нарисована".