>nickey

Микроблог, в этот раз с ActivityPub

Хммм... Пятый по счёту первый пост в блог. Добравшись до очередной итерации бложика (давно сбился со счёту - какой именно), решил, что в этот раз пора что-нибудь поменять. Разумеется, речь только о технических переменах, общий подход прежний - я, как и раньше, не буду сюда ничего писать. Идея минималистичного статического генератора мне по-прежнему импонирует. Но, кажется, написав предыдущий полностью на Emacs Lisp и org-mode, я закрыл этот гештальт. Возможно, это временное помутнение рассудка.

Когда-то у меня уже был аккаунт на почившем ныне lor.sh, а потом - на mastodon.ml. Но, во-первых, мне не всем нравится сама ванильная версия Mastodon, а во-вторых, после закрытия старого бложика домен пустовал с дефолтной страницей nginx 404 на новом сервере. Мне всё ещё нужен был TLS-сертификат для домена, поэтому просто удалить A-запись я не мог (вообще-то, мог, перейдя на dns-acme, но нафиг).

Закрытие старого бложика было не столько моим решением, сколько вынужденной мерой. Но, коль уж так случилось, решил попробовать реализовать давно зревшую в голове идею федеративного ресурса. Сначала думал взять что-нибудь готовое и немного повозиться с ним - например, тот же Mastodon (привет господину Трампу и Truth Social), но разворачивать многопользовательскую платформу ради одного пользователя как-то не улыбалось. А всё однопользовательское, что удалось найти (все полтора приложения) - либо заброшено, либо не впечатлило, либо и то и другое сразу. А может быть, это NIH-синдром - я так глубоко не копал.

Челлендж

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

Более модного и молодёжного, чем ИИ, до завтрашнего обеда уже ничего не предвидится, поэтому вайбкодим. А ключевое ограничение - кодинг только на локальных малых LLM, никаких облачных триллионных гигантов и подписок. Не звучит как челлендж? Сейчас разверну мысль...

Можно было, конечно, просто достать из шкафа две RTX 5090, запустить vLLM и в путь. Но чтобы их из шкафа достать - их надо туда сначала положить. А в мой шкаф их никто не положил, я проверял. Геймером я никогда не был, да и 3D-рендером особо не увлекался, так что под рукой оказалась только 10-летняя затычка GTX 1060 6GB (ох, сколько она повидала за эти 10 лет).

Dense-модели сразу мимо кассы, а вот среди MoE даже есть вменяемые варианты под это железо. Например Qwen 3.6 35B A3B в квантовании Q4_K_XL - очень разумный компромисс. Попробовал и другие MoE-модели A2B и A4B, но остановился именно на qwen-based моделях. Если быть точным, то на Tiel Coder, который основан на Ornith, который, в свою очередь, основан на Qwen 3.6 35B A3B. Хорошо ещё, что я успел купить 64GB оперативки до подорожания, ведь челлендж не требует разместить всю модель на GPU - а значит, CPU Offload никак не запрещён. В противном случае пришлось бы остановиться на dense 4B модели, и тут уж не знаю - удалось ли бы вообще завершить эксперимент за разумное время...

После всех оптимизаций, на изучение и применение которых ушло несколько вечеров, удалось добиться контекстного окна в 96К токенов при квантовании KV-кеша q8 (можно даже 128К, но тогда не помещается mmproj). Производительность декодирования - 15 токенов в секунду при пустом контексте (вообще, 17 - но это уже работало нестабильно). Префилл - около 300 токенов в секунду всё на том же пустом контексте. По мере наполнения контекста - закономерное линейное падение обоих параметров почти вдвое. И, естественно, ни о каком спекулятивном декодировании на этом сетапе даже речи не может идти.

Рабочий процесс

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

Даже если бы я хотел попробовать пройти этот путь слабоумия и отваги - результат от 35B MoE модели скорее напоминал бы оскорбление, чем решение. На практике - даже набор из пары десятков непротиворечивых правил и достаточно развёрнутая спецификация вводят модель в ступор, и она либо начинает игнорировать их, либо часто уходит в бесконечный ризонинг. SpecKit и подобное в этих условиях только усложняет жизнь и, соответственно, не используется.

