TG Telegram Group Link
Channel: partially unsupervised
Back to Bottom
Moderately hot take: современный LLM-based AI engineering больше похож на времена до Imagenet moment, чем на эпоху расцвета диплернинга.

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

Во времена расцвета диплернинга, все больше задач стали решаться end-to-end, и потому ключевыми инструментами стали околоархитектурные изменения (включая знаменитый stack more layers) и, конечно, большие и чистые датасеты. Если предложить делать какой-нибудь adaptive histogram equalization перед инференсом какого-нибудь Resnet/Unet, в приличном обществе на тебя будут смотреть с опаской - пусть сеть сама это выучит, оставь свои древние штучки для аугментаций! Умение сделать кастомный лосс важнее умения придумать релевантную эвристику.

И вот с foundation моделями прошел полный оборот: большие модели делают умные GPU-rich ребята, соваться туда в подавляющем большинстве случаев бессмысленно, и надо снова придумывать пайплайны с эвристиками. Перебор разных фильтров в препроцессинге до сходимости был в той же степени хаком, как и идея добавлять wait в конец генерации; сейчас бы оно легло в парадигму test-time scaling и не считалось зазорным.
Пару дней программировал с Claude Code - это приложение-агент для терминала, которое умеет не только просто писать код, но и планировать, адаптироваться и выполнять команды локально. Весь инференс идет через Anthropic API, так что нужно подключить ключ и готовиться к затратам. Из коробки доступны базовые команды - view, edit, replace, glob, grep, выполнить произвольный баш, но можно и подключить свой MCP и адаптировать под себя. Сколько-то похоже на agent mode в Cursor, с которым я как-то не очень поладил (хотя inline автодополнение там клевое), а из опенсорсных решений напоминает Aider.

Я пробовал работать в двух проектах: один небольшой, но начат умными людьми и потому обладает некоторой структурой, второй я делал прям с нуля в режиме "вайб-кодинга". В обоих случаях у меня уходило что-то около 10 баксов в час, причем я старался вовремя сбрасывать контекст, чтобы счет меня не разорил. Когда осознаешь, что команда "run tests" стоит три цента, это вызывает странные незнакомые эмоции. Помимо денег, есть вопросы и к скорости: например, вчера перед сном я оставил агенту одну задачу и ушел, не закрывая ноутбук. Утром глянул результат - total cost: $5.90, total duration (API): 37m 11s.

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

Скучный бойлерплейт-код пишет отлично (в разы быстрее, чем я бы писал в редакторе даже с копайлотом или аналогом), дебажит неплохо, но, как и все LLM, может пойти по неправильному пути и нахерачить много дичи, надо вовремя останавливать и быть очень конкретным (например, жестко определять стек). Если не влезать в детали и давать недостаточно конкретные указания, будет так: "Бесконечная бессвязность за кажущимся смыслом, абсолютная неконсистентность, скачки мыслей и стилей между разными частями проекта. Полнейший ужас и хаос за кажущимся порядком".

Короче, пока немного сыровато, но буду иногда использовать. Хочется быстрее и дешевле; думаю, еще увидим в этом году.
See also: отзыв от Антона.

P.S. нашел пасхалку: через claude code можно заказать себе стикеры anthropic, но доставка только в 🇺🇸
partially unsupervised
Пару дней программировал с Claude Code - это приложение-агент для терминала, которое умеет не только просто писать код, но и планировать, адаптироваться и выполнять команды локально. Весь инференс идет через Anthropic API, так что нужно подключить ключ и готовиться…
Вдохновился постом о том, как использовать Claude Code для анализа структуры Claude Code и пошел по тому же рекурсивному пути: сгенерил при помощи Claude Code утилиту, чтобы логировать его же запросы. На первый взгляд, магии там мало - системный промпт, две базовые модели (sonnet 3.7 + haiku) и набор тулов.

