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

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

Поддержать автора:
https://pay.cloudtips.ru/p/937f48ac
Download Telegram
Методы сжатия контекста агентов

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


Английский язык

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

Хотя на самом деле язык может быть не только английский, может быть китайский (если говорим про Qwen, DeepSeek и т.д.) или русский (GigaChat, Vikhr, ruAdapt и так далее), в общем следует использовать в модели тот язык который доминировал в корпусе на котором производилось обучение токенизатора.

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


Фильтрация тулов

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

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

Данный метод полезен когда тулов очень много, например 100+ или скажем много тулов которые выполняют похожие задачи, но немного отличаются друг от друга.


Долгосрочная память

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

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

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


Суммаризация

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

Работает это следующим образом: некий метод или функция принимает messages, считает токены, далее определяет, что количество токенов преодолело некие пороговые значения, если да то после этого она берёт несколько сообщений с конца, допустим все до N-5 от последнего сообщения юзера, сохраняет их, а все остальные отправляет в модель с просьбой выполнить суммаризацию (в промте могут быть разные уточнения как её делать и на что обратить внимание, но суть остаётся прежней). В результате получаем некий ответ с подробным саммари, который мы кладём в начало нового массива messages с ролью assistant, а далее те N-5 сообщений которые мы сохранили. Полученный массив уходит далее.

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


Послесловие

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

А какие методы сжатия контекста используете вы?
2🔥25👍143
Pavel Zloi pinned «Про тесты Вы наверно замечали, разрабатывая вайбкод проекты, одну неприятную штуку: фичи, заложенные на первых итерациях, часто удаляются агентом или ломаются в процессе добавления новых фичей, если у проекта нет никаких тестов. А если тесты есть, они начинают…»
Намедни наткнулся на очень любопытный интерфейс для визуализации пайпланов под названием daggr, от инженеров из Hugging Face.

Данный UI позиционируется как аналог ComfyUI, полез смотреть демки, и пока что кажется, что наконец появился приличный и простой аналог, потому как с комфи работать лично мне крайне неудобно из-за того что это low-code система и вместо того чтобы заниматься творчеством приходится часам искать подходящие ноды в подборках или у блогеров, или писать свои кастомные, а потом мышкой проводить связи.

Для daggr тоже можно писать ноды на python, но они имеют универсальные выходы и входы, точнее какие ноды с какими связаны описывается в python-коде, а не в псевдокоде экспортируемом в JSON-объект. Ну а самое удобное с точки зрения UI - в случае возникновения ошибки на одной из нод возможность не перезапускать весь пайплан, достаточно внести необходимые правки и перезапустить только неисправную ноду. В процессе изучения оказалось, что предполагается работа через апишку на железе HF, но можно и локально запустить.

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

Короче ещё одна полезная штука в копилку технологий.
👍203
Фанаты sgr-agent-core регулярно спрашивают нас, с чего мы взяли, что они наши фанаты?

Уже неделю чувствую себя ненормированно свободным, впервые за долгое время проснулось кодовдохновение. А потому - делюсь! Много мыслей и немного кода.

В чем экзистенциальный ужас платформенной разработки? Приходится поддерживать и учитывать разные платформы, их версии, ограничения. И как бы я ни бегал от мрака версионности, всё-же напоролся на примере sgr core

Итак, проблема:
Фреймворк построен на Structured Output, но его поддерживают далеко не все конфигурации локальных/проприетарных LLM. Что самое страшное, даже если поддерживают, то не всегда однородно! Требуемые JSON схемы могут различаться.
Если фреймворк может работать, а может не работать на неопределённом множестве моделей - это ужасненько.

Structured output(SO) по моему скромному мнению это железная база, без которой сложно представить взаимодействие агентов хаоса вольного контекста и неопределëнных суждений и системы требующей, как правило, некоторой детерминированности, свойственной формальным языкам.


Примеры:
- Кто-то гарантирует ответ строго по формату, а кто-то может допустить ошибки даже при заданной схеме
- Кто-то поддерживает вложенные AnyOf и прочие агрегаты схем, а кто-то нет
- Где-то можно прокинуть ограничения min_length=1, max_length=3, а где-то нет, они в лучшем случае будут проигнорированы
- Кто-то хавает литералы и сопутствующие им enums, а кто-то отказывается

Как общий знаменатель пришла мысля создать решение, которое бы эмулировало независимый от ллмки SO без реальной в нём потребности на стороне провайдера . Идея "попроси модель сделать как надо" далеко не нова, и тем не менее было полезно посмотреть, насколько хорошо и стабильно это могут делать современные LLM


Концепция:
class ToolInstantiator принимает в свой init Pydantic модель, и имеет два основных метода интерфейса:
- Сгенерить промпт с описанием схемы для LLM
- Провалидировать полученный ответ LLM на предмет возможности билда инстанса Pydantic модели
На каждом следующем этапе промпт,выдаваемый классом, учитывает ошибки и проблемы предыдущей итерации, корректируя/фокусируя LLM

