Pavel Zloi
3.36K subscribers
646 photos
60 videos
2 files
923 links
директор ИИ · инженер‑интегратор
@eprogrammist | https://github.com/EvilFreelancer

20 лет в IT
∈ 10 лет в разработке
∈ 3 года в ML/AI
∈ 1 год - вайбмастер

Бусти:
https://boosty.to/evilfreelancer

Пожертвования:
https://pay.cloudtips.ru/p/937f48ac
Download Telegram
Как работает tool calling в vLLM

Валерий @neuraldeep и Александр @countwithsasha подняли тему (тыц и тыц) о том, как tool calling работает на стороне inference-движка, давайте разберём это на примере vLLM - одного из топовых движков для реализации tool calling паттерна, но к слову сказать аналогичным образом это устроено и в других движках.

Кратенько, нет единого формата tool calling, каждое семейство моделей придумало свой уникальный синтаксис. Hermes оборачивает вызовы в XML-теги <tool_call>, Mistral использует [TOOL_CALLS] с JSON-массивом внутри, Llama генерирует JSON внутри специальных тегов <|python_tag|>, DeepSeek пишет вызовы в тройных кавычках, и inference-движок должен это все уметь парсить.

Как tools попадают в промпт

Всё начинается с API-запроса, в протоколе ChatCompletion у vLLM для тулов есть два поля:
- tools - список доступных функций
- tool_choice стратегия вызова ("none", "auto", "required"`) или конкретная функция

Дальше tools передаются в chat template через render-слой, тут tools преобразуются в текст, который передаётся через системный промт на вход модели.

Парсинг ответа модели

Когда модель сгенерировала текст, движку надо понять, ват из зис за фак такой, обычный ответ или вызов функции?

Логика напрямую зависит от tool_choice:
- Конкретная функция (named tool choice) - весь вывод модели считается JSON-аргументами для этой функции (парсинг не нужен)
- "required" - вывод парсится как JSON-массив [{name, parameters}], используется всеми нами любимый structured output (JSON-схема), чтобы модель гарантированно сгенерировала валидный ответ
- "auto" - самый интересный случай, тут включается ToolParser, который анализирует сырой текст и ищет в нем tool calls

Базовый класс ToolParser определяет следующие методы:
- adjust_request() - модифицирует запрос перед генерацией, например, может добавить JSON-схему для structured output
- extract_tool_calls() - парсит полный вывод модели (non-streaming)
- extract_tool_calls_streaming() - парсит вывод по мере генерации (streaming), детектит токен за токеном

Все парсеры регистрируются через реестр ToolParserManager, который загружает нужный парсер по имени, активируется на старте через CLI флаг, например так `--tool-call-parser hermes`. На данный момент в vLLM имеется 32 парсера, в том числе и gigachat3 для новых сберовских моделей.

Пример - как парсит Hermes

Разберём как работает Hermes2ProToolParser, предполагается, что модель генерирует что-то вроде:
<tool_call>
{"name": "get_weather", "arguments": {"city": "Moscow"}}
</tool_call>


Парсер делает findall по регулярке <tool_call>(.*?)</tool_call>, вытаскивает содержимое, предполагается, что это JSON-схема, которую парсер раскладывает по объектам ToolCall(name=..., arguments=...), при этом текст до первого <tool_call> сохраняется как обычный content ответа, так как модель может ответить текстом и одновременно вызвать функцию.

В streaming-режиме уже есть нюансики, парсер на каждом новом токене перепарсивает накопленный текст, сравнивает с тем что уже отправил клиенту, и шлет только дельту. Отдельно отслеживается частичное совпадение с тегом <tool_call> - если текст заканчивается на <tool_, парсер придерживает его в буфере, не отправляя клиенту, пока не станет ясно - это начало вызова или просто текст.

Пользовательские парсеры

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

Флаг --tool-parser-plugin path/to/my_parser.py загрузит код парсера в реестр, а --tool-call-parser my_parser_name активирует его. Нужно только наследоваться от ToolParser и вызвать директиву вида @ToolParserManager.register_module("my_parser_name").

Итого

Вся магия tool calling это банальный промпт-инжиниринг + парсинг вывода.

За сим откланиваюсь, спасибо товарищам по вайбцеху за то что затронули тему внутреннего устройства движка vLLM, приятно поднять заметки и покопаться в кодовой базе.
🔥357👍5😇2💅2
Следуя советам Никиты @buckwheat_thoughts прокачал гиперпараметры обучения модели ruGPT3XL-8k, оказалось все мои прошлые попытки не маскировали инпут, а большой LR и прочие параметры приводили к оверфиту, теперь прогресс идёт намного стабильнее. Однако, это привело к увеличению времени обучения со 100 часов до 240, но лучше дольше чем неправильно.

(не пугаемся высокому train loss, из-за fsdp тренер пишет кривые числа, делим их на 32)

Помимо этого благодаря советам Александра @dealerAI смог ускорить процесс в почти 4 раза запустив обучение через FSDP (скрипт train_rugpt3xl_fsdp.py), все видеокарты загружены на максимум, время обучения снизилось с 240 часов до 42-46.

Плюс разобрался с тем как сделать "весёлые картинки", для этого внутри контейнера поставил и поднял tensorboard, и настроил тренер чтобы он писал логи куда надо.

Вот каждый раз убеждаюсь, что самый лучший способ научиться чему-то новому это заявить публично какую-то спорную мысль, а потом мотать на ус советы более умных товарищей.
👍196🤝3🔥2
Самый простой способ выветрить всю "магию" и шарм из VS Code и Cursor.
🔥43🤷2😢1
Ребят в CodeDash появился лидерборд!

Зачем?
1) Интересно узнать на сколько вы отличаетесь от других вайбкодеров
2) Можно найти друзей по цэху и написать им через github
3) Можно поискать что же за проекты пилит автор если он их выкладывает в open-source
4) Можно поискать и хантить себе вайберов если вы поняли о чем я =)
5) Просто по фану измерить примерно сколько у вас в см запросов на фоне других вайберов
В общем качайте новую версию

codedash update && codedash restart


Синхронизируйте Github и регистрируйтесь в лидерборде!
👍8🔥4💩2🤡21🤝1💊1
Pavel Zloi
Следуя советам Никиты @buckwheat_thoughts прокачал гиперпараметры обучения модели ruGPT3XL-8k, оказалось все мои прошлые попытки не маскировали инпут, а большой LR и прочие параметры приводили к оверфиту, теперь прогресс идёт намного стабильнее. Однако, это…
Обучение ruGPT3XL-8k на ризонинг и агентных датасетах продолжается и судя по eval_loss на 500 шаге тренировка прошла свой предел точности, дальше походу начался оверфит.

Чепоинты эти я уже скопировал в отдельную папку, они нарезаны на шарды из-за особенностей FSDP, но сшить их не проблема, если eval_loss и дальше будет ухудшаться то стопорну тренировку и выкачу 500й чекпоинт.

Единственный нюанс который мне кажется странным в том, что eval/mean_token_accuracy даже на 550 продолжает улучшаться, хотя по логике не должен, но подожду до 650го шага, если там eval_loss сильно пойдёт вверх то на mean_token_accuracy смотреть смысла не будет.
🔥10👍42🥱1
Вайб-дизайн Starterkit

18 марта 2026 года Google выкатили стандарт DESIGN.md (прототип которого они тизерили ещё в мае 25го года), если кратко, то это такой хитрый markdown-файл для переноса и импорта общих правил оформления дизайна между проектами и инструментами.

Поддержка данного стандарта уже начала расползаться по агентному стеку, у Google есть отдельный репозиторий stitch-skills, где прямо указана совместимость со Stitch MCP и агентами вроде Gemini CLI, Claude Code и Cursor, параллельно с этим вокруг формата уже вырос внешний зоопарк инструментов и гайдов, например designmd.app отдельно пишет про сценарии для Claude Code, Cursor, Kiro, Windsurf и Cline.


DESIGN.md это AGENTS.md, только для UI

Когда мы обсуждали вайбкодерский starterkit для агентов, речь в основном шла про то, как агент должен выполнять работу кодом.

Какие команды запускать.
Какой архитектуры придерживаться.
Какие практики в проекте обязательны.
Чего делать нельзя, а что можно.
В какой последовательности.

То есть AGENTS.md, CLAUDE.md, Cursor Rules и прочие файлы такого рода обычно отвечают на вопрос "как агент должен делать код?".

А вот DESIGN.md отвечает уже на более абстрактный вопрос - "как агент должен делать интерфейс приложения?".


Что внутри DESIGN.md

В официальной идее Google и в уже появившихся примерах вокруг формата почти всегда повторяется один и тот же каркас:

- общее описание визуального характера продукта
- цветовая палитра и роли цветов
- правила типографики
- отступы и layout-принципы
- оформление базовых компонентов
- ограничения и анти-паттерны

Я ещё добавляю всякие хекс коды, размеры отступов, названия CSS фреймворков и тому подобные моменты, плюс в Cursor это хорошо ложится в общий свод правил .cursor/rules/ (можно например создать подпапку design), так как один общий файл для описания стиля всего со временем будет перегружен.


Простейший пример

Вот совсем примитивный DESIGN.md, которого уже достаточно, чтобы агент не улетел в рандом, взял его из официальной доки на сайте Stitch:
# Design System

## Overview
Calm, minimal interface for a SaaS dashboard.
High information density, but without visual noise.
The UI should feel professional, neutral, and slightly premium.

## Colors
- Primary (#2563EB) - primary actions, links, active states
- Surface (#FFFFFF) - main cards and panels
- Background (#F8FAFC) - app background
- Text Primary (#0F172A) - main text
- Text Secondary (#475569) - secondary text
- Border (#E2E8F0) - separators and input borders
- Danger (#DC2626) - destructive actions and errors

## Typography
- Headings - Inter, semibold
- Body - Inter, regular, 14px to 16px
- Small text - Inter, regular, 12px to 13px
- Use tight, readable hierarchy without oversized headings

## Spacing
- Use 8px spacing scale
- Cards should have generous inner padding
- Avoid cramped layouts, but keep density suitable for dashboards

## Components
- Buttons - medium rounding, filled primary for main CTA
- Inputs - light background, 1px border, no heavy shadows
- Cards - subtle border, soft shadow, clean flat surfaces
- Modals - centered, compact, clear action hierarchy

## Do's
- Keep layouts clean and structured
- Use primary color sparingly
- Prefer subtle contrast over aggressive accenting

## Don'ts
- Do not mix multiple accent colors
- Do not use glassmorphism
- Do not use oversized radii
- Do not make the UI look playful

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


Послесловие

Уже есть реп awesome-design-md, в нём собрана хорошая обновляемая подборочка материалов на эту тему, надеюсь она вам тоже пригодится.
🔥16👍97
Ну чтож, обучение модели закончилось на 963 шаге, по предварительным тестам модель уловила шаблон выполнения ризонинга и даже частично логику работы с тулами, но забыла как говорить на русском языке и стала очень быстро уходить в галлюцинации и repetition loop, тут скрипт тестов, вот тут можно посмотреть отчёты, а тут будут веса адаптера.

Эксперимент судя по всему не удался, но зато получилось собрать набор скриптов и кучу шишек набить. вероятно основная причина неудачи в том что у меня был очень кривой пайплайн обучения и надо над ним больше времени провести, плюс модель маленькая и заточена под небольшой контекст и любые мои попытки контекст увеличить сводят модель с ума, или я как-то неправильно через chat_template составил датасет обучения.

В любом случае ещё попробую потестировать ранние адаптеры, может быть там будет результат получше.

UPD. Ну а пока проект ставлю на паузу, хочется заняться чем-нибудь другим, была ещё идея сделать дистил толстушки GigaChat на ruGPT3XL, но это уже как-нибудь потом.
🔥20👍10👏7
Утром тесты, вечером код

Продолжаю делать заметки на полях о тонкостях работы с кодовыми агентами.

Почему я так много внимания уделяю методологиям BDD и TDD, и всегда пишу, что тесты важны и что кодовому агенту тесты стоит генерировать перед кодом?

Дело в том, что из-за особенностей механизма внимания большие языковые модели (LLM) лучше "помнят" информацию, которая находится в контексте ближе к тому, о чём идёт речь прямо сейчас, и "забывает" то, что было в самом начале диалога.

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

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

Вы можете проверить эту концепцию на нескольких разных моделях, обычно запросы выглядят так:
<спецификации фичи>

Но если вы скажете модели перед реализацией фичи что-то типа:
изучи код, документацию и тесты, потом напиши тесты новой фичи, убедись что они падают, потом напиши код фичи, потом убедись что тесты проходят, потом проверь все остальные тесты
<спецификации фичи>

Результат, который получается у агента через разные модели, будет очень похожим, чем когда мы просто описываем фичу.

Агенту важно объяснить не только "что надо делать", но ещё и "как надо делать", тогда и результат будет стабильным и предсказуемым.
1🔥18👍83❤‍🔥1
Pavel Zloi pinned «Когда поднимут цены на ИИ Недавно мне пришлось оказаться на одной лекции, имен называть не буду, но общий настрой выступления можно описать так - человеку показали Claude Code, после чего он искренне поверил, что теперь "бизнесом можно управлять через ИИ"…»
Скилов много, оркестрации мало

Последнее время только и слышу у себя в информационном пузыре разговоры про skills. Сделайте skill на ревью, skill на деплой, skill на парсинг, skill на тесты, skill на документацию. Идея в целом годная, под небольшую задачу пилим небольшой skill с понятным триггером, коротким SKILL.md, парой reference-файлов и скриптами, такая постановка задачи действительно помогает агенту меньше фантазировать и чаще попадать в нужный флоу. Особенно когда такой skill вырос не из абстракции, а из реальной боевой задачи, реальных фейлов и реальных исправлений, типа вот я сижу пилякаю какую-нибудь штукенцию и хочу на будущее её автоматизировать.

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

Ну или чем Гейтс не шутит, собрать рой агентиков для решения одной большой задачи, а дальше каждому актору раздать небольшие задачки и спокойно идти спать/гулять/дебоширить.

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

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

Но как по мне так подход "одна задача - один skill" уже либо устарел, либо вот-вот упрётся в потолок, и не потому, что skills плохие и не нужны, скорее наоборот, хорошие skills очень нужны. Но центр тяжести смещается. Важен уже не только сам skill, а то, кто, когда и при каких условиях его вызывает.

Отсюда и появляется более интересная конструкция, которую я бы назвал скил-оркестратором или если хотите каскад скилов, по аналогии с каскадом классификаторов.


По сути это не один большой skill, который пытается вместить в себя всё, а коллекция маленьких skills со скриптами, шаблонами, reference-файлами и жёстко очерченными границами ответственности. Один skill собирает контекст. Другой читает спецификации. Третий пишет тесты. Четвёртый запускает проверки. Пятый делает ревью результата. Шестой оформляет итог.

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

Эта история как по мне отлично ложится на рой агентов и позволяет делать сложные многоступенчатые задачи (само собой разделённые на небольшие атомарные этапы) при этом не терять контекст и обходить самое главное ограничение модели связанное с механизмами внимания моделей.

И вот такой подход, как мне кажется, намного ближе к будущему агентных систем, чем бесконечное наращивание папки со skills. Skill сам по себе никуда не исчезает. Просто он перестаёт быть главной сущностью. Skill становится модулем. А главной сущностью становится оркестрация.
👍116💯4🥴1