Если хотите поковыряться своими руками, выложил результат на github.
Думаю, следующим шагом было бы интересно попробовать подменить базовые модели на что-то локальное.
Месяц как перекатился из мира, где комбинировал kNN и PCA, в мир MCP и ToT. Продолжая жонглировать акронимами, назову это мягким переходом из ML в AI - прототипирую некие инструменты для разработчиков, чем давно хотел заняться. Впечатления такие:

Во-первых, software engineering аспект стал прям важен! Раньше умение завернуть свою поделку в докер и высунуть хендлер уже считалось кое-каким уровнем, а умение покрыть это все хоть какими-нибудь тестами выделяло из толпы jupyter-писателей. Сейчас иначе: например, в первую неделю в рамках онбординга нужно было оптимизировать алгоритм обхода графа. Из других нетривиальных задач: придумать и добавить кастомное правило для линтера, спроектировать удобную стейт-машину поверх других низкоуровневых стейт-машин.

Во-вторых, LLM провоцируют выводить все на метауровень. Например, типичная итерация улучшения выглядит так: внес изменение, дальше в одну команду запустил пайплайн на сгенеренных сценариях, достал логи, проанализировал логи LLM-кой, сгенерил отчет, и только потом смотришь глазами на популярные failure modes. Все это занимает 10-15 минут (если не падает в рантайме, ыхыхы), так что итерироваться можно много и часто.

Во-третьих, порой ощущаю себя дурачком, во многом нужно разбираться с нуля и задавать коллегам неловкие вопросы. После рабочего дня голова часто трещит и настойчиво требует отдыха. Но главные навыки - декомпозировать проблему и анализовать ошибки - оказались абсолютно переносимы. Опыт таки пригодился!
(здесь могла быть реклама книги, и особенно глав про preliminary research и error analysis).
Съездил на Gemma Dev Day. Пересказывать пресс-релиз про выход Gemma 3 смысла не вижу, но несколько вещей отмечу.

1) Действительно небольшая разница между 12B и 27B моделями + нативная поддержка квантования = отличный кандидат для локального использования, если это кому-то актуально. На макбуке с M4 Max 12B фигачит 36 токенов в секунду (для сравнения 27B выдает 16 т/сек).

2) Обещанная мультиязычность хоть и есть, но до совершенства еще далеко. На конференции активно хвастались, что помимо собственно знания языка модель прокачали в знании культурного контекста и прочего. Мне скоро предстоит экзамен по польскому, и потому в самолете активно вайб-чекал именно его: болтает нормально, если мучать вопросами грамматики, то даже я могу кое-где увидеть пробелы (а мой уровень польского очень посредственный!). Впрочем, какая-нибудь GPT-4o в этом смысле тоже не без греха.

3) Обещают function calling, но из коробки в ollama его нет. Разработчики говорят, что instruction following хороший, и потому для вызова функций надо просто детально описать инструкцию и потом самому парсить аутпут (привет, регулярки!). На нескольких семплах я бы сказал, что скорее работает даже в zero shot, но неидеально.

4) Всем участникам конфы досталось по футболке (ожидаемо) и по Jetson Nano Orin (неожиданно!). И еще более внезапно лично для меня футболка в моменте оказалась ценнее - опоздал на пересадку, ночевал в отеле аэропорта, но на утренний рейс пришел в свежей футболке! Надеюсь, что канплюктер окажется полезнее в долгосрочной перспективе.

P.S. Незапланированно повидался с Артемом @ai_newz и Григорием @gonzo_ML - ML мир все-таки тесный!
По аналогии с афоризмом “в ходе следствия главное - не выйти на самих себя”, могу сказать, что в ходе разработки фреймворка для AI кодогенерации удалось сделать сам фреймворк совершенно непригодным для генерации. Например, вчера Claude предложил дописать примерно такое:
with HandlerTestTaskNode.run(**params) as ctx:
result = solve(lambda ctx: type('TypeContext', (), {'compiler': ctx.compiler})())
Старый приятель @peopleintech показал the best scam ever: приложение с гороскопами и прочей эзотерической мутью, а под капотом на самом деле - AI и когнитивно-поведенческая терапия. Надеюсь, в качестве дефолтной LLM там Gemini