Путём некоторых экспериментов было выявлено, что прямая json схема для LLM сложновата ввиду нотации и неконсистентной информации о полях и их типах. А ещё иногда модельки путались и выдавали JSON schema аналогичную промптовой в ответ. Поэтому появился класс-помогатор SchemaSimplifier, разбирающий схему и преобразующий в более минималистичную нотацию

Ещё была интересная концепция, где каждое поле валидировалось по отдельности и даже если модель выдала в общем не полностью корректный JSON, часть верных полей принимались и не требовались на дальнейших итерациях генерёжки. Идея была отброшена ввиду нелицеприятности кодреализации такой фичи.
Лучше никому не видеть мою попытку в конвертацию типов raw context regex parsing -> json string->python type -> pydantic validator

Вот тут реализация - почти хорошо

работает следующим образом
for attempt in range(max_retries):
async with self.openai_client.chat.completions.stream(
messages=messages + [{"role": "user", "content": instantiator.generate_format_prompt()}],
) as stream:
completion = await stream.get_final_completion()
try:
content = completion.choices[0].message.content
tool_instance = instantiator.build_model(content)
return tool_instance
except ValueError:
continue
🥰5👍1
OpenAPI to MCP это врапер между API и MCP

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

Надоело повторяться, решил сделать standalone-сервер, который в формате nocode генерит MCP-сервер по документации из OpenAPI/Swagger, а потом ещё и проксирует запросы из тулов на этот API в соответствии со спеками.

Допустим в документации API есть такие эндпоинты:
- GET /messages
- POST /messages
- GET /status
- GET /users

Прокси конвертирует их в тулы вот с такими именами:
- get_messages
- post_messages
- status
- users

Вызов же тула через MCP превращается в HTTP-запрос к API, ответ API через MCP возвращается обратно пользователю.

Запуск одним контейнером, вот к примеру демка OpenAPI:
docker run --rm -p 3100:3100 \
-e MCP_OPENAPI_SPEC=https://raw.githubusercontent.com/readmeio/oas-examples/refs/heads/main/3.1/json/petstore-simple.json \
-e MCP_API_BASE_URL=http://localhost:8080/v1 \
evilfreelancer/openapi-to-mcp:latest

Полный docker-compose,yaml тут.

Дальше можно подключить этот MCP куда угодно, например в Cursor вот так:
{
"mcpServers": {
"demo": {
"url": "http://localhost:3100/mcp"
}
}
}

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

Исходники: https://github.com/EvilFreelancer/openapi-to-mcp
Docker-образ: https://hub.docker.com/r/evilfreelancer/openapi-to-mcp
120👍11🔥5👏1
Media is too big
VIEW IN TELEGRAM
Подосоветовали утилитку CodeGraphContext, она позволяет проанализировать исходники проекта и построить из них граф кодовой базы, да не простой, а такой с которым можно через MCP подружить любой кодовый агент. Вроде как обещают, что агент должен начать грамотнее генерить код.

Плюс можно по кодовой базе такую вот занятную визуализацию построить, в качестве примера взял мой проект openapi-to-mcp, на вид очень неплохо получилось, дальше попробую повайбкодить его со включенным MCP.
3🔥163👍1
Тестирую API'шку по одному проекту мечты, который я давно откладывал в дальний ящик и вот наконец собрал волю в курсор и за неделю, без лишней спешки запилил прототип системы которая кравлит из телеги и ищет по постам.

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

PS. С апишкой из курсора работаю через openapi-to-mcp проксик.
1🔥25👍6
Обновил описание канала, раньше я был вебмастер, а теперь вайбмастер 😎
2😁2361👍1😢1😐1
Текс, ну что же, пробую запустить мою вторую MCP, на этот раз заточенную на поиск сообщений в телеграм.

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

Система ищет в трёх режимах:
- полнотекстовый поиск
- векторный поиск
- гибритный поиск (полнотекст + вектор, по умолчанию)

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

Пока что каналов не много, около 30, но думаю буду помаленьку добавлять.

Для полнотекста используется ManticoreSearch Engine, она хорошо умеет в bm25, а для векторного поиска.... тоже мантикора, с недавних пор в ней есть поддержка векторного поиска, модельку использую FRIDA (про её запуск тут) использую префиксы search_document и search_query.

Конфиг подключения такой вот:
{
"mcpServers": {
"tg-mcp": {
"url": "https://mcp.rpa.icu/mcp",
"headers": {
"Authorization": "Bearer https://t.me/evilfreelancer"
}
}
}
}

Сервер покажет два тула: telegram_channels и telegram_messages, первый - ищет каналы в базе, а второй - сообщения.