Поэтому правила были по возможности вынесены из требований и оформлены алгоритмически - прогоны тестов и линтинг на git-hooks, проверка Pull Request на соответствие стандартам проекта и отсутствие в них артефактов 4-битного квантования. CI-пайплайн с контролем покрытия и всё вот это вот (кстати, для меня загадка - почему, но ИИ отвратительно пишет пайплайны, так что здесь тоже не всё гладко)...

В качестве харнеса был выбран, конечно же, Pi - просто в силу своего минимализма, удобства и короткого дефолтного системного промпта. Вместо большой спеки и плана реализации в md-файлах - куча issue в Gitea, выступающем единственным источником истины. Ну и несколько промптов для Pi - /take N берёт issue с номером N и пишет план реализации. Затем корректировки в режиме чата, после чего /go - сохраняет согласованный план в виде комментария к issue, реализует основную задачу по этому плану и готовит Pull Request, закрывающий issue по всем правилам проекта.

В итоге я просто отдавал пул задач в работу и ждал, пока накопится пачка Pull Requests. Когда доходили руки (раз в пару дней) - проводил ревью, иногда возвращая в работу откровенный брак. На мелкие огрехи в реализации либо закрывал глаза, либо открывал новые issues с меткой tech-debt.

Внимательный читатель задастся вопросом: "Откуда же пачка Pull Requests, если надо самостоятельно отдавать задачу модели и валидировать план перед началом реализации?". Отличный вопрос! Рад, что вы спросили 😄

Поначалу я так и работал - держал открытый терминал с запущенным Pi и периодически, спотыкаясь о него, вспоминал, что там идёт какая-то работа. Чтобы терминал не мешал - я стал запускать его в сессии tmux и детачиться от неё. Но стало ещё сложнее вспоминать, что вообще-то там может ожидаться моё очередное действие. Тогда я настроил уведомления через notify-send, и модель отправляла мне что-нибудь, когда заканчивала работу или когда ей требовалось моё подтверждение. И это решение тоже не стало панацеей - если работа над задачей длилась часами, случалось просто забыть и ребутнуть систему. Так что я завёл LXC-контейнер в Proxmox, и сессия tmux жила уже в нём (да-да, я знаю про herdr, и всё равно tmux).

А чтобы issue отправлялись в работу без моего вмешательства - собрал на коленке расширение для Pi, позволяющее из одной сессии отправлять команды в другую и контролировать процесс (что-то вроде субагентного флоу, только вообще ни фига не оно). Так что я просто держал две параллельные сессии Pi в tmux. Одна следила за ходом выполнения - брала новые issue из очереди, отдавала их в работу и даже как-то худо-бедно валидировала план по каждой задаче, иногда возвращая его на доработку. А другая - занималась всей работой в рамках одной задачи. Права мерджить Pull Requests, разумеется, ни у кого из них не было, и по этой причине я не очень переживал, что работа над кодом ведётся без моего участия.

Designs очень affordable

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

Несколько раз я попросил LLM придумать дизайн, и каждый раз был ужаснее предыдущего. Я почти уверен, что Opus и Astra выдали бы что-то эстетически приятное и удобное, но это нарушало бы условия челленджа, поэтому даже не пробовал.

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

Что в итоге

А в итоге - 210 закрытых issue, 222 влитых pull request и чуть более месяца работы. Не могу сказать, насколько это медленнее, чем реализация с помощью большой облачной модели - без эксперимента не определить, а на некоторые грабли я наступал не по вине LLM. Да и работа далеко не всегда шла 24/7 - иногда я экспериментировал с разными моделями, иногда останавливал работу на дни, иногда тупо отключали электричество, и т. д. и т. п... Но это совершенно точно быстрее, чем если бы я писал весь код руками - просто потому что за весь этот месяц я бы просто не нашёл на это времени из-за работы. Совсем. И идея лежала бы в копилке ещё много месяцев не начатой. А ревью - даже подробное, как ни крути, занимает сильно меньше времени, чем ручное написание кода.

Поэтому можно уверенно констатировать, что челлендж выполнен, результатом я доволен. Буду считать эту итерацию пятой - просто потому что почему бы и нет 🤷‍♂️...

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

лайк 1, буст 2