В данной статье под "вайбкодингом" понимается прохождение всего ЖЦ разработки проекта с использованием ИИ-агентов, без самостоятельного написания программного кода.
Большинство разработчиков так или иначе сталкивалось в своей жизни с рисованием UML диаграмм, или диаграмм в других нотациях. Рисование (проектирование) процесс весьма творческий, дающий много свободного пространства, много манёвров для ошибки и отнимающий много времени. Было бы классно, если бы ИИ мог генерировать диаграммы по текстовому описанию?
Давайте посмотрим, что он выдаёт при запросе на генерирование диаграммы
Пёстрое, красивое, с картинками. Но в презентацию такое не вставишь и коллегам не покажешь. Во-первых, непонятна нотация, во-вторых, даже самые передовые модели всё ещё лажают с текстом на изображениях.
Попробуем конкретизировать запрос, указав, что нужно генерировать именно UML диаграммы
Что это? Диаграмма состояний? С безымянным актором? Внезапно на английском и с развилкой не оставляющей выбора? (Yes/Yes) Думаю не стоит объяснять, насколько это плохо
На самом деле решение есть. Оно весьма нетривиально, но я им пользуюсь самостоятельно и агитирую всех, кто "страдает" ручным рисованием. Вместо просьбы сгенерировать картинку, просим у ChatGPT сгенерировать код. PlantUML код. Здесь не буду погружаться в детали реализации, и то, как он работает, на эту тему написано много статей.
Получили PlantUML код, скачали плагин для рендеринга под любой JetBrains IDE, или VS Code, вставили диаграмму. Профит! Еще и редактировать можно на ходу, что не нравится. Ну а для совсем ленивых (или не совсем разработчиков), есть онлайн версия рендеринга и редактора.
Дело в том, что для флоу описанного выше, выполняется много действий. Кто-то, увидев кривую картинку, сдастся сразу же, кого-то испугает необходимость работы с кодом, третий не сможет установить плагин, ну вы поняли.
А что, если все указанные выше действия, замести под капот, сделав их для конечного пользователя "чёрным ящиком", а в UI оставить только магию?
– Ты нам идею, а мы тебе диаграмму!
И при этом, заодно постараться использовать "трендовый" вайбкодинг на максимум, отдав всё исполнение полностью в руки ИИ.
Итак, нам нужно разработать сервис. С вайбкодингом, или без, жизненный цикл проекта всегда похож. С идеей разобрались.
Есть интерфейс, через интерфейс пользователь вводит запрос, выбирает тип диаграммы, отправляет запрос.
Далее, условный бекенд получает данные, отправляет его в LLM, получает PUML код, отправляет на серверный рендеринг, готовая диаграмма сохраняется у нас и выдаётся назад пользователю
Далее идёт выбор стека технологий. На фронтенд почти безальтернативно был выбран React + NextJS, на бекенд Typescript + NestJS, БД по стандарту Postgres. Разработка и развёртывание в докере.
Архитектура микросервисная, связка через брокер RabbitMQ, ИИ-агенту (codex) был задан жёсткий промпт на DDD архитектуру с EDD посредством шины EventBus.
Рендерить изображения будем через сервис plantuml "из коробки", для этого использовался образ plantuml/plantuml-server:jetty , хранение было решено организовать через Minio, редис для кеша, nginx как веб-сервер.
Сразу же был зарегистрирован домен, арендована дешёвая vds-ка, заведён репозиторий на гитхабе, поднята инфра с обвесами в виде grafana, prometheus, loki, просто, чтобы было.
Действительно, в процессе перечисления стека я забыл упомянуть ключевую деталь, ядро всей системы, без которого "магии" не будет. Это конечно же LLM, которая ответственна за генерацию PlantUML кода.
Здесь существует принципиальная развилка. Либо мы идём по пути связки по API с сильнейшими мира сего, либо пытаемся развернуть модель локально.
Сервис задумывался как бесплатный, и мне, изначально понятно, что на первых порах за него платить никто не будет. В то же время API запросы не самые дешёвые и с ростом аудитории, будет непременно увеличиваться их стоимость.
Выбор пал на развёртывание локальной LLM на той же ВДС-ке, где лежит основной сервис. Знающие люди уже на этом этапе почувствуют подвох (и неспроста). В пару кликов, дефолтная модель llama3:7B была развёрнута, был отправлен на неё запрос, спустя пару минут получен ответ, вставлен в редактор в соседнем окне, и о чудо! Магия произошла! Мы действительно получили диаграмму, почти за бесплатно!
А когда же уже вайбкодинг? Не скоро. К сожалению, если мы хотим сделать нормальный, надёжный и масштабируемый сервис, нам как минимум для себя нужно получить картинку, как он должен выглядеть, какие в нём будут сущности и какие мы ставим функциональные требования к нашей системе.
Первым делом определимся со структурой сущностей в БД. Я всегда начинаю проектирование новой системы именно с БД, а не с самой архитектуры, потому что на основе сущностей и понимания связей между ними можно планировать декомпозицию архитектуры на микросервисы и определение зон ответственности между ними.
Формирование структуры базы данных было полностью отдано на откуп ChatGPT 5.2, и, справедливости ради, в процессе реализации MVP менялась она всего несколько раз, и добавилась лишь одна таблица логов.
На основе структуры базы данных, тому же GPT было дано задание спроектировать архитектуру самой системы
Итого, у нас имеется веб-фронт, который является одновременно и лендингом и основным функциональным сайтом. Фронт связывается с гейтвеем по http и сокетам, гейтвей же в свою очередь публикует задачи в реббит и получает апдейты по статусам, все апдейты он стримит по сокетам обратно клиенту.
LLM Worker консьюмит задачи на генерацию, делает запросы к LLM-ке, получает ответ, валидирует его, отправляет задачу на рендер. Render Worker консьюмит задачи на рендер, отправляет их рендериться, готовые изображения кладёт в S3.
Где-то в сторонке болтается еще сервис с ТГ ботом, у которого 3 принципиальных задачи: пересылать ответы формы обратной связи, пересылать сообщения отправленные боту мне на отдельный аккаунт, и подхватывать мои ответы из аккаунта, пересылая их пользователю.
Ещё не указывается на диаграмме сервис постгрес миграций, который занимается доставкой апдейтов в постгрес.
Промпты написаны, архитектура собрана, микросервисы декомпозированы. Казалось бы, осталось почивать на лаврах и смотреть как за тебя делают всю грязную работу.
Как я читал недавно в одной статье - "ИИ-агенты могут быть отличными сеньорами, но отвратительными джунами". И здесь я убедился в этом на практике.
Не счесть сколько раз мне пришлось "подчищать" за кодексом. Где-то он забыл расширение файлов при импорте добавить, где-то событийную шину не использует, а тут вдруг полез из application прямо в инфраструктуру, через function call, оставив скучать одинокий порт.
Энвы для постгреса в один сервис добавил, а в другом решил захардкодить. Такой микроменеджмент ужасно утомляет, и это наверное главный и пока к сожалению нерешённый пробел в вайбкодинге.
За один запрос я требовал у агента сгенерить все слои одного сервиса, учитывая при этом входящие и исходящие данные. Добавил также "фейк мод", чтобы выдавать dummy диаграмму в дев-среде и тестировать систему в обход ответов от LLM.
По фронту изначально были минимальные требования. Лишь бы работало. ИИ даже сам сгенерировал не самый плохой вариант UI. (Гораздо лучше, чем делал я руками во времена знакомства с html, или чем тот, что сейчас на половине гос.сайтов)
Итак, локально всё протестировано, через гит залито на сервер, сервис запущен, вводим в поле наш заветный запрос, и... получаем ошибку о недостатке памяти для ollama, когда она запущена на одной вдске на 8гб оперативки вместе со всем остальным зоопарком сервисов.
Итак, решение не канает. LLM не может работать параллельно с остальными сервисами на текущей конфигурации сервера. Можно было бы конечно улучшить текущую конфигурацию, но она всё ещё будет без GPU.
Минимальные сервера с GPU начинаются от 20 000 рублей в месяц. Расчёты по использованию API "гигачат лайт" тоже неутешительные при перспективе развития
Примерные расчёты стоимости гигачатаЦена
5 000 000 токенов = 1000 ₽
1 токен = 0,0002 ₽
1 ₽ = 5 000 токенов
Через символы (3–4 символа на токен, возьмём 3,5):
1 000 символов ≈ 285 токенов ≈ 0,057 ₽
10 000 символов ≈ 2 857 токенов ≈ 0,57 ₽
100 000 символов ≈ 28 571 токенов ≈ 5,7 ₽
Усреднённые значения для нашей системы:
prompt 800, completion 1200 → 2000 токенов
0,4 ₽ / генерация
На 1000 ₽ → ~2 500 генераций
В таком архитектурном цугцванге внезапно вспоминается давно заброшенный ноутбук с графическим процессором на борту, который лет 5 тому назад даже тянул игрушки на минимальных настройках. Под него покупается зарядка и принимается решение переквалифицировать его в сервер.
Из плюсов текущего положения, наличие давно приобретенного статического айпишника у провайдера. Ноутбук из графической убунты переквалифицируется в консольную версию, удаляется всё ненужное, в пару кликов устанавливается всё та же ollama3:7b. Настраивается фаервол, чтобы по порту ламы принимались только запросы с вдски.
Из крайне интересного опыта была настройка port forwarding-а через консоль модема. Эта настройка позволяет при обращении к моему статическому айпишнику и конкретному порту всегда редиректить запросы именно на нужное мне устройство.
Дополнительно устанавливается утилита, экономящая электроэнергию, другая утилита позволяющая отключить режим сна при закрытии крышки, из ноутбука насильно конфискуется батарея, вечно отходящий штекер зарядки приматывается скотчем и вуаля! Сетап юного инженера готов!
Попытка отправить запрос к ноутбуку по своему айпишнику увенчалась успехом! Старенькая видеокарта работает конечно некратно быстрее, чем вдска без GPU, но это выделенная машина, у которой есть одна задача.
Проверяем диаграмму классов. И получаем успешный, первый результат! Промпт пользователя на текущий момент дополняется приставкой по типу:
Сгенерируй валидную plantuml диаграмму по тексту ниже. Она должна начинаться со @startuml и завершаться @enduml. Не используй внешних подключений. В результате от тебя требуется только текст самой диаграммы без дополнительных пояснений и размышлений. "ТЕКСТ ПОЛЬЗОВАТЕЛЯ"
Уже на данном этапе можно заметить странную структуру, когда есть не совсем валидные связи, или и вовсе, отсутствие таких связей к нужным таблицам.
Далее, делается второй запрос и он завершается ошибкой. LLM в части запросов начинает галлюцинировать, добавляя несуществующие конструкции.
На первых порах пытаюсь лечить это вайтлистом команд для каждого типа, заданным на стороне кода, но через время, особенно когда доходит дело до генерации диаграммы последовательностей, или состояний, когда добавляются условия, процент успеха крайне мал.
Принимается решение перейти на "кодогенерирующую" модель LLM, которая решает проблему лишь отчасти, но далее, проект до конца будет работать именно на qwen2.5:7b, которая на генерации PUML в среднем показывает себя лучше и немного быстрее, чем чат-версия llama3:7b.
Средний показатель по больнице, на минимальных промптах:
Диаграмма классов - 80% успешных диаграмм
Диаграмма последовательностей - 31% успешных диаграмм
Диаграмма процессов - 74% успешных диаграмм
Диаграмма состояний - 49% успешных диаграмм
С такой надёжностью система работать не будет однозначно. По итогу было принято решение перехода от подхода "свободной генерации" к подходу "заполнения шаблонов".
Суть такого подхода заключается в том, чтобы задать максимально жёсткий промпт для LLM, который как бы подсвечивает все места синтаксиса, чтобы вероятность ошибиться была минимальной. Несомненно, такие запросы обрабатываются дольше. Но, зато результат успеха приближается к 100%
Ужасный шаблон мега-запросаСгенерируй PlantUML-диаграмму состояний (state) по описанию ниже.
Отвечай строго ВАЛИДНЫМ PlantUML-кодом, обёрнутым в @startuml и @enduml, без дополнительных комментариев, пояснений и текста вне этих директив. Никаких markdown-кодблоков (), никаких языковых тэгов типа plantuml```.
Структура ответа:
Первая строка: ровно @startuml
Вторая строка: ровно skinparam watermark "demo"
Далее — только код диаграммы состояний.
Последняя строка: ровно @enduml Не добавляй пробелов, пустых строк или текста до @startuml и после @enduml.
Требования к диаграмме:
Используй именно диаграмму состояний (state diagram), а не activity diagram.
Не используй внешние !include.
Все видимые на диаграмме названия состояний, событий и условий должны быть на русском языке.
Для каждого состояния с названием из нескольких слов сначала объяви его явно через алиас, например: state "Ввод данных" as VvodDannykh state "Ошибка ввода" as OshibkaVvoda В объявлениях состояний текст в кавычках — это отображаемое имя, алиас (после as) — идентификатор без пробелов.
В переходах (стрелках) в качестве источника и цели используй ТОЛЬКО алиасы без кавычек. Никогда не пиши кавычки вокруг источника или цели. Пример: [*] --> Nachalo Nachalo --> VvodDannykh
Начальное состояние записывай как [], конечное — как переход из состояния в [], например: UspeshnayaRegistratsiya --> [*]
Переходы без события записывай так: источник --> цель Пример: [*] --> Nachalo
Переходы с событием записывай строго так: источник --> цель : событие Всегда ставь ровно один пробел:
один пробел между целью и двоеточием,
один пробел между двоеточием и событием. Формат должен быть строго таким: источник --> цель : событие Недопустимы варианты:
источник --> цель: событие
источник --> цель :событие
Источник: событие
Гварды (условия) записывай строго в формате: источник --> цель : событие [условие] то есть:
цель (алиас),
ОДИН пробел,
двоеточие,
ОДИН пробел,
событие (при необходимости в кавычках),
ОДИН пробел,
условие в квадратных скобках [ ]. Пример: ProverkaDannykh --> Uspeshno : "Результат" [Данные корректны] Имя события (после двоеточия) НЕ МОЖЕТ быть пустым. Недопустим формат вида: istochnik --> tsel : [условие]
Никогда не используй формат: источник --> цель [условие]. Такой синтаксис недопустим. Даже если осмысленного события нет, всё равно записывай переход с двоеточием и формальным именем события, например: istochnik --> tsel : "Переход" [условие]
Не используй синтаксис действий (/ action), не используй фигурные скобки {} и не смешивай синтаксис activity-диаграмм с state-диаграммой.
Не добавляй никаких комментариев (// и т.п.) в код.
После этих инструкций я дам тебе текстовое описание процесса. На его основе сгенерируй только одну диаграмму в соответствии с правилами выше.
Также, отдельно нужно ЯВНО указывать, чтобы описания генерировались на русском языке. А названия элементов генерировались на английском языке. LLM может перепутать эти определения местами
Вроде всё неплохо, но с таким интерфейсом "в люди" не выйдешь. Так как наша цель - максимально использовать мощности искусственного интеллекта, то перерабатывать дизайн будем в два этапа.
Первый этап. При помощи сайта генерации дизайн-идей по входящему промпту, а также, указанию предпочтений по дизайн-коду, были сгенерированы базовые 3 экрана
Второй этап. На основе сгенерированных абстрактных экранов, кодексу предлагается переработать стилистику текущего сайта под предоставленный дизайн, с сохранением всего функционала
Надо сказать, что такой подход неплохо сработал, и мы получили уже более человеческий дизайн
Текст на сайте также был переработан, превратив его в максимально "продающий" вариант и исправив все логические расхождения.
Отдельно, была проведена SEO оптимизация, добавлена фавиконка, сгенерирован robots.txt, с разрешением для ИИ, добавлена карта сайта, раздел FAQ. Актуализированы контакты
Вот, казалось бы, сайт уже готов, но выход в люди может привести к санкциям со стороны регулирующих органов.
Для начала были подготовлены документы пользовательского соглашения и политики конфиденциальности.
Затем, был разработан баннер, который сообщает, что пользователь соглашается с хранением печенек, пользуясь сайтом. Был актуализирован раздел контактов и приведена в порядок форма обратной связи
Ну, и наконец, самое сложное - это регистрация себя как оператора персональных данных в роскомнадзоре. Интерфейс, от людей, которые и знать не знали о существовании CSS, выравнивании блоков, знающие про существование UX только понаслышке.
Данный квест, или же финальный босс был пройден на 100% при помощи ИИ за два с половиной часа, который подсказывал что куда тыкать, чтобы не было лишних вопросов, и доходчиво объяснял все юридические хитросплетения великого и могучего.
Самым главным узким местом сайта сейчас является LLM, которая работает на изживающем себя ноутбуке у меня на кухне. Как выбраться из текущего положения я не знаю, как впрочем и про способы монетизации данного проекта. Разве что на гранты какие-нибудь пытаться подаваться.
Конечно же, ложиться никто от большого потока не будет, не зря на страже безопасности стоит брокер с пулом в два параллельных сообщения. Просто UX будет постепенно деградировать - время ожидания генерации с ростом числа запросов будет неуклонно расти.
По технологическим планам, это конечно же добавление новых типов диаграмм, ибо PUML далеко не ограничен базовыми четырьмя типами, которые сейчас введены в систему. Более того, он сильно расширяется с добавлением аддонов, как например той же нотации C4
Также, крайне важной вехой развития будет возможность диалога, или же сохранения контекста. Сейчас флоу такой, что если пользователю что-то не нравится в имеющейся диаграмме, то он не может сказать ИИ исправить один конкретный элемент. В любом случае требуется повторная перегенерация диаграммы, без предыдущего контекста. Идея состоит в том, чтобы кидать имеющуюся диаграмму (PUML код) вместе со входящим новым промптом от пользователя. Правда чувствую, что на текущих ресурсах именно в этом месте, ЛЛМка падёт смертью храбрых из-за обилия входящих токенов.
Далее, интересная перспектива добавления прямого редактора сгенерированных диаграмм. Учитывая, что у нас есть PUML код, наверняка существуют удобные инструменты конвертации его в JSON формат, и готовые библиотеки, позволяющие этим JSON-ом оперировать, по типу какого-нибудь drawio. Это решит очень много мелких проблем, когда пользователю допустим не нравится просто какое-то название, или стрелочку хочется на пару пикселей передвинуть (что кстати не сделаешь в PUML). Также, можно дать возможность выгружать диаграммы в JSON, в PUML для дальнейшего взаимодействия с ними. Единственное, что пока вызывает сомнения - это возможность обратного переката из JSON в PUML, для дальнейшего взаимодействия с ЛЛМ
Ещё одним важным этапом сразу после онлайн-редактора видится версионирование диаграмм, с возможностью отката на предыдущую версию.
О монетизации проекта пока нет особых идей. Хотелось бы конечно в идеале сделать его автономным, чтобы он окупал аренду GPU сервера. Но пока сильно пугают юридические аспекты такого начинания и отсутствие веры в то, что кто-то будет готов платить за такой продукт. Пожалуй в этом основная особенность мышления инженера, а не маркетолога
Не использовал бы связку NestJS + TS. ТГ-бот был написан на питоне (fastapi), и запускался со второго раза, без танцев с бубнами. Если будет в планах реализовать другую идею вайбкодингом, то там определенно будет питон.
Что ж, мне на своём примере удалось доказать, что современные технологии, позволяют при правильном подходе использовать возможности ИИ-агентов на максимум. И что можно, не написав ни одной строчки кода создать надёжный и масштабируемый сервис в крайне ограниченный срок. Радует постоянное развитие и улучшение агентов, и есть надежда, что со временем, они станут не только хорошими сеньорами, но и удовлетворительными джунами
Если хотите пощупать готовый сервис, то вот сам сайт с генерацией диаграмм https://ai-diagram.ru/
Источник