PS. У меня конечно не так эпично как у Валерия @neuraldeep получилось, но мне интересно было именно с нуля нечто подобное запустить )

PPS. Для подключения к апишке кравлера использую openapi-to-mcp проксик, по ходу дела заметил, что описания параметров не передаются, так что накатил на него патчик.
211
Очень хочется рассказать про один небольшой сторонний проект, который я решил попробовать собрать.

Называется штука coddy, это аббревиатура фразы COmmunity Driven Development, Yep.

Идея очень простая: создать бота который сможет следить за репозиторием, ловить задачки пользователей и выполнять запрошенные работы.

Работает бот сейчас так: он следит за issue на github (в планах добавлю gitlab и bitbucket), и если видит, что появилась новая задачка, то создаёт ветку, переключается на неё, запускает кодового агента cursor cli (пока только его, но хочу добавить и другие), кодовому агенту на вход передаётся описание из issue, он выполняет работу, коммитает правки и пушит их в реп, после чего создаёт PR и завершается.

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

Ссылка на реп: https://github.com/EvilFreelancer/coddy

Приглашаю всех принять участие в работе над проектом!
2🏆11👍6😱53
Pavel Zloi
OpenAPI to MCP это врапер между API и MCP На этих выходных уже в который раз пришлось пилить MCP обёртку над API, чтобы подключить его к агенту. Надоело повторяться, решил сделать standalone-сервер, который в формате nocode генерит MCP-сервер по документации…
Чуть прокачал openapi-to-mcp, за неделю зарелизил 6 новых билдов, добавил кучу новых фичей и пофиксил пачку багов.

Вот кратенько, что было сделано:
- теперь спеку можно определить переменной MCP_OPENAPI_SPEC, система сама разберётся файл там или ссылка
- добавил конвертацию дескрипшенов HTML в Markdown, опция MCP_CONVERT_HTML_TO_MARKDOWN, отключено по дефолту
- можно указывать свои инструкции через MCP_INSTRUCTIONS_FILE и менять режим их отображения MCP_INSTRUCTIONS_MODE, по дефолту отображается то что написано в site.description из OpenAPI-конфига
- пофиксил баг с переменными в path, теперь эндпоинты типа /user/{username} система конвертирует в тул user_username

Задействовал это решение уже в десяти моих проектах, развёртывание MCP ещё никогда не было таким простым и удобным.
18🔥5👍1🆒1
Наблюдаю за собой странный эффект, вызванный кодовыми агентами, появилось ощущение бесконечных возможностей которых попросту не было до кодовых агентов, а точнее даже до того как я научился ими эффективно пользоваться, это вызывает в сознании неуемное стремление творить, творить и творить.

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

Какое-то приятное чувство азарта, сложно сравнить это с чем-то ещё, похожее ощущение было когда учился в колледже, когда мир программирования и инженерии казался ещё чем-то загадочным и таинственным.

И если просуммировать эту мысль, то могу сказать, что вайб-код и кодовые агенты открыли второе дыхание.
💯3619👍10💊2🤔1🤡1🤣1
Вчера прям основательно решил поработать над coddy, вместо того чтобы делать по наитию продумал архитектуру дотошно, составил план работ.

1. поизучал аналоги, наткнулся на два прикольных проекта: ralph и ralphy, она они реализуют т.н. ralph-loop, это когда любая задача декомпозируется на шаги и решение её представляется в виде графа, поэтому я решил разделить на две подсистемы, observer смотрит за гитхабом и worker делает вещи.

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

3. перебрался с пуллинга на вебхуки, это очень упростило логику запуска автоматики, на вебхук наблюдателя приходит запрос от гитхаба, в нём вся необходимая информация о том, что произошло (была создана/изменена/закрыта issue, был добавлен/удалён исполнитель, был добавлен/изменен/удалён комментарий в задачке и заглушка для приёма информации о PR).

4. в папке .coddy/ организовал хранилище pr и issue в виде yaml файлов, в них задокументировано всё что происходило с сущностями, изначально думал хранить в markdown, но запарился дебажить их парсер.

5. папка .coddy/ создаётся и рулится в папке workspace, это директория в которой находится git репозиторий и проводится вся работа, иными словами я планирую хранить в индексе репа логи процесса разработки и потом ещё и действия агентов (не подробный вызов тулов, а отчёт что был сделано на текущем шаге)

Делаю всё по BDD, сначала пишу спеки, потом по ним планирую действия и пинаю ИИ.

Вот такой прогресс, думаю за сегодня смогу добить ещё автоматический запуск ralph-loop и прикручу к этому логику создания PR, про мою моё мнение к оригинальной петле и о порочности полной и бесконтрольной автоматизации кодогенерации расскажу в другой раз.
👍13🔥7🤣1
Подал свою первую заявку на участие в конференции AiConf 2026 в роли докладчика.

