Искусство. Код... ИИ?
420 subscribers
22 photos
4 videos
1 file
71 links
Канал @vkochetkov о прекрасном (и не очень) вокруг кода, ИИ и безопасности приложений.

FAQ: https://t.me/art_code_ai/7
Download Telegram
💻 Уязвимость в cgo (CVE-2025-61732): и снова парсеры

В Go 1.25.7 и 1.24.13 разработчики устранили пару уязвимостей, одна из которых оказалась на мою любимую парсерную тему ☺️

Уязвимость была в стандартном инструменте cmd/cgo — компоненте Go, позволяющем Go-коду взаимодействовать с кодом на C. Из-за расхождений в правилах разбора комментариев между компиляторами Go и C атакующий мог скрыть фрагменты C-кода внутри комментариев. Такие фрагменты игнорировались компилятором Go, но воспринимались как исполняемый код компилятором C, встраиваемым в итоговый бинарник.

Уязвимость проявлялась в механизме обработки doc-комментариев в cgo. Ранее cgo включал (и весьма криво) пользовательские комментарии из исходников Go в генерируемые заголовочные файлы для сишки, из-за чего было возможно нарушить границы комментария в выходном C-коде и внедрить туда выполняемые строки. Например, вставить символы закрытия/открытия комментария */ и /* внутри строки, начинающейся как комментарий Go. В Go такая строка полностью игнорируется (как комментарий //), но в сгенерированном коде Си она была бы преобразована в активный код.

Выглядит это могло как-то так:

// */ system("rm -rf /"); /* 
//export Func1
func Func1() {}


Здесь строка с // */ system("rm -rf /"); /* интерпретируется Go как комментарий и полностью пропускается. Однако утилита cgo при генерации C-кода убирала префикс //, либо заменяла его на /* (видимо для того, чтобы объединять в один большой многострочный коммент несколько однострочных). В итоге в C-код здесь попадет скрытая от гошных SAST'ов команда system("rm -rf /");.

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

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

TL;DR: В свежих версиях Go пофикисили парсерную уязвимость в cgo, позволявшую внедрить в генерируемые заголовочные C-файлы произвольный код через гошные комментарии.
Please open Telegram to view this post
VIEW IN TELEGRAM
57👾2👏1
💻Средства разработки ИИ-агентов на Go

Что делать, если, устав обкладывать свой Python-код линтерами, тайпчекерами и избыточными тестами, решили свалить на Go, а разрабатывать ИИ-агентов всё ещё нужно? Ниже — подборка библиотек и фреймворков, которые помогут продолжить этим заниматься на Go.

Агентные фреймворки (на выбор):

🌟 LangChainGo (tmc/langchaingo)

Go-порт LangChain с упором на композицию: цепочки, агенты, память, инструменты и интеграции для LLM-приложений. Умеет в агенты/инструменты/память; поддержку нескольких LLM/провайдеров; векторные хранилища.

🌟 Eino (cloudwego/eino)

Go-first фреймворк для LLM/AI-приложений, явно ориентированный на Go-конвенции и вдохновлённый LangChain и другими подходами. В наличии композиция пайплайнов (графы/цепочки); инструменты и агентные workflow блоки; экосистемные интеграции; визуальный дебаг/инспекция узлов и оркестрации.

🌟 tRPC-Agent-Go (trpc-group/trpc-agent-go)

Ещё один фреймворк для построения агентных систем на Go, с фокусом на LLM+tools. Поддерживает автономные/полуавтономные агенты; планировщики (в т. ч. иерархические); долгоживущую память/состояние; телеметрию; управление исполнением инструментов с возможностью внешнего выполнения.

🌟 Blades (go-kratos/blades)

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

Библиотеки:

🌟MCP Go SDK (modelcontextprotocol/go-sdk)

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

🌟tiktoken-go (pkoukk/tiktoken-go)

Порт OpenAI tiktoken на Go для быстрых BPE‑токенизаций и подсчёта токенов: оценка стоимости, контроль лимитов контекста, чанкинг документов и предотвращение отказов по превышению токенов.

Официальные SDK:

🌟OpenAI Go SDK (openai/openai-go)
🌟Go OpenAI (sashabaranov/go-openai)
🌟Anthropic Go SDK (anthropics/anthropic-sdk-go)
🌟Google Gen AI Go SDK (googleapis/go-genai)
🌟AWS SDK for Go v2: Bedrock (github.com/aws/aws-sdk-go-v2)
🌟Azure OpenAI extensions module for Go (Azure/azure-sdk-for-go, azopenai)

Клиенты векторных БД:

🌟Qdrant Go Client (qdrant/go-client)
🌟Pinecone Go SDK (pinecone-io/go-pinecone)
🌟Weaviate Go Client (weaviate/weaviate-go-client)
🌟pgvector-go (pgvector/pgvector-go)

Локальный инференс:

🌟 Go llama.cpp bindings (go-skynet/go-llama.cpp)

Высокоуровневые биндинги для Go к llama.cpp — производительной библиотеке с открытым исходным кодом, написанной на плюсах, и предназначенной для локального инференса LLM.

🌟Ollama (ollama/ollama)

Легковесная, расширяемая высокоуровневая оболочка llama.cpp для создания и запуска языковых моделей локально, хорошо интегрирующаяся с Go-проектами.

🌟LocalAI (mudler/LocalAI)

Альтернатива, дающая «drop-in replacement» REST API, совместимый с OpenAI‑подобными спецификациями. Поддерживает мультимодальность; агентную совместимость через Open Responses API; и Anthropic API.

А ещё больше подобного — здесь.

TL;DR: Просто сохраняем в избранное ☺️
Please open Telegram to view this post
VIEW IN TELEGRAM
10👀322👍1
Пусть на этом канале будет своя, особенная валентинка 🤗 Код сложил сюда.

P.S: Чуть доработал прошлогоднюю консольную версию, да 🙈
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
1017❤‍🔥2
Как разработчику быстро углубиться в тему LLM? Часть 2

Часть 1.

2. Механизм внимания (self-attention)

Вопрос на разминку: как во фразе «Data visualization empowers users to» понять, что слово empowers относится к visualization? В трансформерах за такие зависимости отвечают механизмы внимания.

Сами трансформеры разберём в следующей части, а пока достаточно знать следующее: это нейросеть для работы с последовательностями (текст, аудио, ДНК и т.д.), которая обновляет представление каждого токена слоями. В обучении/обработке готовой последовательности это делается параллельно по всем токенам; в генерации текста новые токены добавляются шаг за шагом (autoregressive), но внутри каждого шага операции параллельные.

Ключевая операция внутри слоя — self-attention: способ «взвесить» для каждого токена, какие другие токены в контексте ему сейчас важны, и собрать из них непосредственно контекст. Для каждого токена линейными преобразованиями вычисляются три вектора:

• Query (Q): «что я сейчас ищу в контексте?»
• Key (K): «по каким признакам меня можно найти/со мной сопоставиться?»
• Value (V): «какую информацию я передаю, если на меня "посмотрят"?»

Как считается self-attention, по шагам:

1️⃣ Dot product (оценка совместимости): для каждого токена берут его Query и считают скалярные произведения со всеми Key остальных токенов. Получается матрица «оценок внимания» размера n×n (n — длина последовательности).

2️⃣ Scaling (масштабирование): оценки делят на √dₖ, где √dₖ — размерность Key/Query в одной голове внимания.
Зачем это нужно: без деления разброс значений Q·Kᵀ растёт с dₖ softmax начинает «насыщаться» (почти 0/1), и обучение/градиенты становятся менее стабильными.

3️⃣ Mask (маскирование): перед softmax часто запрещают некоторые связи, выставляя им очень большие отрицательные числа (эквивалент −∞), чтобы после него они получили почти нулевой вес. Два самых частых случая:
• padding mask: игнорировать токены-паддинги;
causal mask: в генерации текста запретить смотреть в будущее (токен i видит только позиции ≤ i).

4️⃣ Softmax (и иногда dropout): превращает оценки в нормированные веса (распределение внимания), которые суммируются в 1 по строке — для каждого «смотрящего» токена.

5️⃣ Взвешенная сумма Values: веса умножают на V и суммируют — получается контекстный вектор для каждого токена: он содержит информацию о других токенах пропорционально их важности.

Формально:
Attention(Q,K,V) = softmax(Q·Kᵀ / √dₖ) · V,
где T — транспонирование (чтобы Q·Kᵀ дало матрицу n×n).

Зачем вниманию несколько голов (multi-head)?

Одна голова — это один «взгляд» на последовательность: свои матрицы проекций для Q/K/V и свои веса внимания. Multi-head attention делает такие «взгляды» параллельно: каждая голова считает attention независимо, затем выходы голов конкатенируются и проходят через выходную линейную проекцию (W^O). Практический смысл: разные головы могут подхватывать разные типы зависимостей (локальные, дальние, синтаксические/семантические шаблоны), и итоговый контекст получается богаче.

Наивная реализация self-attention опирается на матрицу n×n, поэтому вычислительная природа операции квадратичная по длине контекста. По памяти квадрат возникает, когда мы явно материализуем/храним attention-матрицу (веса). В продакшене часто используют оптимизированные подходы (например, FlashAttention), которые уменьшают пиковую память за счёт того, что не пишут всю матрицу внимания n×n в глобальную память. В autoregressive inference LLM обычно кэшируют K и V для уже сгенерированных токенов (KV-cache), чтобы не пересчитывать их на каждом шаге. Этот кэш растёт линейно с длиной контекста и на больших окнах часто становится главным потребителем памяти на инференсе. Как прикинуть потребление памяти KV-cache для заданной модели и длины контекста хорошо описано здесь.

✍️ На правах домашнего задания стоит изучить следующие материалы:

The Annotated Transformer
Attention? Attention!
FlashAttention
Краткая история механизма внимания в NLP

... и обязательно поиграться с левой частью интерактивной визуализации 🦄
Please open Telegram to view this post
VIEW IN TELEGRAM
106👍1💯1
Agentity: самомодифицирующийся ИИ-агент

В эфире рубрика «потому что могу» 🦄

Набросал игрушечного (~350 строк кода) ИИ-агента для решения примерно всех задач. Ну... в теории 😬 Из коробки эта кроха умеет только читать собственный код, модифицировать его (преимущественно — добавляя себе реализации новых инструментов, необходимых для достижения цели), и рестартовать с сохранением контекста, чтобы подтягивались сделанные изменения.

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

Задачи «на смекалочку» хорошо решает только с большими моделями, типа gpt-5.2, deepseek и т.п. Увы, но их младшие локальные братья зачастую просто не вдупляют, как им могут помочь доступные на старте три инструмента, несмотря на всё, написанное в системном промпте. Тут и сам промпт оптимизировать надо, и структурированный вывод прикручивать (SGR здесь прям напрашивался, но сразу сделать было лень), и нормальный планировщик запиливать. Ну, или дотошно расписывать в формулировке задачи, как связана модификация кода агента с достижением поставленной цели.

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

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

Но, блин, оно работает 🎉 А лежит — здесь.

В комменты скину логи с примерами работы.
Please open Telegram to view this post
VIEW IN TELEGRAM
50🔥91👍1
🎲 Вайб... ресёрчинг?

Вдохновленный OpenSpec'овским opsx-explore (скилл для исследований перед разработкой спеки), сделал его вайбовую версию для ненапряжных ресёрчей по вечерам, когда совсем нехрен делать хочется прекрасного, а думать лень. Воркфлоу предельно простой:

1️⃣ Обозначаете общую тему ресёрча.
2️⃣ ИИ собирает релевантную инфу в сети, обогащает ею контекст, предлагает варианты, и задает уточняющие вопросы.
3️⃣ Отвечаете на вопросы, корректируете текущий вектор мыси на древе, если нужно.
4️⃣ Всё повторяется с шага 2, пока не надоест.

Работает, как часы ☺️ Воткнул его в QoderWork (на скрине, рекомендую — реально хороший агент для повседневных задач, с песочницей и тулами).

В комменты скину SKILL.md, в нём стоит поправить имена тулов для поиска в сети и скачивания контента, если захочется использовать в другом агенте. В теории, ничего не мешает и просто воткнуть текст оттуда в промпт условного ChatGPT, если что.
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥6👍32
🧩 Мой набор кастомных агентских скиллов

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

• vibe-research — скилл из предыдущего поста;
• scamper — трансформация идей по методике SCAMPER;
• explore — обобщенная под произвольные темы ресёрчей версия /opsx-explore из OpenSpec;
• triz-solver — ресёрч через ТРИЗ.

Позднее буду туда докидывать также и скиллы для разработки и прочих смежных задач R&D (сейчас они гвоздями прибиты к моим воркфлоу в Qoder'е, как дойдут руки отвязать — так сразу).
Please open Telegram to view this post
VIEW IN TELEGRAM
14👍103😱1
This media is not supported in your browser
VIEW IN TELEGRAM
Всех подписчиц — с чудесным весенним праздником! 🫶🌷

P.S: код того, что на видео, сложил здесь, если что.
Please open Telegram to view this post
VIEW IN TELEGRAM
512🔥4👍3🥰2
This media is not supported in your browser
VIEW IN TELEGRAM
Вы как, слушаете подкасты? Мне нравится и послушать, и поговорить. Недавно вот, был в гостях у подкаста «В SREду на кухне», который ведут инженеры Avito. Обсуждали, как безопасность влияет на надёжность, где чья зона ответственности и в какой момент разработки уже пора думать о безопасности.

Посмотреть и послушать можно на YouTube, VK Video, RuTube или на странице подкаста.
10👍87🔥5💯3
Тут нечаянно (но зато с душой и в лучших чувствах) родилась вот такая незатейливая утилитка, позволяющая мониторить качество соединения к заданному хосту и фиксировать все отклонения на дашборд и в логи.

Возможно, кому-то окажется полезной 🙈
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥14😁1
🤏 Как рассуждают кодинг-агенты?

Почему (например) Cline, OpenCode и Claude Code дают настолько разные по полноте и качеству результаты на одной и той же LLM? И почему нетривиальный код, написанный тупо в чате с ChatGPT, почти всегда не заводится с нескольких попыток? Дело здесь не только и не столько в промптах, сколько в модели рассуждений (ризонинге), реализованной в конкретном агенте или чат-боте. Ну и ещё в механизмах управления контекстом, которые, тем не менее, напрямую зависят от ризонинга.

В основе большинства современных агентов лежит композиция нескольких паттернов ризонинга: ReAct задаёт базовый цикл рассуждения и действия, Chain-of-Thought структурирует внутренние рассуждения, Plan-and-Execute разделяет стратегическое планирование и тактическое исполнение, а Reflexion обеспечивает самокоррекцию через вербальную рефлексию.

1️⃣ ReAct: фундаментальный цикл рассуждения и действия

Паттерн ReAct (Reasoning + Acting) является основой практически каждого кодинг-агента. Ключевая идея состоит в том, что на каждом шаге агент генерирует либо «мысль» — свободный рассуждательный трейс, не влияющий на среду, — либо «действие» — вызов инструмента или команду, которая порождает наблюдение из среды.

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

В контексте кодинг-агентов цикл ReAct отображается естественно: мысль — «нужно найти функцию, обрабатывающую аутентификацию», действие — grep -r "def authenticate" src/, наблюдение — список найденных файлов. Далее: мысль — «файл auth.py содержит релевантный код, нужно его прочитать», действие — open auth.py, наблюдение — содержимое файла. И так далее до решения задачи.

Сильные стороны ReAct — интерпретируемость, приземление, гибкость. Ограничения — давление на контекстное окно, чувствительность к качеству примеров в промпте и риск зацикливания без явных механизмов завершения.

2️⃣ Chain-of-Thought: структурирование внутреннего ризонинга

Chain-of-Thought (CoT) заставляет модель генерировать промежуточные шаги рассуждения перед финальным ответом. Для генерации кода это означает, что модель сначала рассуждает об алгоритме, структурах данных и граничных случаях, а затем пишет код.

Однако стандартный CoT — это однопроходный процесс без взаимодействия со средой. В кодинг-агентах он играет роль «внутреннего монолога» внутри каждого шага ReAct-цикла: перед тем как выбрать действие, агент проходит через цепочку рассуждений. Именно здесь появляются специализированные варианты CoT для кода.

Structured CoT (SCoT) ограничивает рассуждения программными конструкциями — последовательностью, ветвлением и циклом, зеркально отражая структуру исходного кода. Semantic CoT (SeCoT) направляет модель рассуждать о потоке данных и потоке управления перед генерацией кода, что особенно полезно для задач с нетривиальной логикой. Intention CoT (ICoT) фиксирует алгоритмическую суть и временную сложность до написания кода.

В архитектуре кодинг-агента CoT — не столько самостоятельный паттерн, сколько элемент, встраиваемый в каждый шаг ризонинга внутри ReAct-цикла. Его роль — повысить качество отдельного рассуждения, но без обратной связи из среды он бессилен перед ошибками, которые обнаруживаются только при исполнении.

Продолжение — в следующем посте.
Please open Telegram to view this post
VIEW IN TELEGRAM
47👍3💯1
Продолжение...

3️⃣ Agent-Computer Interface: циклы использования инструментов

Если ReAct задаёт абстрактную схему, то циклы использования инструментов (tool-use loops) наполняют её конкретикой. Кодинг-агент взаимодействует с файловой системой, терминалом, LSP (Language Server Protocol), браузером и интерпретатором кода в итеративных циклах: наблюдение текущего состояния → ризонинг → выбор инструмента и аргументов → исполнение → получение результата → обновление контекста.

Ключевое открытие, определившее направление всего поля, было сделано в SWE-agent: интерфейс между агентом и его инструментами столь же важен, как и базовая модель. Авторы ввели понятие Agent-Computer Interface (ACI) — набора специально спроектированных команд (open, edit, search_dir, find_file), оптимизированных для восприятия LLM. Например, команда edit автоматически проверяет синтаксис и отклоняет некорректные правки, показывая агенту, что пошло не так.

Отдельно стоит упомянуть RepairAgent — первый полностью автономный LLM-агент для ремонта программ, где агент свободно перемежает сбор информации, подготовку патчей для исправления и валидацию, управляемый формальным конечным автоматом.

Ещё один интересный результат был получен в Live-SWE-agent: агент стартует с минимальным набором инструментов (только bash) и автономно эволюционирует собственный скаффолдинг в процессе работы, адекватно поставленной цели. Собственно, agentity был сделан под влиянием именно этой работы, хотя ризонинг там и ограничивается пусть и специализированным, но весьма примитивным ReAct'ом.

4️⃣ Plan-and-Execute: разделение стратегии и тактики

Паттерн Plan-and-Execute (P-t-E) разделяет процесс на две фазы: сначала модель формирует план (последовательность шагов), затем последовательно исполняет каждый шаг. В кодинг-агентах это часто выглядит как: понять задачу, локализовать релевантный код, спланировать изменения, реализовать изменения, проверить тестами, итерировать при необходимости.

Ключевые варианты: статический P-t-E (план фиксирован), динамический реплэнинг (план пересматривается после каждого шага на основе результатов), иерархическое планирование (цели → подзадачи → конкретные действия) и DAG-based execution, где независимые шаги исполняются параллельно.

5️⃣ Reflexion: вербальное обучение с подкреплением

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

Архитектура включает три компонента: Актор (генерирует действия в ReAct-стиле), Оценщик (сигнал о качестве траектории — тесты прошли/не прошли, ошибки компиляции), Рефлектор (анализирует неудачу и генерирует вербальную рефлексию).

Reflection-Driven Control идёт ещё дальше, встраивая рефлексию непосредственно в процесс генерации: агент непрерывно запускает внутренний цикл рефлексии, который мониторит и оценивает его собственный путь принятия решений, извлекая релевантные примеры ремонта и руководства по безопасному коду из эволюционирующей рефлективной памяти.

OmniReflect вводит иерархическую рефлексию: из опыта множества задач дистиллируется «конституция» — компактный набор руководящих принципов, которые переносятся между задачами.

Как паттерны композируются в реальных системах

Кодинг-агенты используют композицию этих паттернов. Общая тенденция: Plan-and-Execute на макроуровне для декомпозиции задач, ReAct на микроуровне для каждого шага исполнения, CoT внутри отдельных шагов рассуждения, tool-use loops для приземления в реальность, и Reflexion для самокоррекции при неудачах.

Но дьявол здесь, как водится, в деталях, которые в итоге и определяют качество «выхлопа» агента: как именно реализован ReAct, чем ограничен CoT и каков он, развит ли Reflexion до re-plan, реализован ли DAG в P-t-E и каким образом и т.п.

Если пост вызовет достаточный интерес, попробую подготовить разбор подходов к ризонингу и контекст-менеджменту, реализованных в конкретных кодинг-агентах.
Please open Telegram to view this post
VIEW IN TELEGRAM
211👍8💯2
🥸 Как рассуждает Claude Code?

Как и обещал, рассмотрим подходы, применяемые в реальных решениях. Было бы странно начать не с Claude Code, чей внезапный и незапланированный врыв в мир опенсорса, вчера анонсировали все релевантные каналы.

Архитектура CC основана на 3 типах агентов и 3 механизмах их работы.

Агенты:

• Встроенные (tools/AgentTool/built-in/): generalPurposeAgent — универсальный, Explore — только для чтения кода, и Plan — планировщик.

• Пользовательские — загружаются из .claude/agents/*.md.

• Плагинные — регистрируются через систему плагинов.

Механизмы:

coordinator/coordinatorMode.ts реализует режим, при котором агент-координатор делегирует работу агентам-воркерам.

tools/AgentTool/forkSubagent.ts реализует механизм FORK_SUBAGENT. Субагент наследует полный родительский контекст. Режимы fork и координатор взаимно исключают друг друга.

utils/swarm/spawnInProcess.ts и utils/swarm/inProcessRunner.ts реализуют поддержку механизма, позволяющего запускать рой агентов (по сути — ролевую команду исполнителей).

На всем этом строятся используемые CC подходы к ризонингу.

ReAct: центральный цикл рассуждения, реализован в query.ts:L241-1728, и состоит из обычного «наблюдение→мышление→действие». Действия при этом могут выполняться параллельно, распределяясь по батчам.

Plan & Execute: активируется командой /plan в commands/plan/plan.tsx. В этом режиме модель записывает план в plan.md, пользователь проверяет и одобряет его перед выполнением.

В commands/ultraplan.tsx предусмотрен также более мощный режим Ultraplan, использующий облачные сессии для работы по схеме: «удалённая сессия→мультиагентное исследование→декомпозиция→одобрение→выполнение».

В skills/bundled/batch.ts реализован скилл пакетного выполнения: фаза 1 — исследование и планирование, фаза 2 — декомпозиция на независимые единицы для параллельного выполнения.

Явная реализация CoT отсутствует, CC полагается на возможности своих моделей и имеет три режима: автоматический выбор между следующими двумя, явное включение мышления с лимитом токенов и явное отключение. По аналогии с UltraPlan агент также умеет в UltraThink, увеличивающим бюджет токенов при явном включении, а также — в уровни усилий мышления моделей (utils/effort.ts).

RAG'и, графовые модели кода и т.п. в агенте также отсутствуют. Для быстрой навигации по коду используется tools/AgentTool/built-in/exploreAgent.ts полагающийся на ripgrep (tools/GrepTool/GrepTool.ts) и тулу для чтения файлов (tools/FileReadTool/FileReadTool.ts).

В memdir/memdir.ts также реализована семантическая память: файлы хранятся в ~/.claude/projects/<slug>/memory/, точкой входа служит MEMORY.md. За отбор воспоминаний отвечает memdir/findRelevantMemories.ts: модель выбирает топ-5 наиболее релевантных записей для текущего запроса. Сессионная память реализована в services/SessionMemory/sessionMemory.ts, хранится в ~/.claude/projects/<slug>/session_memory/<sessionId>.md и работаает аналогично семантической, но в рамках конкретной сессии.

А native-ts/file-index/index.ts реализует индексацию кода с нечётким поиском на основе алгоритма Nucleo, применяющим бонусы за совпадение по границам слов, camelCase-совпадения, последовательные совпадения символов, и штрафующим тестовые файлы.

В CC также есть забавный механизм «снов» autoDream (services/autoDream/ для регулярного обогащения семантической памяти новыми знаниями о проекте.

Оффтопиком стоит упомянуть распиаренную команду commands/security-review.ts, по факту представляющую собой промпт в ~200 строк, полагающийся на работу с кодом, как с текстом. И вот к этому есть вопросики, поскольку в больших проектах, протянуть контекст по той же тейнт-модели от сорса к синку, оперируя кодом, как текстом, весьма непросто. Даже примитивная формальная модель кода в виде графа вызовов — уже могла бы улучшить качество ревью в разы (про PDG/CPG скромно промолчу).

TL;DR: архитектура с реализацией достаточно стандартные и незамысловатые (но в этом и их прелесть). Из оригинальных решений стоит выделить роевой запуск агентов, движок сна, и подход к индексации кода и поиску с Nucleo.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍101💔1
Разбор CVE-2025-15031

В понедельник мы публиковали таск про реальную уязыимость в MLflow. Сегодня разбираем, что там произошло, почему это опасно и как это починили (три месяца чинили, кстати).

Вот уязвимый код ещё раз:


def extract_archive_to_dir(archive_path, dest_dir):
os.makedirs(dest_dir, exist_ok=True)
with tarfile.open(archive_path, "r") as tar:
tar.extractall(path=dest_dir)


А вот ссылка на репорт: https://huntr.com/bounties/09856f77-f968-446f-a930-657d126efe4e

Проблема кроется в последней строке: tarfile.extractall() распаковывает архив, доверяя путям файлов внутри него. А эти пути — просто строки, которые записал тот, кто создавал архив, т.е. потенциальный злоумышленник.

Ничто не мешает ему положить в архив файл с именем ../../config/settings.py или /etc/cron.d/backdoor. Python при распаковке честно создаст его именно там, где сказано.

Это атака Tar Slip — та же механика, что и Zip Slip, только для .tar.gz. И она в целом классическая: сама документация Python помечает extractall() как небезопасный метод начиная с 3.12. Но код был написан раньше, и никто не обратил внимания. OpenSource, hah?

Давайте теперь поговорим про патч. Разработчики MLflow написали отдельную функцию check_tarfile_security(), которая проверяет каждый файл в архиве до распаковки. Она блокирует три сценария:

1. Абсолютный путь


/etc/cron.d/mlflow-backdoor


Файл с абсолютным путём записывается именно туда, игнорируя dest_dir полностью.

2. Path traversal через `..`


../../.env
../../app/config.py


Классика — выход за пределы целевой директории через .. в имени файла.

3. Traversal через симлинк

Это самый хитрый вектор. В архив кладётся симлинк escape -> .., а потом файл escape/pwned.txt. При наивной проверке путь выглядит безобидно — никаких .. в имени. Но физически файл окажется за пределами директории назначения, потому что симлинк выводит наружу.

Именно поэтому в патче два прохода по членам архива: сначала собирается множество всех симлинков, потом проверяется, не ведёт ли путь файла через один из них.

И вот как выглядит исправление


def check_tarfile_security(archive_path):
with tarfile.open(archive_path, "r") as tar:
symlink_set = set()

# Первый проход: собираем все симлинки
for m in tar.getmembers():
path = posixpath.normpath(m.name)
if m.issym():
symlink_set.add(path)
else:
# Блокируем абсолютные пути
if path.startswith("/"):
raise MlflowException(f"Absolute path is not allowed: {path}")
# Блокируем path traversal
if path.split("/")[0] == "..":
raise MlflowException(f"Escaped path is not allowed: {path}")

# Второй проход: проверяем пути через симлинки
for m in tar.getmembers():
if not m.issym():
path_parts = posixpath.normpath(m.name).split("/")
for prefix_len in range(1, len(path_parts) + 1):
prefix = "/".join(path_parts[:prefix_len])
if prefix in symlink_set:
raise MlflowException(
f"Path goes through a symlink, not allowed: {m.name}"
)


И одна строка в extract_archive_to_dir:


def extract_archive_to_dir(archive_path, dest_dir):
check_tarfile_security(archive_path) # <- вот и весь фикс снаружи
os.makedirs(dest_dir, exist_ok=True)
with tarfile.open(archive_path, "r") as tar:
tar.extractall(path=dest_dir)


В контексте MLflow жертва часто даже не знает, что запускает чужой артефакт — модели регулярно обновляются и загружаются автоматически. А сам MLflow нередко работает с широкими правами, потому что ему нужен доступ к S3, базам и GPU-инфраструктуре.

Встречали ли Вы когда-нибудь похожие места в своём коде, где архивы распаковываются без проверки путей? А может, даже писали что-то подобное?🫣
🔥3👍1
🤭 Да или нет вайб-кодингу?

На днях участвовал в дебатах на сабжевую тему, в рамках конференции Data Fusion. И остался под впечатлением, скажем так.

Меня пугают некоторые CTO (благо хоть — из других компаний), которые уже сейчас готовы пересадить всех своих разработчиков на кодинг исключительно с помощью агентов, а всех несогласных — уволить, и заменить ИИ.

Я не луддит. Последние 7-8 месяцев, число строк кода, которые мне пишет ИИ, исчисляется тысячами, иногда — десятками тысяч в месяц. Я перепробовал туеву хучу решений, от Claude Code до весьма недооцененного Oh-My-Pi, плотно поработав с каждым на реальных проектах минимум неделю-две, чтобы решить для себя вопросы его применимости.

ИИ-кодинг прекрасно работает для PoC и MVP, внутренних утилит, быстрой проверки гипотез — везде, где стоимость ошибки низкая. Неплохо справляется и с boilerplate-кодом: ИИ сейчас вполне способен запилить по mockup'ам добротный фронт и грамотного подвязать его к запиленному им же бэку, на уровне чуть выше тривиального CRUD, спрятанного за REST API. Ок. Искренне рад за тех, у кого работа сводится только к этому.

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

Качество ИИ-кода у более сложных задач, чем обычный веб, ещё и с непростой логикой и алгоритмами, контролем доступа и параллельными вычислениями — вообще отдельная (и весьма печальная) тема. Говорю это, как тот, кто именно такими задачами и занимается 😢

Иллюзия готового продукта

Главный риск ИИ-кода — не в том, что он плохой, содержит баги, уязвимости и т.п. В том-то и беда, что он выглядит убедительно хорошим. Агент выдаёт что-то, что компилируется, проходит тесты, рендерит красивый UI. И возникает непреодолимый соблазн пустить это в прод, не заглядывая внутрь. Тем временем, с точки зрения, как функциональности, так и стабильности с безопасностью, там всё... «альтернативно».

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

Cost-to-deliver vs cost-of-ownership

Все говорят: ИИ снижает стоимость разработки. И это правда — cost-to-deliver падает. Но вот cost-of-ownership — нет. Эксплуатация, поддержка, инциденты, комплаенс. Если ИИ-код не проходит через тот же девсекопс-пайплайн... исследования по-прежнему показывают, что он содержит уязвимости чаще, чем написанный опытными разработчиками. Так это точно дешевле? Или просто кто-то внутрь не заглядывал?

Инженер ≠ оператор промптов

Человек, который виртуозно промптит, но слаб без AI — это инженер? Я считаю — нет. Инженер — тот, кто понимает, почему код работает, а не только что он делает. Кто может объяснить, почему в промпте или ризонинге были приняты те или иные решения, по всем аспектам. ИИ снижает порог входа в написание кода — это прекрасно. Но не в предметную область. И теперь нужно не просто писать код, а уметь промптить чуть выше уровня «сделай мне збс», писать спеки, и обеспечивать качество кода, который ты не писал сам.

За любой инцидент отвечать потом придется всё же человеку, а не ИИ.

Возможно, через 2-3 года инженерам вообще не нужно будет смотреть в ИИ-код и разбираться в нём. Мне бы очень хотелось, чтобы однажды это стало возможным. Но сейчас «попромптил и задеплоил» звучит так же дико, как «я не пишу тесты — и так работает».

Поймите правильно, я не против ИИ-кодинга. Сам — могу, умею, практикую: прототипирую, экспериментирую, кайфую от скорости, пропускаю через всё это десятки идей в день, и готовлю их для прода. Но между «ИИ-кодом, который работает» и «кодом, который можно влить в продукт» — пока ещё пропасть.

TL;DR: ИИ-кодинг сейчас — ок, но без зрелых процессов, построенных вокруг него, с учетом всей его специфики и сопутствующих рисков — чистое безумие. Или непрофессионализм, тут уж кому как.
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥17👍9💯6
🤤 Как рассуждает OpenCode?

Рассмотрев особенности мышления закрытого (нет) Claude Code, рассмотрим наиболее популярный среди реально открытых OpenCode (далее — OC).

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

В основе цикла рассуждений лежит всё тот же классический ReAct. Каких-либо принципиальных отличительных особенностей, которые стоило бы отметить, нет. А вот реализация Plan & Execute заслуживает внимания. Режим планирования здесь реализован, как отдельный агент plan с мультиагентным воркфлоу:

1️⃣ Initial Understanding — агент запускает до 3-х explore суб-агентов параллельно для исследования кодовой базы, задаёт уточняющие вопросы пользователю.

2️⃣ Design — запускает general суб-агента для проектирования плана реализации на основе собранного контекста.

3️⃣ Review — читает релевантные файлы, сверяет план с запросом.

4️⃣ Final Plan — записывает план в специальный файл.

5️⃣ Exit — вызывает инструмент plan_exit для передачи плана обратно в build агент.

Мультиагентная архитектура реализована через делегирование. Основной агент порождает специализированных суб-агентов, каждый из которых работает в изолированной сессии со своей историей сообщений. Агенты описываются через Zod-схему (мордоровский аналог Pydantic).

Ключевые свойства:

mode (является ли агент пользовательским "primary", вспомогательным "subagent" или обоими "all"), permission (набор правил, контролирующих доступ к инструментам через glob-паттерны),

model (опциональная привязка к конкретной модели),

steps (максимальное число итераций цикла),

prompt (кастомный системный промпт, заменяющий стандартный).

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

Для работы с кодом
OC не использует RAG и векторные/формальные модели кода, отдавая это на откуп внешним MCP. Вместо этого применяется обычный поиск через обертки для ripgrep, glob, нечеткий поиск по именам файлов, и ± стандартные файловые тулы.

Организация памяти также заслуживает внимания:

1️⃣ История сообщений сессии. Каждая сессия хранит полную цепочку сообщений в SQLite. При каждой итерации ReAct, в runLoop() загружаются все сообщения сессии. Модель видит всё — каждый предыдущий шаг ReAct, каждый вызов инструмента и его результат, до тех пор, пока контекстное окно не переполнится.

2️⃣ Сжатая память. Когда контекстное окно переполняется, запускается двухфазный процесс сжатия. Сначала система проходит по истории и вычищает содержимое результатов инструментов, оставляя лишь 40К «свежих» токенов. Затем агент compaction генерирует структурированное резюме по шаблону: цель, инструкции, находки, выполненная работа, релевантные файлы. В дальнейшем, вместо полной истории используется только это резюме — аналог «эпизодической памяти», сжатый пересказ предыдущего опыта, из которого агент может продолжить работу.

3️⃣ История дочерних сессий. У суб-агентов своя изолированная история сообщений — они не видит истории родителя и друг-друга, только тот промпт, который им передали. Результаты сжимаются до текстового ответа и возвращаются в историю родительской сессии как результат тулкола.

4️⃣ Список задач. Инструмент todowrite сохраняет список задач в SQLite-таблицу TodoTable сессии, который потом передается между итерациями ReAct основного агента.

5️⃣ Сохранённый полный вывод инструментов. Когда вывод инструмента превышает 2К строк или 50 КБ, truncate сохраняет полный текст в файл ~/.opencode/tool-output/<id> на 7 дней. Агенту возвращается усечённая версия плюс подсказка: делегировать explore суб-агенту обработку полного файла. Это «внешняя память», вынесенная за пределы контекстного окна, но доступная через явное действие.



Из подходов Claude Code и OpenCode уже может быть очевиден принцип: чем проще инструмент внутри, тем он популярнее. На самом деле, так оно и есть. Но о причинах мы ещё поговорим, чуть позже 😉

TL;DR: OpenCode прост, но не проще поинтереснее, чем Claude Code.
Please open Telegram to view this post
VIEW IN TELEGRAM
11🔥63👍3
🧩 Принципы и паттерны безопасной разработки: LSP

Часть 2.

Продолжаем разбор SOLID... на очереди — принцип подстановки Барбары Лисков (Liskov Substitution Principle, LSP). Формально он гласит: объекты подклассов должны быть способны заменить объекты базовых классов без нарушения корректности программы. Проще говоря, наследник не должен «ломать» контракт, установленный родителем — ни в предусловиях (не требовать большего), ни в постусловиях (не гарантировать меньшего), ни в инвариантах (не нарушать постоянных условий).

Что неочевидно для многих, благодаря дядюшке Мартину, так это то, что LSP является поведенческим принципом, а не структурным. Иными словами, чтобы нарушить его, наследование (да и ООП в целом) — вообще не нужно. Если у нас есть одна сущность, переопределяющая поведение другой, и при этом к ней можно обратиться, как к исходной — этого достаточно. Даже, если сущности — результат функциональной композиции, без каких-либо объектов в терминах ООП в целом. Пример того, как LSP выглядит в языках, не имеющих наследования, можно посмотреть тут.

С точки зрения безопасности, нарушение LSP — это прямая дорога к обходу защитных механизмов. Когда подкласс изменяет семантику безопасности базового класса (например, отключает проверку прав доступа или меняет логику валидации), код, написанный с расчётом на родительский контракт, начинает работать непредсказуемо. Это порождает логические уязвимости, которые сложно отловить статическим анализом, поскольку формально типы совместимы, а вот их поведение — нет.

Как правило, нарушения LSP могут повлечь за собой примерно любые уязвимости, так или иначе связанные с логикой работы приложения. «В природе», однако, чаще всего они относятся ко следующим категориям:

CWE-264: Permissions, Privileges, and Access Controls
CWE-284: Improper Access Control
CWE-290: Authentication Bypass by Spoofing
CWE-703: Improper Check or Handling of Exceptional Conditions

🐛 Жизненное

CVE-2025-22223 — Spring Security (Authentication Bypass by Spoofing).

Когда аннотация безопасности (@PreAuthorize) размещена на методе обобщённого суперкласса или интерфейса, и конкретный подкласс переопределяет этот метод, механизм UniqueSecurityAnnotationScanner не находит аннотацию на переопределённом методе. Причина -- использование targetClass.getDeclaredMethod(method.getName(), method.getParameterTypes()) для поиска, что не работает после стирания типов (type erasure): сигнатура родительского метода Object mutate(Object) не совпадает с сигнатурой конкретной реализации AccountSecret mutate(AccountSecret).

public abstract class BaseService<T> {
@PreAuthorize("hasRole('ADMIN')")
public abstract T getResource(Long id);
}

// Подкласс -- Spring Security не видит аннотацию
public class UserService extends BaseService<User> {
@Override
public User getResource(Long id) {
return userRepo.findById(id);
}
}

Нарушение LSP здесь в том, что родительский тип объявляет контракт «этот метод требует роли ADMIN». Подкласс переопределяет метод, и контракт безопасности молча пропадает. При подстановке подкласса вместо родителя предусловие (авторизация) ослабляется.

Патч (коммит dc2e1af). Наивный поиск getDeclaredMethod заменен на итерацию по всем методам класса с разрешением обобщённых типов.

❗️Что делать?

• Помечайте security-critical классы как final|sealed или явно контролируйте наследование.

• Аннотации безопасности дублируйте на каждом переопределяющем методе.

• Фильтруйте и определяйте сущности по их типу, а не по имени.

• Соблюдайте явным образом все поведенческие контракты переопределяемых методов.

• Обеспечивайте инварианты объекта даже при аварийном завершении конструктора или инициализации.

TL;DR: В целом, общий принцип один: если ваш код принимает сущность по ссылке на базовую реализацию, он неявно доверяет поведенческому контракту этой сущности. Убедитесь, что это обосновано — особенно на границах доверия между компонентами системы.
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍61💯1
🐞 CVE-2026-40372: Improper verification of cryptographic signature in ASP.NET Core

Microsoft сама сравнивает эту уязвимость, исправленную на днях, и получившую CVSSv2 9.4, с MS10-070 (2010 год) — классической padding oracle атакой на legacy ASP.NET ViewState/encryption infrastructure. Обе уязвимости разрушают криптографические гарантии целостности, позволяя подделывать подписанные данные. Разница в том, что MS10-070 требовала множественных запросов для oracle-атаки, тогда как CVE-2026-40372 позволяет напрямую подделывать payload'ы, поскольку HMAC-проверка фактически отсутствует.

ASP.NET Core Data Protection — это встроенный фреймворк для симметричного шифрования и HMAC-подписи конфиденциальных данных «на лету». Он применяется повсеместно в ASP.NET Core приложениях: шифрование и подпись authentication cookies, защита antiforgery-токенов, шифрование TempData, защита session state и любых пользовательских payload'ов через IDataProtector.Protect() / Unprotect().

🐛 Уязвимость

В .NET 10.0 разработчики переписали часть кода ManagedAuthenticatedEncryptor — managed-реализации аутентифицированного шифрования, которая используется на Linux, macOS и других не-Windows платформах (на Windows используется отдельный путь через CNG, который этой уязвимостью не затронут).

Регрессия была внесена в метод CalculateAndValidateMac класса ManagedAuthenticatedEncryptor. Ошибка заключалась в двух вещах:

HMAC вычислялся по неправильному диапазону байт payload'а — вместо (IV + ciphertext + AAD) использовались некорректные смещения, из-за чего подпись фактически покрывала не те данные.

Вычисленный хеш в ряде случаев отбрасывался — результат HMAC-вычисления не сравнивался с тегом из входящего payload'а, либо сравнивался с массивом нулевых байт.

Вот, как выглядел уязвимый код код (упрощенно):
// ManagedAuthenticatedEncryptor.CalculateAndValidateMac

private void CalculateAndValidateMac(
byte[] payloadArray,
int ivOffset,
int macOffset, // смещение, где начинается HMAC-тег в payload
int eofOffset, // конец payload
ReadOnlySpan<byte> validationSubkey,
byte[] validationSubkeyArray)
{
using var hmac = new HMACSHA256(validationSubkeyArray);
byte[] computedMac = hmac.ComputeHash(
payloadArray,
ivOffset,
ivOffset // <-- ОШИБКА: должно быть (macOffset - ivOffset), хэш считается по пустому буферу
);
}


В результате любой payload с произвольным содержимым и нулевыми (или любыми) байтами вместо HMAC-тега проходил валидацию.

🧑‍💻 Атаки

Подделка authentication cookie

Формат cookie: Base64Url( [key_id:16B] [IV:16B] [AES-CBC(AuthTicket):NB] [HMAC:32B])

Атакующий формирует поддельный cookie:
var forgedTicket = CreateAuthTicket(
claimsIdentity: new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, "admin"),
new Claim(ClaimTypes.Role, "Administrator")
}, "Cookies")
);

byte[] iv = RandomBytes(16);
byte[] ciphertext = AesCbcEncrypt(arbitraryKey, iv, Serialize(forgedTicket));

byte[] fakeHmac = new byte[32];

// (key_id публично доступен — он передаётся в каждом cookie)
byte[] payload = Concat(knownKeyId, iv, ciphertext, fakeHmac);

string forgedCookie = Base64UrlEncode(payload);


Обход antiforgery-токенов

ASP.NET Core Antiforgery также опирается на Data Protection. Атакующий может аналогичным образом подделать и antiforgery-токен и выполнять CSRF-атаки, обходя стандартную защиту.

Расшифровка защищённых данных

Поскольку MAC-валидация не работает, атакующий может использовать приложение как оракул: отправлять модифицированные payload'ы и по ответам приложения (ошибка расшифровки vs. успех) побайтово восстанавливать ключ шифрования. После чего — расшифровать любые перехваченные ранее protected-payload'ы.

Ну и 🍒, напоследок: если во время окна уязвимости атакующий подделал cookie и аутентифицировался как привилегированный пользователь, приложение выдало ему легитимно подписанные токены — refresh-токены, API-ключи, ссылки для сброса пароля. Эти токены остаются валидными и после обновления до 10.0.7, пока не будет ротирован Key Ring 😕
Please open Telegram to view this post
VIEW IN TELEGRAM
12🔥1
🖥 Самое недооцененное преимущество ИИ в R&D

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

Сейчас куда ни плюнь — всюду пишут о разработке с ИИ-агентами. Ну как, пишут... генерируют с помощью того же ИИ то, что хотели бы написать, если бы умели. И когда на десяток статей приходится хотя бы одна не про восторги от очередного агента, MCP, поделок Карпаты, или «почему нас всех заменят», ещё и написанная человеческими руками — уже можно обводить красным день в календаре.

И это настораживает. Ведь, в случае осознанного assisted-кодинга с ответственным подходом к написанию промптов, организации проекта, и проведения ревью, выигрыш во времени и стоимости не так уж велик (и надо ещё очень постараться, чтобы он вообще был, по совокупности факторов). И речь в таком случае идет скорее о переносе человеческого фокуса внимания с написания кода на его чтение и написание ADR/требований/спецификаций. Классно? Однозначно. Но совершенно неадекватно раздутому вокруг этого хайпу. Ведь главная ценность ИИ для разработки — вовсе не в написании им кода за ленивых кожаных.

Все будто напрочь забыли: в R&D, вообще-то — две буквы.

Казалось бы, что может быть проще? Любой agentic-фреймворк, позволяющий замутить ReAct-цикл, пара тулов web_search и web_fetch, незатейливый промпт или скилл (или даже затейливый)... и у тебя на кончиках пальцев оказывается вся глобальная сеть. Сеть, с которой можно разговаривать, из которой можно извлекать экспертизу по множеству областей, с помощью публикаций в которой можно формулировать и проверять гипотезы, готовить те самые спецификации и планы и, наконец, учиться и развиваться.

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

Поэтому самыми недооцененными среди разработчиков на данный момент, лично я, считаю такие сервисы, как Perplexity, NotebookLM, NoteGPT, и им подобные, а вовсе не очередной «прорыв» в очередном кодинг-агенте, позволяющий молотить код в два раза лучше/быстрее/выше/здоровее. Самым же недооцененным преимуществом ИИ в R&D, на мой взгляд, является всё то, что он может дать именно для R, а не для D.

Но почему-то мало кто отваживается это взять.

Искренне ваш,
«из Петербурга, с апатией и безразличием» (с) 🫡
Please open Telegram to view this post
VIEW IN TELEGRAM
5🫡13👍106🤝1
📈 Deeper Research Bot (с TODO-листом и ветками рассуждений)

Давно чесались руки попробовать ToT (Tree of Thoughts — древовидная генерализация Chain of Thoughts, о котором рассказывал ранее), а тут ещё задумался, так ли просто запилить своего ресерч-агента, как утверждал в предыдущем посте... в общем, всё одно к одному сошлось 🤦‍♂️

Вообще, оно задумывалось, как очередной игрушечный агент на пару сотен строк, но в какой-то момент, что-то пошло не так, и получилось то, что получилось 🙈 Telegram-бот для глубоких исследований, на базе ToT, с возможностью добавления в контекст документов (любые текстовые форматы, .pdf, .docx, .xlsx и .pptx) a-la «NotebookLM для бедных», и ReAct-циклом с обновляемым TODO-списком и инструментами для обшаривания сети.

TODO-список, причем, я делал исключительно ради того, чтобы можно было отслеживать прогресс исследования из чата телеги. Но внезапно, его добавление ощутимо улучшило результаты ризонинга. Да так, что Plan&Execute, на основе которого сейчас делаю c0wrk (своего кодинг-агента — спойлер), местами ему даже проигрывает на одних и тех же задачах. В том числе и за счет ToT, скорее всего, но тем не менее — результаты прям приятно удивляют. Есть над чем задуматься.

Реализация ToT, если кому будет интересно, вся уложена в системный промпт, в prompts.py. Сжатие контекста сделал максимально примитивно: все ранее суммаризованные сообщения удаляются, все не суммаризованные, кроме относящихся к текущей задаче, суммаризируются. Остальное — обвязки вокруг aiogram, litellm и стандартное агентское барахло.

LiteLLM — потому, что изначально предполагал, что под ToT ReAct-цикл нужно будет жестко тюнить. Но оказалось, что не нужно, а переписывать всё под какой-нибудь LangChain стало тупо лень, поскольку, учитывая простоту агента, особого смысла в этом нет.

Да, и на основе того промпта сделал ещё и агентский скилл для ресерча, реализующий ToT — если вдруг кому захочется его попробовать, но будет лень разворачивать для этого бота.
Please open Telegram to view this post
VIEW IN TELEGRAM
11🔥13👍32