Комментарии 16
Какие у Вас выводы после разработки компилятора с ИИ?
С ИИ я могу взяться за проект, который в одиночку раньше вряд ли бы потянул. Но за архитектурой приходится следить самому. В Nova Oracle я слишком долго принимал задачи по одной и не замечал, как расползается общая конструкция.
С выводом типов так и вышло: месяц мы проверяли, что поведение не изменилось, а старый механизм, который собирались убрать, оставался на месте. Вовремя я этого не заметил.
Отсюда мой вывод: нужна более чёткая, декларативная методология. Заранее описать, какой результат нужен и как его проверить, чтобы выполнение задачи меньше зависело от того, как агент понял очередной разговор. Такую методологию я сейчас собираю на опыте Nova: https://github.com/unitcraft/ai-dev-methodology
С ИИ я продолжу работать, с ним в разработке можно делать то, что раньше было недоступно. Но в большом проекте агенты пока сильно спотыкаются и регулярно нарушают даже явно записанные правила и соглашения. Записать правила и довериться агентам пока не получается: у меня держатся только те правила, которые CI проверяет при каждой сборке.
У вас Nova - это компилятор. У меня Nova - 2д графический бэк😅
Приятно познакомиться
Если вы ведёте с агентами большой проект: случалось ли, что задание агента выполнено для галочки, тесты зелёные, а нужного результата нет? Какую проверку вы добавили после этого?
Помню прошлую статью и вижу, что работа над ошибками проведена. Но, как мне кажется, проведена недостаточно.
В новом проекте у вас ограничение на размер файла - тысяча строк и объявлено, что модуль - это директорий. Это лучше, чем тридцать тысяч в файле что было раньше, но... Ведь это не решает проблему... Ограничение на размер файла/модуля должно, помимо прочего препятствовать появлению божественных объектов, но с таким малым размером файла это приводит к тому, что агенты просто начинают раскладывать код божественного объекта по разным файликам. От раскладывания по файликам анализ клубка зависимостей только усложняется, границы не проводятся. В частности модуль check - это 21 тысяча строк рабочего кода с запутанной ответственностью.
У вас довольно сложная и продуманная система управления разработкой, но... она очень тяжёлая. Много источников правил, которые хорошо если не противоречат друг другу (а они противоречат), записанная история разработки (которая вместо того, чтобы сделать хорошо провоцирует агента сохранять устаревшие решения). Агенты получают кучу лишней информации. Агенту сложно ориентироваться. В частности у агента есть три способа сообщить о баге/находке/недоработке. Это ровно на два больше чем должно быть. Не дело исполнителя фичи решать, блокирует найденная проблема релиз или нет.
Агентам предписано соблюдать спецификации, но проект вырастает из штанишек, а спецификации не пересматриваются. Это, кстати, основная проблема SDD. Спецификации тупо не поспевают за разработкой. История и спеки не так важны, как текущее состояние проекта. Его нельзя прибить гвоздями. Агент силиться уложить код в спеки, получается плохо, код начинает противоречить спекам, агент мямлит, ну мол пук-среньк, я старался... Разработчик недоволен, агенту стыдно.
Если агент не хочет добавлять новый тип, предпочитая работать только с целочисленными... На это есть причина! Возможно, добавление нового типа в текущей архитектуре переусложнено. Если это происходит регулярно, проблема определённо есть. Надо разобраться.
История про починку бага с гонкой тоже интересна. Если баг не получается пофиксить с первого раза, проблема глубже и лежит скорее всего на уровне переусложнённой архитектуры. Нужно разобраться в каком месте код сложно поддаётся анализу и перебрать это место. Оно определённо есть.
Что по существу...
Вы спросили "Случалось ли, что задание агента выполнено для галочки, тесты зелёные, а нужного результата нет?". Разумеется. Есть простое правило. Агент стремиться сделать хорошо. Если он не сделал хорошо, значит не были созданы условия, чтобы сделать хорошо. Вместо того, чтобы обвешивать его дополнительными правилами и ограничениями, надо разобраться, почему он счёл выполнение работы нецелесообразным. Возможно выполнение задачи сложнее, чем планировалось, возможно, последствия реализации не такие простые как вам кажется. Возможно, агент просто не понимает, чего от него хотят. Не понимает, что из запланированного будут проверять и в каком объёме спека должна быть реализована на текущем этапе разработки.
Вы спросили "Какую проверку вы добавили после этого?". В данном случае, я бы скорее задался вопросом, не стоит ли какую-то проверку убрать, а какое-то правило ослабить.
Спасибо, что посмотрели исходники и сравнили подходы с прошлой статьей.
С размером файла согласен: лимит в тысячу строк не мешает разложить один большой объект по двадцати файлам, и проверка зависимостей между модулями этого не ловит. check надо смотреть по связям и состоянию, число строк тут мало что говорит.
Процесс действительно тяжёлый: реестр, followups и учёт упрощений появлялись под разные задачи, и исполнителю приходится выбирать, куда нести находку. Согласен, что от него нужны воспроизведение и последствия, а блокирует ли это выпуск, решаем мы с интегратором (тоже агент ИИ).
Спецификация у меня — журнал решений, и решения пересматриваются, когда реализация упирается в требование. Можно согласовать меньший объём и явно отказывать в неподдержанном. С интерполяцией претензия была в том, что компилятор молча делал из дробного целое, а тест этого не видел.
С гонкой согласен: семь попыток наугад были ошибкой, и порог 30 из 30 отсеял их все. Причину нашла диагностика (очередь использовалась после освобождения памяти), дальше исправление заняло полчаса. Но поставить агенту задачу так, чтобы он сам правильно провёл такую диагностику, — та ещё песня.
Что правила чего-то стоят, справедливо, в статье я это почти не разобрал. Но убирать их не выход: где правила нет, агент делает как получится. Как сказал мой товарищ, самое сложное — заставить агентов работать контролируемо. Агент нарушает даже непротиворечивые правила, и гарантию даёт только автоматическая проверка каждого из них. А правил в большом проекте тысячи, многие трудно формализовать. Всё в детерминированный скрипт не заложишь, а проверка силами агента недетерминирована: каждый запуск находит что-то своё.
Чтобы все же делать это более детерминировано, разрабатываю такой раннер https://github.com/unitcraft/ai-dev-methodology/blob/main/task-runner.md
Я вот так скажу. У меня тоже большой проект на 500 тысяч строк, если не больше. 3д редактор типа годот или юнити. Проблемы вроде тех, о которых вы пишите унас были ровно до тех пор, пока мы не пересели с планов и спеков на доску. Как только пересели - проблемы мистическим образом испарились. Я думал, дело в том, что модели стали сильнее. Но, судя по тому, что вы пишете, проблемы всё ещё с нами. Теперь думаю, что дело было именно в отказе от спеков.
Интересно, спасибо. А что у вас значит «доска»: задачи на канбане с короткими описаниями и критериями приёмки, а архитектура живёт только в коде? И как агент понимает, что задача готова и сделана правильно, если спеков нет?
У языка, правда, особый случай: спецификация здесь сама часть продукта. Пользователь должен знать, что делает каждая конструкция, а два компилятора, в моем случае, должны отвечать одинаково. Но планы у меня действительно разрослись, и вести работу агентов через доску, а спецификацию оставить только для самого языка, выглядит, разумно.
Сейчас я разрабатываю такую методологию: https://github.com/unitcraft/ai-dev-methodology/blob/main/methodology.md. Агенты по ней уже неплохо работают сами, но чтобы результат был стабильным, нужен детерминированный контроль. Для этого я и делаю раннер, он описан там же.
Задачи на канбане, да. С описаниями. Критерии приёмки там есть, но я их не уточняю. У меня в инструкции по пользовании доской написано туманное "карточка должна иметь понятный проверяемый критерий закрытия". То есть карточка "ускорить проект" правилам не соответствует. Архитектура у меня размазана. Что-то действительно живёт в архитектурных документах, что-то существует в виде umbrella на доске. Их все пишет сам агент. В проекте есть ровно один архитектурный документ, который я написал своими руками - описал модель интеропа и управления временем жизни объектов движка. Но я не то чтобы требую их соблюдать. Я держу их как ориентиры. Критерием истины в любом случае считается код.
У меня процесс разработки очень простой. Я в принципе на сложные пайплайны смотрю с изрядным удивлением, скепсисом и недоверием. Если я хочу большую фичу, я сначала провожу архитектурную консультацию, по её результатам агент нарезает карточки. Чё он там в критериях приёмки пишет - я ни сном ни духом. С карточками я иду ко второму агенту, спрашиваю у него, всё ли ему понятно. Бывает, что не понятно. Тогда мы уточняем. Когда всё понятно, просто говорю копать от забора и до обеда. Под это дело у меня на доске две колонки заведены Blocked и Ready, чтобы агент в порядке выполнения не путался. Вот собственно и весь пайплайн. Если потом оказывается, что что-то не готово... Ну... смотрим, что не готово и доделываем. Обычно готово.
Знаете... Я таки думаю, если бы я писал компилятор, я бы расчехлил TDD. У меня было бы много маленьких сниппетов кода, которые должны компилироваться, образовывать правильные деревья и отдавать правильный вывод. И уже гораздо позже, когда конструкции устаканятся, я бы уже натягивал на то, что получилось спецификацию.
Но я счастливый человек, я не пишу компиляторов :)
Спасибо, что так подробно расписали. Особенно понравился приём со вторым агентом, который до начала работы проверяет, всё ли ему понятно в карточках. Это дёшево и снимает часть недопониманий ещё до кода, возьму на заметку.
С TDD для компилятора согласен, у меня примерно так и устроено: у Carina около 16 тысяч строк тестовых фикстур, а корпус примеров прогоняется обоими компиляторами, и результаты сравниваются. Но одних тестов мало, это видно по эпизоду с интерполяцией. Тест проверял только целые и был зелёным, а компилятор молча превращал в целое всё остальное. Поймали это по спецификации: там написано, какие типы можно подставлять.
Ваш язык будете использовать только вы (и то только первые пару месяцев), как и 99% самописных языков - и это нормально, свой язык это априори хобби проект.
Но вы украли у самого себя процесс написания компилятора, гору знаний о куче предметных областей от парсинга до работы железа и реализации оптимизаторов кода. Вместо того чтобы пройти этот путь самому и на порядки прокачать экспертизу в практически любом существующем ЯП вы просто попросили черный ящик сделать что-то что ведет себя как компилятор и выглядит как компилятор.
Зачем люди делают LLM-ками круды на работе я понимаю, а зачем отдают на аутсорс процесс творчества предназначенный в первую очередь для них самих - не понимаю.
Что языком буду пользоваться в основном я, вполне возможно, но для меня это не главное. Это хобби, а хобби бывают и дорогие, и трудоёмкие. Мне интересен сам процесс.
Творчество при этом никуда не делось, оно сместилось. Чтобы спроектировать язык, всё равно нужно разбираться во всех его областях. Отдать агенту на аутсорс задачу такого масштаба не получится: «написал один промпт и получил Counter-Strike, только лучше» бывает только в маркетинге ))) Но не исключаю, что такое может быть в перспективе. Агенты все же становятся более умными и более быстрыми.
Язык я проектирую сам, а пишу вместе с агентами. Они сильно поднимают производительность: в одиночку такой проект занял бы годы и очень вымотал бы и умственно, и эмоционально.
Архитектуру Carina мы с агентами разбирали по rustc, Go, Roslyn, Zig и другим компиляторам, решения там мои. Последнее слово и проверка того, что получилось, за мной, иначе я не заметил бы ни запасной вывод, ни сужение интерполяции. Знаний о компиляторах у меня заметно прибавилось: получился экспресс-курс «пять лет за пять месяцев», и это очень интересный и вдохновляющий опыт.
И есть ещё одна цель: понять, как заставить агентов вести большой проект контролируемо. Про это и статья, и это нужно мне для проектов на основной работе.
Потому что это круто... Знаете, какую вы экспертизу общения вы получаете, когда реализуете такую огромную систему. Это ж охренеть какое колдунство - заставить агента делать то что вам надо месяцами. После этого вы уже все что угодно собрать на коленке можете
Спасибо больше! Точно подмечено: колдунство и есть 🙂 Самое ценное в таком проекте - умение добиваться от агентов предсказуемой работы на длинной дистанции. Это переносится на любой проект. Но думаю, мне придется написать отдельный продукт, который будет работать по методике https://github.com/unitcraft/ai-dev-methodology/blob/main/methodology.md , что бы колдунство превратить в реальную автоматизацию разработки. И проект этот будет на Nova )))
Продайте мне этот язык как целевой при реализации проекта с помощью LLM
Попробую. В Nova я хочу совместить удобство написания кода с проверками, которые помогают доверять результату работы агента. Параллельная работа обходится без async/await, задачи выполняет M:N рантайм. При этом компилятор проверяет, какие данные можно передавать между задачами и совместно изменять.
Работу с ресурсами контролирует consume: ресурс нужно потребить или передать дальше, повторное использование после потребления запрещено. Для таких типов с методом @cleanup компилятор делает освобождение ресурса при выходе из области видимости автоматически.
Через контракты можно записать требования к аргументам и результату функций (методов). Там, где возможно, они доказываются статически на этапе компиляции; остальные обычные контракты проверяются при выполнении, включая релиз. Собственные эффекты позволяют описать операции приложения и выбирать их реализацию через обработчики, в том числе для тестов без написания дополнительных фреймворков.
Для работы с LLM я рассчитываю именно на это сочетание: больше ошибок агент сможет исправить по результатам проверок ещё до моего ревью.Выстрелы себе в ногу запрещает сам язык Nova.
Агенты уже пишут на Nova по материалам репозитория. Даже бесплатная модель Big Pickle написала ядро модуля BigInt (https://github.com/nv-lang/nova-bignum/blob/main/src/bigint/core.nv) для пакета чисел произвольной точности сама, и тесты прошли. Это говорит о том, что спецификация и синтаксис языка не являются перегруженными.
Пока это альфа с известными ошибками компилятора и недоработками. Для небольшого эксперимента с агентом попробовать можно, для продакшена конечно надо дорабатывать.

Можно ли написать язык программирования с ИИ? Опыт Nova: первый компилятор зашёл в тупик, второй собрал себя сам