Хочу выступить с докладом про SGR Agent Core и рассказать широкой аудитории о нашем замечательном проекте.
3🔥55👍10🥰9👏1💅1
OpenAI vs Antropic

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

Но при этом почти все современные модели основаны на том, что сделали спецы OpenAI. На идеологии моделей, которую они продвигали, на спецификациях протоколов, которые они стандартизировали. Да даже UI у многих - это копия, отдалённо напоминающая интерфейс ChatGPT. И самые передовые из публичных моделей - это gpt-oss серия.

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

Но при этом по сравнению с OpenAI они, как бы так сказать, помягче. Почти ничего не выкладывают в паблик, кроме небольших датасетов, постов в блоге с порой интересными картинками и AI slop прототипов на GitHub, иногда даже не рабочих. А моделей в паблике от них, по сути, никогда не было.

В общем есть над чем пофилософствовать.
👍23
Посмотрел за чашечкой кофия "We Studied 150 Developers Using AI (Here’s What's Actually Changed...)". В нём авторы провели исследование с участием 151 профессионального программиста о том, как меняется сложность сопровождения кода. Эту группу разделили на тех, кто пользовался ИИ-агентами, и тех, кто нет. Подробности в работе "Echoes of AI: Investigating the Downstream Effects of AI Assistants on Software Maintainability" (arXiv:2507.00788), вот мой кратенький пересказ.

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

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

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

Исследование показало, что скилл разработчика значит гораздо больше, чем используемые ИИ-агенты: они выступают как множители скилла, но не как замена. И что ИИ-агенты, запущенные без контроля, раздувают кодовую базу и повышают когнитивную сложность.

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

Инструменты важны, но гораздо важнее то, как мы их используем.
💯19👍103
Смотрите какую прелесть https://paperdraw.dev/ я подсмотрел на канале тёзки @toshoseti

Если кратко то этот сайт позволяет симулировать архитектуру приложения, при помощи простых блоков там можно описать схему вашего приложения, описать линии связи между блоками, логику работы очередей, можно даже логику работы ИИ-агентов описать.
👍12🔥62🥱1🗿1
Тихо и незаметно проект SGR Agent Core преодолел планку в 1000 звездочек на GitHub.
1👍38❤‍🔥13🤯32💯1
Частично закрыл старую боль в своём проекте docker-routeros (релиз проекта был ещё в 2018м, омг), ну и так вот, с самого начала там не было нормального способа сохранять данные между перезапусками контейнера и сменой версий RouterOS в VDI-образах.

В issue #63 люди как раз спрашивали, как сохранять конфиг и данные. Поигрался с разными вариантами и в итоге сделал так, что второй диск подключается как raw-образ (файл disk2.raw в каталоге /data). QEMU монтирует этот образ на старте, затем надо один раз в RouterOS форматнуть этот диск в ext4, дальше он виден в /file. На него можно складывать бэкапы, файлики, скрипты или логи - всё это переживает перезапуски и обновления образа.

Не идеально конечно, образ системы по-прежнему в контейнере, а вот свои файлы уже можно хранить отдельно.
6
Ну так вот, к чем я про RouterOS-то внезапно так вспомнил, решил я настроить MCP-сервер, чтобы агент мог моим домашним роутером рулить, а у RouterOS c 7й версии было добавлено REST API, но к сожалению без Swagget/OpenAPI спецификаций, поэтому пришлось гуглить, нашёл вот этот реп https://github.com/tikoci/restraml в нём помимо доков была ссылка на сайт https://tikoci.github.io/restraml/ на котором можно легко и просто найти ссылочку на нужные мне спеки. Тестовый стенд решил собрать на виртуалке, взял ессно мои docker-routeros.

Подготовил такой вот .env для openapi-to-mcp:
MCP_API_BASE_URL=http://192.168.1.21:8080/rest  # тут у меня виртуалка с RouterOS 7.20.8
MCP_API_BASIC_AUTH=admin:
MCP_OPENAPI_SPEC=https://tikoci.github.io/restraml/7.20/extra/oas2.json
MCP_TOOL_PREFIX=routeros_
MCP_SERVER_NAME=MikroTik RouterOS MCP
MCP_LOG_LEVEL=DEBUG
MCP_INCLUDE_ENDPOINTS=get:/interface,get:/interface/bridge

Запускаю контейнер c MCP-прокси и вижу в логах красоту...

В курсоре и других клиентах подключаю вот так:
{
"mcpServers": {
"mikrotik-mcp": {
"url": "http://localhost:3100/mcp"
}
}
}

Далее можно вызывать тулы типа routeros_interface или routeros_interface_bridge, как в моём примере, но можно ещё тулов добавить, просто всего через REST публикуется примерно 6000 тулов и MCP сервер крашится, поэтому надо выбирать только то что нужно.
🔥8👍1🤯1