Вообще, на первый взгляд это смешно, а если задуматься, то такой UX не может не быть успешнее, чем стандартный чат-интерфейс с дополнительной парой кнопок поверх LLM API 🤔
Вчера запекал баранью лопатку (вам же интересно мое чревоугодие? 🍖), и из этого вырос пост про случайность и скапулимантию.

Мы все знаем много алгоритмов, в которых случайность важна - в криптографии, оптимизации, ML, распределенных системах и так далее. А как насчет менее академических, более древних примеров? Теория вероятностей стартовала как прикладной инструмент для азартных игр, но я сейчас не про то, как Кардано играл в кости. Но кости в этом тексте еще будут упомянуты!

Давайте представим такую ситуацию: на некой территории живут племя охотников и стая вкусных животных (например, оленей или баранов). Охотники могут отходить от лагеря в поисках дичи в выбранном ими направлении. Олени хотят где-то пастись и избегать охотников. Предположим, что качество пастбищ на всей территории одинаковое. Каково оптимальное поведение для каждой группы с точки зрения базовой теории игр?

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

Например, гадание на лопатке. Алгоритм такой: охотник берет кость нужного зверя, нагревает на углях до образования трещин и трактует эти трещины как своего рода карту, выбирая направление для охоты. Поздравляю, теперь вы знаете, что ответить на интервью, если вас попросят задизайнить random number generator, имея остатки ужина и костер!

Фактоид честно украден из книги Джозефа Хенрика.
Про вайбкодинг

Я сжег уже больше 100М токенов в Claude Code, потому имею моральное право поделиться опытом про вайбкодинг.

1. Вайбкодинг действительно очень сильно ускоряет решение большей части задач. Нюанс, как обычно, в том, чтобы вовремя заметить те 20% кода, где его применять не надо.

Не надо применять:
- нетривиальный алгоритмический код (сломается в корнеркейсе - задолбаешься дебажить);
- свежие библиотеки (даже если заставлять читать документацию из интернета, в среднем получается плохо);
- метапрограммирование, написание фреймворков, дизайн API между компонентами;
- security-sensitive задачи.

Надо применять:
- +1 задачи (посмотри, как сделано здесь, и сделай по аналогии);
- все некритичные задачи в незнакомом домене (набросать фронтенд);
- типичный IO layer (в основном хендлеры);
- задачи, в которых вся “сложность” - знать 100500 команд и флагов API (например, aws cli).

2. Вайбкодинг несет неочевидный оверхед в сеньорной команде. Раньше если человек видел код и не понимал его с первой попытки, применялась презумпция качественного кода: если оно написано и закоммичено умным человеком, то, наверное, в этом смысл, надо перечитать и вдуматься. Сейчас иногда приходится переспрашивать “в этом есть какой-то нетривиальный замысел или ты просто нагенерил говна?

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

4. Если диалог идет не в ту сторону с нескольких итераций, нужно всегда начинать сначала, его уже не спасти. Если несколько попыткок стабильно скатываются в дичь, несмотря на добавление деталей в изначальный промпт, см. пункт 1.

5. Главный кайф не только в кодогенерации, а именно в активном агентском режиме - кидаешь промпт типа “посмотри на CI, почему упал такой-то PR и найди проблему” или “я задеплоил сервис этим терраформом, посмотри все логи и разберись, почему хелсчеки не проходят”.

6. Для эффективной работы нужно дописывать правила в CLAUDE.md (.cursorrules и так далее), подключать релевантные MCP и в целом анализировать, где оно косячит. Например, вот кусок моего глобал конфига:
Python style guide:
1) when catching exceptions, use logger.exception("message"), not logger.error(str(e)).
2) do not use mocks unless explicitly asked!
3) ensure types are correct, e.g. def hello(name: str = None) is WRONG, def hello(name: str | None = None) is correct.
4) use logger = logging.getLogger(__name__) when declaring a logger
5) prefer match + case over if + elif + else
6) using hasattr is typically a sign of bad design!


Делитесь своими лучшими практиками в комментах! Просто ворчать, что вайбкодинг - херня для кретинов, можно тоже там.
Как недооценить на порядок тривиальную задачу

Есть небольшая кодовая база; в ней много вызовов LLM. Хочется гонять интеграционные тесты быстро, не ждать ответа от медленной (да и не самой дешевой) апишки. Решение напрашивается: давайте закэшируем ответы (VCR testing)! Это же должно делаться буквально одним кэширующим декоратором поверх уже существующего LLM клиента, не так ли?

Оказывается, не совсем, ведь:
- клиент инициализируется в куче мест, нужно сделать синглтон;
- клиент инициализируется со слегка разными параметрами, нужно привести к общему знаменателю и проверить, что нет регрессий;
- два одинаковых запроса к LLM могут вернуть разные ответы, в т.ч., например, один валидный и один невалидный примерно в одно и то же время.
- клиент вызывается конкурентно и асинхронно, нужен лок;
- запрос содержит сложные иерархические слаботипизированные структуры, вычисление ключа кэширования нетривиально;
- эквивалентные запросы могут осуществляться по-разному (например, через именованные и неименованные параметры);
- часть запроса формируется из логов, а потому может содержать случайные элементы (например, айдишки или таймстемпы), которые нужно подчищать;
- такой VCR кэш устаревает с каждым минимальным изменением в логике того, как мы работаем с контекстом - нужно обеспечить простой и понятный developer experience, как этим пользоваться, как обновить, и в каких случаях это уместно.
- разрастается логика: оказывается трех режимов (не использовать / обновить кэш / проиграть из кэша), не хватает - например, в дебаге полезно иметь гибрид, который и переиспользует старые записи, и может сходить в апишку. А вот для тестов это харам, cache miss должен явно ронять тест.

Но разве кого-то волнует, насколько я недооценил сложность изначально, когда тесты такие быстрые?.. 🚀
Недавно собрал на коленке Reddit Research - максимально простую вариацию на тему deep research, но с фокусом только на реддит (лично у меня это довольно частый сценарий использования и в обычном поиске, и в AI-ассистентах).

Очевидно, он уступает по качеству deep research от крупных вендоров, но вполне подойдет тем, кто зачем-то хочет гонять все локально, или сделать форк и контролировать какие-то мелочи. Ну и для неопытным разработчикам LLM-приложений может пригодиться для вдохновения - кода мало, и большая его часть - свистелки для терминала.
Примерно раз в год на меня накатывает настроение поковыряться в железках, хотя объективной потребности в этом нет, и приходится ее придумывать.

В этот раз идеально совпали дождливые выходные и приехавший ко мне Argon EON Pi NAS.

В итоге:
- стряхнул пыль с raspberry, собрал старые диски по всей квартире (получилось 17 с небольшим терабайт) и запихал все в новый корпус. EON классный, все работает, выглядит изящно, всем рекомендую, отличный подарок умеренным нердам.
- поставил openmediavault, долго плевался от того, какой это инвазивный отстой, и полчаса удалял метастазы;
- засетапил там samba и подключил TimeMachine бэкапы (да, так можно!);
- наконец-то засетапил подаренный jetson (как всегда с nvidia, это оказалась слегка нетривиальная задача - нужно замыкать пины, перепрошивать, переписывать конфиги для sdkmanager…). qwen3:8b выдает 7 токенов в секунду, как будто мне это хоть когда-то понадобится;
- связал все это в одну сеть через tailscale, раскидал по углам, умиротворенно слушаю, как шуршат старые HDD.

Делитесь в комментариях, кто держит дома всякие микроканплюктеры и главное - зачем.
Не так давно широко разошелся твит про то, что агентский AI будет массово требовать скиллы, похожие на игру в starcraft.

Метафора прикольная и, конечно, греющая душу (пусть в старкрафте я нуб, но свои сотни часов в warcraft 3 и age of empires отыграл). Но если обобщать опыт вайбкодинга, то метафора неточная, и Dungeon Keeper или Tropico будут ближе. В классических RTS много микроконтроля: закайтить, отвести раненого юнита, минимизировать урон от AoE; именно микроконтроль отличал казуалов от продвинутых.

Но вся суть работы с агентами в том, что человек не должен микроменеджить. Продуктивный AI-кодинг требует выстроить такую систему, в которой агент будет эффективно работать, с минимальной вероятностью наделает херни, а если вдруг и начнет творить дичь, у этого не будет серьезных последствий. Не нужно быстрее всех нажимать tab или enter, нужно писать непротиворечивые инструкции, гранулярно декомпозировать, сетапить тесты/линтеры/валидаторы - иными словами, предпочитать непрямой контроль, потому что он лучше скейлится.
Формально у меня сегодня последний день в Neon, потому что я оказался среди поглощенных кирпичным заводом, на котором - пока столь же формально - начинаю работать завтра.

Поэтому символично, что сегодня успели зарелизить app.build - продукт, над которым мы небольшой командой работали с февраля. Это just another end2end генератор CRUD веб-приложений от промпта до деплоя.

Он полностью опенсорсный (можно покопаться в истории и увидеть все мои коммиты в стиле “maybe fix a lot of things”), работает как CLI и обычно генерит скорее работающие приложения. Можно сгенерить на наших серверах, можно развернуть у себя (все равно понадобится gemini и claude API, но можете прислать PR с поддержкой любимого LLM-провайдера). Шероховатостей еще много, но уже скорее работает, чем нет, так что пробуйте и присылайте баг-репорты!
Когда-то давно я нахваливал Streamlit, в свое время наделал на нем пару десятков приложений, и пересадил на него кучу коллег. Но настало время двигаться дальше, и потому сегодня хочу порекомендовать читателям NiceGUI.

Вкатиться в NiceGUI немного сложнее, чем в Streamlit: невозможно просто прокатиться мордой по клавиатуре и получить работающее приложение. Но если повозиться чуть больше, то результат получается сильно более зрелым:
- настоящие отдельные фронтенд (Vue/Quasar + Tailwind) и бэкенд (Fastapi), в которые можно провалиться для доработки (а можно и не вникать и оставаться в высокоуровневом python коде);
- вебсокеты вместо перезапуска всего приложения на каждый чих;
- нормальная поддержка нескольких параллельных пользователей благодаря нескольким гранулярным видам хранения стейта вместо одного st.session_state;
- к этому можно писать тесты!

Вайбкодить на NiceGUI сложнее, чем на стримлите, но мы над этим работаем 👀

Этот пост не имеет никакого отношения к тому, что Streamlit уже давно часть Snowflake, а я сейчас работаю в Databricks.
У меня есть кореша и немного даже собутыльники, которые когда-то стояли у истоков Vochi, успешно продали их Пинтересту, и вот сейчас они запустили новую компанию про genAI и музыку. По этому поводу они ищут толкового deep learning инженера, который умеет не только склеивать апишки, но еще помнит, как пользоваться пайторчем, умеет читать статьи и привносить какую-то новизну поверх - иными словами, повидал некоторое дерьмо может запилить что-то нетривиальное.

Я не стану перечислять все эти штуки про уникальные задачи, клевый офис в Варшаве и большой GPU кластер; скажу только, что ребята толковые и, думаю, что по деньгам с хорошим человеком договориться смогут.
Сегодня я узнал, что если придти на митап Snowflake❄️ в футболке Databricks🧱, то примерно через час к тебе вежливо подойдут специально обученные люди и попросят уйти
Написал лонгрид о том, как мы делали app.build, какие дизайн-решения принимали и немного о будущих планах.

Рекомендую тем, кто делает агентские системы, и особенно - близкие к кодогенерации.
HTML Embed Code:
2025/06/30 03:47:45
Back to Top