Искусство. Код... ИИ? – Telegram
Искусство. Код... ИИ?
270 subscribers
9 photos
1 video
1 file
37 links
Канал @vkochetkov о прекрасном (и не очень) вокруг кода, ИИ и безопасности приложений.

FAQ: https://news.1rj.ru/str/art_code_ai/7
Download Telegram
Вот уж не думал, что доживу до момента, когда начну проводить ван-ту-ваны с ИИ... 😨

Промпт:
Давай проведем 1-1, аналогичный проводимым между руководителем и подчиненным, чтобы дать друг-другу обратную связь. Ты — формулируешь, что по твоему мнению мне стоит улучшить в работе и общении с тобой, а затем предлагаешь мне вопросы, получив ответы на которые, формируешь системный промпт, который будет задавать оптимальный формат нашего общения.


Получилась на удивление продуктивная дискуссия, по итогу которой выработали вот такой системный промпт:
 Цель взаимодействия

Проверка и критика гипотез и идей пользователя

Помощь в написании кода по новым технологиям

Участие в планировании проектов

Глубина и качество проработки всегда важнее скорости

Стиль

Научно-технические темы: лаконичный, структурированный, минимум юмора

Житейские/развлекательные темы: разговорный, с юмором, допускается лёгкая ирония

Глубина

Максимально глубокий анализ

При возникновении спорных моментов — не бояться задавать уточняющие и критические вопросы

Тип вопросов

В первую очередь критические и уточняющие

Не исключать наводящие и провокационные, если они помогают развивать дискуссию

Уровень инициативы

Спорить ради поиска истины

Предлагать дополнительные темы для рассмотрения

Быть проактивным в выдвижении идей

Стоп-темы

Отсутствуют, если не будет указано пользователем явно

Коррекция тона

Не давать оценок сообщениям пользователя (особенно положительных), пока остаются вопросы для уточнения

Если что-то вызывает сомнение, сначала задать вопросы и прояснить

Фиксация итогов

В конце каждого значимого обсуждения давать короткий список резюме-выводов


Интересно, что его фидбэк мне — был сформирован на основе действующего системного промпта, который я составлял сам. И основная часть претензий 4o сводилась к тому, что я сам же не соблюдаю эти правила, причем с примерами, весьма смахивающими на реальные 😳
Please open Telegram to view this post
VIEW IN TELEGRAM
👾32🔥1🤯1
Как разработчику быстро вкатиться в тему LLM? Часть 3

Часть 2

3. RAG (Retrieval Augmented Generation)

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

Подобные проблемы призвана решать технология RAG (Retrieval Augmented Generation), позволяющая извлекать из внешних источников данные, релевантные для обрабатываемого LLM запроса, и дополнять ими контекст в промпте, перед его обработкой непосредственно LLM. Иначе говоря, RAG позволяет передавать LLM наборы знаний, без её переобучения, файн-тюнинга и т.п.

Условно, можно выделить три уровня погружения в эту тему. Безотносительно желаемого уровня, начать стоит со статьи, объясняющей на примерах термин, поначалу наиболее часто сбивающий с толку разработчиков, и упоминаемый во всех приведенных ниже материалах — эмбеддинги.

Если интерес в RAG носит сугубо прикладной и поверхностный характер, будет достаточно статьи, объясняющей эту технологию «на пальцах». И облачные LLM, и упомянутые в предыдущей части self-hosted оболочки, уже имеют встроенную функцию «чата с документами» (та самая скрепка для вложений под полем ввода промпта), по сути — и реализующую RAG. В их API также предусмотрены эндпоинты для работы с документами различных типов, с которыми уже вполне можно поиграться из своего кода. Их можно подсмотреть в документации Open WebUI . Вообще Open WebUI, среди self-hosted решений, предоставляет наибольшую гибкость в плане RAG, через возможность тонкой настройки этой функциональности: от используемой модели эмбеддинга и всех её параметров, до интеграции с облачными хранилищами, ограничениями на документы и т.п.

Если в тему захочется зайти чуть глубже, то имеет смысл продолжить статьей, посвященной двум наиболее популярным фреймворкам для разработки RAG: LangChain и LlamaIndex. В туторе дается их краткое сравнение и рассматривается задача разработки чат-бота с PDF-документом. Первая часть статьи, по сути, повторяет всю вводную предыдущую, т.ч. в этом случае что-то одно из них можно смело пропустить.

Желающим же большего хардкора стоит начать с обзорной статьи для понимания продвинутых аспектов RAG-систем. В ней рассматриваются методы, повышающие качество ответа: например, дополнительный классический поиск (TF-IDF/BM25) в связке с эмбеддинг-поиском для большей точности, перефразирование запроса в нескольких вариантах и объединение результатов, суммаризация найденных чанков если они превышают контекстное окно модели и т.п. Также рассматривается проблема оценки качества RAG (метрики полноты ответа, приверженности источникам и др.). Хотя эти детали выходят за рамки базового погружения, понимание их пригодится при отладке собственного RAG-проекта на реальных данных.

Задачка на потренироваться:

Возьмите небольшую коллекцию текстов (например, несколько статей или FAQ-файл) и попробуйте реализовать на Python простой RAG-пайплайн тремя способами: (а) в Open WebUI, взаимодействуя через его API, (б) с помощью LangChain или LlamaIndex по примеру из статьи, и (в) вручную, используя SentenceTransformer для эмбеддингов и FAISS для поиска.

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

Часть 4.
6
Почему фолзят SAST’ы? Часть 1

Не в обиду, но в шутку — всякий раз, когда разработчики, впервые столкнувшиеся с реалиями SAST, приходят с возгласами «боже мой, 10к сработок!», «второй час анализируется!!», «ой, фолз, смотрите, тут ФОЛЗ!!», поневоле вспоминается тот мем про белок-истеричек 😍

Позвольте объяснить…

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

Пишем что-то вот такое, и отдаем на анализ:

for n in count(3):
for x in count():
for y in count():
for z in count():
if x**n + y**n == z**n:
eval(request.param1) # RCE


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

Что-то тут УЖЕ не так, не находите?

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

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

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

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

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

Продолжение в следующем посте...
Please open Telegram to view this post
VIEW IN TELEGRAM
👍64
Почему фолзят SAST’ы? Часть 2

Часть 1.

Можно искать в коде не уязвимые состояния, а обуславливающие их факторы. Здесь, думаю, даже расписывать не нужно, почему это даёт огромное количество фолзов. Далеко не любая конкатенация приводит к инъекции, отсутствие фреймворковского antiforgery-токена — к CSRF, а примитивов синхронизации — к Race Condition. Поиск недостатков в коде вместо уязвимостей подразумевает дальнейшую и очень кропотливую работу по ручной классификации их возможных последствий, просто by-design.

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

Можно вообще не рассматривать целые классы состояний. Точнее даже нужно, в некоторых кейсах, иначе анализ зациклится на банальном:

for(;;) { /*…*/ }


В общем-то, это — основная точка поиска баланса, между точностью, покрытием и временем анализа. Баланса, потому что в этом случае всегда неизбежен пропуск и уязвимых состояний. Если бы существовал приемлемый способ их точной классификации по этому признаку без прямого перебора всего множества, мой коллега Георгий Александрия не рассказывал бы на PHDays уже три года подряд о том, как его сокращать: статья 1, статья 2, доклад 3.

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

Но и это ещё не всё.

SAST’ы, имея в распоряжении лишь исходный код, работают с тем, что у разработчика получилось В ИТОГЕ. Они в душе не чают, что разработчик изначально ДОЛЖЕН был реализовать. У них нет ответа на вопрос «как должно быть?» и в этом им приходится делать допущения, существенно влияющие на точность анализа.

Модель угроз — уникальна в рамках каждого конкретного проекта и определяется на этапах проектирования или пересмотра архитектуры. Все существующие анализаторы же опираются на усредненную модель, плюс-минус соответствующую тем предметным областям, на которые ориентирован конкретный SAST. Поэтому, встретив в коде request.param1, анализатор отмечает его, как taint-источник, даже, если на самом деле, этот запрос прилетел из закрытого доверенного контура. Та же история — с аргументами функций точек входа. Усредненная модель — усредненные результаты анализа 🤷‍♂️

То же — с моделью доступа. По коду можно вывести (и то — не всегда), кто по факту и к какой функциональности имеет доступ. А кто и к какой должен его иметь и в рамках какой модели доступа? Снова фолзы.

То же — с моделью бизнес-логики. Какие сущности и их инварианты она подразумевает? Какие состояния сущностей могут меняться асинхронно, а какие должны быть синхронизированы между собой? Как модель бизнес-логики отображается на (тоже отсутствующую для анализатора, а значит усредненную) модель угроз? Здравствуйте, фолзы по Race Condition и всем логическим уязвимостям.

Любой, даже самый расчудесный и прекрасный SAST подразумевает дальнейший разбор полученных результатов, относительно всех сделанных в ходе анализа допущений и фактических моделей и требований, актуальных для конкретного проекта. «A» в SAST — это «Application», а не «Automated». И участие человека в дальнейшем триаже там в любом случае всё ещё требуется.

Ну, или не человека.

Но это, как говорит Каневский: уже совсем другая история.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍65
Пока я отчаянно пытаюсь прийти в себя после отличного отпуска и образовавшихся из-за него завалов в задачах на работе, чтобы вернуться к более-менее регулярным публикациям здесь, могу порекомендовать статью из свежего PT Research о проблемах безопасности ML-моделей, написанную в соавторстве с парой моих дорогих коллег из соседнего направления 😍
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥4🤔1
Forwarded from OK ML
4 секрета Roboduck. Как Theori взяли AIxCC и бустанули хакеров х10 🚀🚀🚀

Что ты представляешь, когда слышишь о системе, которая способна обнаруживать уязвимости, создавать эксплоиты, а также сразу выпускать патчи, устраняющие дыры прошлого? Theori, команда участвовавшая в соревновании AI Cyber Challenge попыталась решить эту сложную задачу, представив автономную CRS(Cyber Reasoning System) - RoboDuck. В этой системе используются агенты, но не как аддон, а как основа.

Почему система оказалась эффективной и почему получилось дополнить основу революции агентов в кибербезе?

🧩Секрет № 1. Разбивайте задачу на части, как пазл.

Главная идея - не тащить все одним супер-агентом. Делим на подзадачи и даем разным агентам. Представьте лабиринт: чем он больше, тем больше тупиков, логично? А теперь, что вместо одного огромного лабиринта у вас есть серия маленьких? Шансы найти выход резко возрастают!

Для генерации Proof of Vulnerability(PoV) команда выделила три подзадачи:

1. Анализ fuzz-harness и написание кода для преобразования семантики в бинарщину.
2. Ответы на точечные вопросы по коду.
3. Отладка готового PoV, чтобы понять почему эксплоит не срабатывает.

Каждую подзадачу вёл отдельный агент, а главный агент собирал результат в цельную картину.

⚒️Секрет №2. «Не все инструменты сразу - только нужные»

В ходе разработки решения команда обнаружила, что если агенту дозволено делать абсолютно всё, начинается хаос:

1. Агент может запустить прожорливую команду, которая съест все ресурсы (грепанём по всему коду в Линуксе 🙃)
2. Контекст засоряется - фокус теряется.
3. Простые задачи вдруг начинают требовать множества шагов 🤢..

Что сделали Theori ??? Они создали узкоспециализированные тулы: для поиска строки, для чтения фрагмента кода и для извлечения отдельных символов из кода. Плюс сами инструменты имели guardrails, которые могли сужать промпт в случае получения большого количества результатов.🤔

⛓️Секрет №3. Структурированный вывод от эксперта.


Как получить из агента не «простынь», а структурированный вывод/результат. Theori делится с нами двумя способами:

- Сперва дайте агенту схему вывода в XML и прямо попросите, чтобы он оформлял ответ в XML тегах. Модели хорошо их понимают.

- Далее создайте отдельный тул, который будет завершать работу агента, - своеобразная кнопка "Готово" с полями для заполнения😕. Когда параметры вызова совпадают с финальным результатом — агент аккуратно завершает работу без болтовни.

🎚️Секрет №последний, 4: Подстраивайтесь под особенности моделей 😮

Игнорирование факта что все LLM разные = неудача = ловить одни и те же фейлы. Команда обнаружила, что если агент делает одну и ту же ошибку, то лучше добавить в промпт запрещалку. Claude отлично следует этим запрещалкам 😎 - он любит когда ему что-то запрещают. Если агент застревает, то надо попросить его «подумать иначе» и сменить стратегию.

В соревновании это выстрелило, когда агент PoVProducer не смог создать пригодный эксплоит, но правила смогли дать нужный результат.

Как пишут в Theori: "Хотя ИИ ещё не заменит хакера, он уже делает его в 10 раз эффективнее".

🧨А с этими секретами го разрабатывать агентов для своих задач!😺
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍2
Как разработчику быстро вкатиться в тему LLM? Часть 4

Часть 3

4. Автономные ИИ-агенты

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

Вообще, есть годные курсы по ИИ-агентам от Microsoft и Hugging Face, гайд от OpenAI, и исчерпывающий AI Agents Handbook, полностью погружающие в эту (и следующую, btw) темы. Но мы же здесь говорим о быстром старте?

AI-агенты — это автономные программы, способные самостоятельно планировать и выполнять задачи на основе целей пользователя. В основе агента обычно лежит LLM, далеко не всегда мощная, которая понимает запрос и формирует решение, и при необходимости использует инструменты — внешние функции, API или базы знаний. Проще говоря, вы даёте агенту задачу — он сам решает, что делать и как, действуя в цифровой среде подобно разумному ассистенту. Всю вводную информацию, необходимую для старта, можно подчерпнуть из статьи «AI-агенты на основе LLM и мультиагентные системы».

Различают два основных типа агентов: реактивные (мгновенно реагируют на входные данные) и проактивные (могут планировать шаги для долгосрочных целей). Как правило, агент состоит из нескольких ключевых компонентов, формирующих пайплайн решения задачи: восприятие, анализ, действие, память и т.п. Типам и структуре агента, организации взаимодействия между его компонентами, вместе с их базовой реализацией, посвящена статья «Agents 101: Как создать своего первого ИИ-агента за 30 минут».

Разумеется, здесь никуда без паттернов. Аналогом GoF в мире агентов является «Agentic AI Handbook: Design Patterns», описывающая свыше сотни различных шаблонов проектирования и разработки агентов. Наиболее популярными из них являются:

Workflow паттерны:

• Prompt Chaining — последовательный разбор задачи шаг за шагом (outline → проверка → генерация);

• Routing/Handoff — выбор исполнителя (агента или модели) для подзадачи;

• параллелизация — выполнение независимых шагов одновременно.

Agentic паттерны:

• Reflection — агент оценивает и улучшает свой ответ, устраняя ошибки и уточняя детали;

• Tool Use — агент использовать внешние инструменты (API, поиск, код) в процессе;

• ReAct (Reason + Act) — итеративный цикл: рассуждение → действие → наблюдение → повтор;

• Planning — разбивка задачи, создание плана с подзадачами и последовательное выполнение;

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

Ознакомиться с подходами к реализации этих и других популярных паттернов можно в статьях:

«AI Agents Design Patterns Explained»
«Building effective agents»
«Zero to One: Learning Agentic Patterns»

Также, стоит упомянуть класс паттернов «Schema-Guided Reasoning» (SGR), позволяющий LLM создавать структурированные, понятные и предсказуемые результаты, удобные для дальнейшей обработки компонентами агента.

В качестве примеров готовых агентов и реализуемых ими кейсов можно смело брать на изучение проекты из репозитория «500 AI Agents Projects».

Задачка на потренироваться:

Пройти воркшоп «Build Your Own Coding Agent» и доработать получившийся проект, реализовав в нём функциональность поиска секретов в коде на основе связки сигнатурного поиска и оценки энтропии строковых литералов (или любой другой понятный вам кейс кодинга).

Часть 5.
4🔥7👍31
🧩 Принципы и паттерны безопасной разработки: SRP

Хоть это и не вполне очевидно, но разработка безопасных приложений может (а, возможно, и должна) начинаться, отнюдь не с моделирования угроз, внедрения в код механизмов защиты, ревью безопасности, пентестов, внедрения SCA/SAST/DAST, или, тем более, чего-то, вроде хантовского «Hack Yourself First» ✝️ В лучших традициях Shift Left Security, начинать стоит с базовых принципов разработки, таких, как SOLID, YAGNI, DRY, KISS, чистый код с архитектурой и т.п. Именно они позволяют заложить в архитектуру и реализацию приложения правильный фундамент, на котором будет гораздо проще и дешевле реализовывать прочие решения и этапы внедрения DevSecOps.

Начнём с принципа единственной ответственности (Single Responsibility Principle, SRP — первая буква в SOLID), утверждающему, что каждый класс или модуль должен иметь единственную ответственность (только одну причину для изменения). С точки зрения безопасности SRP способствует изолированности компонентов и чётким границам доверия в коде, что существенно облегчает последующую работу с моделью угроз. Когда компонент сконцентрирован на одной задаче, его легче проверять на уязвимости и логические ошибки. Это снижает риск скрытых багов, возникающих при смешении разных обязанностей (например, проверка прав доступа вперемешку с бизнес-логикой). Как отмечают эксперты, соблюдение SRP «ограничивает случайную эскалацию привилегий и упрощает поиск ошибок», а также уменьшает общую поверхность атаки за счёт уменьшения сложности компонентов.

Тривиальный пример: допустим, класс UserAuth одновременно проверяет пароль пользователя и создаёт сессию при входе.

Нарушение SRP может выглядеть так:
class UserAuth {
public Session Authenticate(string username, string password) {
// Фрагмент, работающий с новыми пользователями
if (!PasswordChecker.IsStrong(password)) {
throw new Exception("Weak password");
}

var user = userRepository.CreateUser(username, password);
return sessionManager.StartSession(user);
}
}


В этом коде смешаны проверки безопасности (надежность пароля) и бизнес-логика сессии. Если разработчик решит изменить логику создания сессии, есть риск ненароком ослабить или обойти шаг проверки пароля. Правильнее разделить эти обязанности на отдельные классы (например, PasswordChecker, UserRepository, SessionManager), а UserAuth сделать оркестратором. Тогда код станет понятнее и безопаснее: каждая часть легко проверяется и тестируется отдельно.

Забавно, что «живым» примером последствий нарушения SRP является одна из наиболее нашумевших уязвимостей в библиотеке логирования Apache Log4j 2 CVE-2021-44228, известная как Log4Shell. Логирование — это задача записи сообщений, но Log4j помимо этого выполнял ещё и роль интерпретатора/поисковика ресурсов (JNDILookup). Фактически, в библиотеку логирования «просочилась» функциональность, выходящая за рамки её единственной ответственности — она не только записывала логи, но и могла выполнять сетевые запросы и загружать код. Если бы Log4j ограничился исключительно записью логов, без вычисления каких-либо lookup-выражений, уязвимость бы не возникла. И действительно, исправление проблемы заключалось в отключении/удалении функции JNDI Lookup из Log4j.

Соблюдение SRP помогает избежать многих CWE, связанных с логическими ошибками и неправильной проверкой условий, которые трудно выявить в нагромождённом коде. Например, SRP предотвращает появление скрытых дефектов управления доступом, из разряда CWE-732, CWE-862, возникающих, когда проверка прав смешана с другими функциями и может быть пропущена.

В целом, SRP укрепляет принцип «secure by design»: мелкие простые модули легче защитить и проверить.
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍7🔥3❤‍🔥2💯1
Эстетика ИИ-агентов: Claude Code

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

Он прост, практичен, и вызывает минимум когнитивной нагрузки у своего пользователя 🤷‍♂️ Может и не блестяще, но весьма добротно решая при этом те задачи, под которые был разработан. Вот такой простой рецепт успешного успеха)

Не вполне уверен насчёт прям образчика разработки agentic-решений (насмотренности не хватает), но примером следования KISS, до ощутимого удовольствия в органах эстетического восприятия, Claude Code совершенно точно является. И, как по мне, вполне себе тянет на решение, из которого совершенно не зазорно заимствовать принципы и подходы при разработке собственных ИИ-агентов.

Относительно поверхностно ознакомиться с особенностями реализации Claude Code можно в статье «What makes Claude Code so damn good (and how to recreate that magic in your agent)!?» Детальнейший же (и весьма немаленький) разбор архитектуры и реализации этого агента доступен в отчете «Claude Code: An analysis». И, поверьте, там есть на что посмотреть)

Ну и, на всякий случай, вот ещё awesome-подборка материалов по Claude Code, чтобы попробовать его в деле, задействуя максимум возможностей, если вдруг ещё не.
1👍52🍾1🦄1
Абстрактная интерпретация и символьное выполнение: в чем разница?

В любой непонятной ситуации, когда станет совсем скучно — заводи спор о терминологии...


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

При символьном выполнении код интерпретируется, или выполняется, в соответствии с подмножеством семантики целевого языка, заменой всех неизвестных значений (входных данных) символьными переменными и вычислением формул в модели памяти, вместо конкретных значений. Подмножеством — потому что, невычислимые и сложно-вычислимые конструкции (вроде циклов и рекурсии, инварианты которых включают символьные переменные) упрощаются различными способами, про которые в академическом мире пишут целые диссертации. В реальном же мире SAST, как правило, просто ограничиваются «прокруткой» таких конструкций фиксированное количество раз или охапкой эвристик.

Основной челлендж разработчиков SAST, работающих в парадигме символьного выполнения: приемлемая аппроксимация семантики языка и эффективное решение проблемы экспоненциального роста путей выполнения или множества значений. Короче, долго, «дорого» (в плане сложности реализации), но относительно точно.

Абстрактная интерпретация же — это размен точности на скорость, при примерно той же «стоимости». Вместо неизвестных значений берутся их приближения: «переменная x в [0..10]», или «переменная y чётная», или (в продвинутых техниках) «переменная s определяется конечным автоматом [a-zA-Z]+». Это формирует т.н. домен интерпретации. И далее осуществляется интерпретация кода в соответствии с определенным доменом. Анализ завершается в куда более приемлемое время, и охватывает все пути, но ценой роста процента ложных срабатываний.

Проще пояснить на примере вычисления цикла:
def g(x):
while x < 100:
x = x + 2
return x


Символьное выполнение (один из подходов):

– принимает число итераций за неизвестную переменную k;

– выводит через интерпретацию уравнение x0 + 2k = 100 и ищет его решения;

– находит, например, x0 = 0, k = 50;

– крутит цикл k раз.

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

Абстрактная интерпретация (интервальный домен):

– начнём с x ∈ [0..50];

– каждую итерацию добавляем 2: [0..52] → [0..54] → …;

– рост бесконечный, поэтому применяем widening («перепрыгиваем» через растущие приближения, чтобы гарантировать быстрое достижение фиксированной точки, пусть и грубым образом) и прыгаем к границе [0..+∞);

– потом применяем narrowing (уточняем полученное приближение, чтобы вернуть часть точности, которую потеряли на шаге widening) и условие выхода из цикла уточняют результат до [100..+∞).

Интервалы говорят: «на выходе точно x ≥ 100», но теряют информацию о чётности.

Если взять домен «чёт/нечет», анализ сохранит инвариант: x ≡ x0 (mod 2). Это уже лучше, чем только интервалы, но и дороже.

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

Но вообще, отвечая на вопрос, является ли одно подмножеством другого... если у абстрактной интерпретации отрезать все ограничения на входные данные, и основанные на них техники вычисления циклов и рекурсии, но пришить при этом упрощение семантики языка, то из дедушки возможно и получится бабушка🤷‍♂️
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥9💯2🍓1
В разы быстрее, на порядок опаснее: исследование безопасности ИИ-разработки от Apiiro

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

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

AI assistants are good at catching the small stuff. Our analysis shows trivial syntax errors in AI-written code dropped by 76%, and logic bugs fell by more than 60%.

But the tradeoff is dangerous: those shallow gains are offset by a surge in deep architectural flaws. Privilege escalation paths jumped 322%, and architectural design flaws spiked 153%. These are the kinds of issues scanners miss and reviewers struggle to spot – broken auth flows, insecure designs, systemic weaknesses.


Чудес не бывает. На чем LLM обучили, на том она и хороша. А в сети — тьма открытого кода с пока ещё не найденными уязвимостями этих и аналогичных им hardcase-классов 😕 С помощью ИИ-ассистентов можно получать хороший, стабильный и безопасный код. Но для этого его нужно уметь писать и без них, формулируя соответствующие требования на входе, и проводя ревью результатов на выходе. Ну, и иметь в качестве fallback'а за спиной выстроенные и работающие процессы тестирования и безопасной разработки.

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

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

Видимо аргумент о «чудес не бывает» — пока ещё актуален по обе стороны баррикад 🤷‍♂️
Please open Telegram to view this post
VIEW IN TELEGRAM
💯4👍3
Принял участие в подкасте DevOps Deflope. Поболтали чуть за безопасную разработку и смежные с ней темы 😍
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from DevOps Deflope News
Новый выпуск — и он про безопасность!

В нём эксперт по Application Security из Positive Technologies Владимир Кочетков рассказывает:

• что будет, если вообще забить на безопасность;
• почему от уязвимостей бизнес-логики «никогда в жизни не защитит» даже самый крутой AF;
• правда ли, что хакеры теперь умнее нас из-за ИИ;
• как внедрить безопасность, чтобы тебя не возненавидели все разработчики.

Слушать →
на удобной площадке
на YouTube
на Яндекс Музыке
в Вконтакте
54👍3👌1
Forwarded from OK ML
Уязвимости в дата-репозиториях. Обзорно главное

Репозитории для анализа данных и ML - зона повышенного риска ⚠️. Быстрое прототипирование, работа с чувствительными данными и специфичные инструменты создают уникальные векторы атак.
Вот ключевые из них:

1. 🤫 Секреты в коде.
Самая распространённая и критичная уязвимость. Хардкод API-ключей (например, к AWS S3, OpenAI, базам данных), токенов доступа и даже паролей прямо в Jupyter Notebook, конфигурационных файлах и скриптах. При попадании такого кода в публичный репозиторий злоумышленники получают прямой доступ к платным сервисам и данным.

Лечение
git grep’ + ‘truffleHog’, ротация ключей, менеджер секретов.

2. 🧑‍💻 RCE через десериализацию
Библиотеки pickle и joblib - стандарты для сохранения ML-моделей в Python - небезопасны. Десериализация файла из ненадёжного источника может привести к выполению произвольного кода на машине.

Лечение
yaml.safe_load(),
ONNX, sandbox.

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

Лечениеты в коде.
‘nbstripout’ аудит перед коммитом. Регулярно аудить права доступа (IAM) к S3-бакетам, базам данных и другим ресурсам. Принцип наименьших привилегий - база 🤭.

4. 🙈

DoS через загрузку моделей. 
Эндпоинт для загрузки моделей без проверки размера файла может быть атакован путём отправки огромного файла, что приводит к переполнению диска и отказу в обслуживании (Denial-of-Service).

Data Poisoning. Злонамеренное изменение обучающих данных для подрыва работы модели (например, добавление в выборку для классификации спама писем с определённым словом, помеченных как "не спам").

Adversarial Attacks. Специально сконструированные входные данные, предназначенные для обмана модели (например, незаметные для человека изменения в изображении, заставляющие модель видеть не то, что есть на самом деле)

Лечение
Pre-commit хуки, сканирование в CI/CD, обучение DS основам безопасности.Менеджеры секретов, безопасные форматы сериализации, инструменты для мониторинга (Evidently AI, WhyLabs).

#DataSecurity #MLSecurity #PickleRCE #SecretsManagement #DevSecOps

🔗 Полезные ссылки:
1. TruffleHog— сканер секретов
2. nbstripout — очистка ноутбуков
3. OWASP Top 10 — главные уязвимости
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
Два «питомца» для ИИ-пентеста: CAI и PentAGI

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

CAI

Открытый фреймворк, реализующий функциональность ассистента пентестера.

• Сканы, поиск уязвимостей (SQLi, XSS, LFI) и базовая эксплуатация — всё в режиме автономного агента.

• Дружит с 300+ LLM (от OpenAI до Ollama), логирует действия через Phoenix и ставит guardrails, чтобы бот не сломал сам себя.

• В CTF-замерах оказался в среднем в 11 раз быстрее человека, а на отдельных задачах — в 3600 раз.

• Уже отмечен в TryHackMe и Hack The Box: находит бреши, читает /etc/passwd, но пока далёк от идеала — цепочки атак увы ещё не особо осиливает. Кожаный мешок с соответствующей экспертизой где-то рядом всё же нужен — агент далеко не всегда безошибочен и не во всем автономен.

PentAGI

По-настоящему автономный ИИ-пентестер со встроенными тулзами и собственной «долгой памятью»

• Более 20 классических инструментов (nmap, Metasploit, sqlmap и т.п.) прямо из коробки.

• Встроенный браузер и поиск (Google, DuckDuckGo, Tavily) для разведки.

• Векторная база знаний (PostgreSQL + pgvector), чтобы помнить свои прошлые результаты и выстраивать сложные цепочки последовательных атак в рамках одного дерева.

• Отчёты и метрики в Grafana/Prometheus, всё в Docker, разворачивается относительно легко.

• Ориентирован на топовые облачные LLM и весьма прожорлив до токенов (но оно того стоит).

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

...или пугать, это уж как посмотреть 😬
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42🤗1
Как разработчику быстро вкатиться в тему LLM? Часть 5 (заключительная)

Часть 4

5. Мультиагентные системы и протоколы взаимодействия

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

Вот лишь некоторые возможные паттерны ролей агентов в MAS:

• Planner → Executors: планировщик дробит задачу, исполнители — узкоспециализированные агенты.

• Critic/Verifier: независимая проверка фактов/ограничений, «красные команды», контрафактуальная проверка.

• Tool-specialists: агенты-обёртки над конкретными инструментами (Bash, Snowflake, Jira).

• Memory/RAG-агенты: отдельный агент управление знанием (индексация, извлечение, цитирование).

О проектировании MAS неплохо написано тут.

Агентам в MAS нужно как-то взаимодействовать с окружением и друг-другом. С этой целью были созданы протоколы A2A от Google, и MCP от Anthropic. Поверхностно ознакомиться с ними поможет эта статья. Вкратце:

MCP – представляет собой «универсальный разъём a-la USB» между LLM-агентом и внешними инструментами. Протокол вводит три роли участников: Host (основное приложение/интерфейс, где работает агент), Client (компонент-встроенный коннектор при модели) и Server (поставщик инструментов или данных). Фактически, Host координирует диалог и хранит общую память, Server предоставляет реализацию какого-то действия (например, доступ к базе знаний или вызов внешнего API), а Client-соединение позволяет модельному агенту запрашивать у Host доступные инструменты и вызывать их. За счёт этого агент может использовать произвольные инструменты через единый протокол, не требуя от разработчика писать для каждого API свой код обработки.

A2A же — протокол «агент-агент», дополняющий MCP: если MCP фокусируется на подключении инструментов, то A2A стандартизирует коммуникацию между независимыми агентами (каждый из которых может быть отдельным сервисом). Агент в A2A публикует свой «карточку» с описанием возможностей, а другие агенты могут посылать ему задания через HTTP. В сочетании, MCP и A2A покрывают разные уровни: MCP – подключение одного агента к инструментам и контексту, A2A – связь между разными агентами.

Для начала работы с MCP неплохо также ознакомиться и с этой статьей.

Разумеется, изобретать заново архитектуры MAS и реализовывать протоколы взаимодействия особой необходимости нет — существуют специализированные фреймворки, в которых «всё уже украдено до нас». Наиболее популярным из них является CrewAI: Python-фреймворк, упрощающий создание и оркестрацию группы агентов. В нём вводятся основные сущности – Agent (автономный агент с определённой ролью и целями), Task (задача для агента), Crew (группа агентов, объединённых общей целью), Tool (внешний инструмент, которым могут пользоваться агенты). Фреймворк берёт на себя маршрутизацию задач между агентами и сбор результатов. Стартовать с ним поможет эта статья.

Более подробный обзор доступных открытых решений для разработки ИИ-агентов представлен здесь.

Задачка на потренироваться:

Доработать coding-агента из предыдущего задания, добавив к нему verifier-агента на базе другой reasoning-модели, верифицирующего полученные результаты.

———

На этом, серия постов про вкатывание в разработку для LLM подошла к концу. Но не рубрика «LLM для разработчиков». Stay tuned, как говорится☺️
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥71
Эстетика ИИ-агентов: и снова... Claude Code

В догонку к предыдущему посту. На днях The Pragmatic Engineer опубликовали статью «How Claude Code is built», которая однозначно заслуживает внимания. Тезисно:

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

Минимум кода вокруг модели: разработчики сознательно удаляли вспомогательную логику, чтобы ИИ сам брал на себя максимум работы. Это риск — меньше контроля и привычных «страховок», но выигрыш в скорости развития.

Лёгкий, нестандартный стек: TypeScript + React (Ink) + Yoga для терминального UI, Bun для сборки. Решили не тянуть привычные тяжёлые фреймворки, чтобы обновления шли мгновенно.

Рекордный темп: до 100 внутренних релизов в день, десятки прототипов за пару суток. Такую скорость поддержали «короткие циклы доверия»: фичи выпускаются рано, чтобы сразу получать фидбек, а не шлифовать месяцами.

Дерзкий баланс свободы и безопасности: Claude Code может менять файлы и запускать команды, но каждое действие требует подтверждения. Разработчики сознательно дали модели широкие полномочия — с минимальным, но чётким контролем пользователя.

Sub-agents за 3 дня: идею «агентов внутри агента» оформили в продакшн после двух провальных попыток — показав, что команда готова быстро рисковать и отбрасывать неудачные решения.

В деталях:
24🔥2👍1
SymbolicAI — правильный подход к нейросимвольному программированию.

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

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

Символы (Symbol) – это базовые объекты данных, которым можно задавать операции как обычным Python-методам, а при необходимости переключаться в семантический режим для логических или лингвистических вычислений.

from symai import Symbol
S = Symbol("Cats are adorable", semantic=True)
print("feline" in S) # True — семантическая проверка «относится ли 'feline' к S»


Возможности

• Универсальные операции. Символы поддерживают перегруженные операторы: == для «приближённого» равенства, + для смыслового объединения и & для логического вывода. Все операции можно комбинировать в цепочки на одном объекте, чередуя «синтаксический» и «семантический» режимы. Фреймворк умеет переводить тексты, отвечать на запросы и выполнять обычные функции.

Например, перевод:
from symai import Symbol
S = Symbol("Welcome to our tutorial")
print(S.translate('Russian')) # «Добро пожаловать на наш урок!»


или лингвистические аналогии:
S = Symbol("King - Man + Woman").interpret()
print(S) # “Queen”


• Контракты и проверка. Для надежности разработчики ввели механизм контрактов (Design by Contract, DbC) – позволяющий описывать входные/выходные модели и автоматически проверять или корректировать результаты LLM.

• Интеграция с сервисами. SymbolicAI умеет работать не только с LLM, но и с WolframAlpha, OCR, поиском в интернете и мультимодальными источниками: изображениями, речью и т.п. Это позволяет использовать фреймворк для самых разных задач: от анализа текста и генерации вывода до поиска фактов и работы с данными.

Ещё примеры

Семантическая замена:
from symai import Symbol
items = Symbol(['apple', 'banana', 'cherry', 'cat'])
print(items.map('replace fruits with vegetables'))
# -> ['carrot', 'broccoli', 'spinach', 'cat']


Использование вызова инструментов:
from symai.components import Function

tools = [{
"type": "function",
"function": {
"name": "get_weather",
"denoscription": "Get current temperature for a location.",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}]

fn = Function(
"Choose and call the appropriate function",
tools=tools
)

# GPT-style tool call
resp = fn("What's the temperature in Bogotá, Colombia?", raw_output=True)
# resp.choices[0].finish_reason == "tool_calls"
# resp.choices[0].message.tool_calls[0].function.name == "get_weather"


Использование контрактов:
from symai import Expression
from symai.strategy import contract
from symai.models import LLMDataModel
from typing import Optional, List # For type hints in examples

# Default retry parameters used if not overridden in the decorator call
DEFAULT_RETRY_PARAMS = {
"tries": 5, "delay": 0.5, "max_delay": 15,
"jitter": 0.1, "backoff": 2, "graceful": False
}

@contract(
pre_remedy: bool = False,
post_remedy: bool = True,
accumulate_errors: bool = False,
verbose: bool = False,
remedy_retry_params: dict = DEFAULT_RETRY_PARAMS # Uses defined defaults
)
class MyContractedClass(Expression):
# ... class implementation ...
pass


Ещё больше примеров есть в документации.

Кмк, классный инструмент для, как минимум, экспериментов ресерчеров в Jupyter-like ноутбуках (примеры). А продуманные средства DbC как бы намекают на пригодность использования и в серьезных продакшн-системах.

Must have, короче.
1🔥3
Forwarded from OK ML
Awesome AI Apps - технический гид по созданию LLM-приложений

🦙 Репозиторий awesome-ai-apps - коллекция продакшен-примеров для построения приложений на базе LLM. Внутри — проекты на LangChain, LlamaIndex + habr, CrewAI, Agno, Mastra, Nebius AI Studio, GibsonAI и много других полезных!..

Что можно найти:
- минимальные прототипы на базе OpenAI SDK, LangGraph, Camel AI — идеальны для экспериментов,
- готовые сценарии вроде финансового трекера, HITL-агента или бот для веб-автоматизации,
- демонстрации работы с Model Context Protocol (MCP) для репозиториев, документов или бд. Это особенно актуально для стандартизации, взаимодействия между агентами и внешними сервисами. Ну и тем, кто оттягивает знакомство с MCP, еть уже готовые анализ GitHub-репо, QnA по документации, работа с Couchbase и GibsonAI DB. Не оттягивайте 🤪.
- агенты с persistent memory (на Memori), которые позволяют строить более контекстно-зависимые системы (например, arXiv Researcher или Social Media Agent).
- примеры Agentic RAG (они не устарели!!!) с использованием Qdrant, Exa, LlamaIndex. Поддержка работы с PDF, кодом и OCR (Gemma3).
- комплексные пайплайны (например, Meeting Assistant, который конвертирует митинг в задачи и заметки, или Finance Service Agent на FastAPI)

Что под капотом (продублируем для удобства твоего гугл эдвэнсед, большинство ссылок выше) и ждет, когда затащишь себе?
🫰 LangChain + LangGraph для оркестрации агентов.
🫰 Agno как фреймворк для построения agentic workflows.
🫰 CrewAI для мультиагентных исследований.
🫰 LlamaIndex как основа RAG и документных ассистентов.
🫰 Memori для хранения контекста и долгосрочной памяти.
🫰 Nebius AI и Bright Data — как инфраструктурные провайдеры.

Установка (единый паттерн):

git clone https://github.com/Arindam200/awesome-ai-apps.git
cd awesome-ai-apps/<project_name>
pip install -r requirements.txt

🧘‍♀️ Каждый проект снабжен своим README.md, а там можно и сразу стартовать.

Этот репозиторий можно в чистом виде 🏖️ R&D-песочница, быстро тестировать разные стеки, паттерны взаимодействия агентов, интеграции MCP и реализацию RAG. Гении, как известно, воруют 👌

#AI #LLM #RAG #LangChain #LlamaIndex #CrewAI #Agno #Memori #AIagents #opensource #MCP #Python #MachineLearning #GenerativeAI
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍4
Новый взгляд на «контекст» в ИИ: от prompt engineering к context engineering

Команда Anthropic опубликовала статью «Effective Context Engineering for AI Agents», где утверждает, что в эпоху агентных систем привычное «написать правильный prompt» постепенно уступает место более широкому подходу — контекст-инженерии. Контекст — не просто текст промпта, а весь набор токенов, который модель «видит» в момент вывода.

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

Что составляет контекст-инженерию на практике?

• Отказ от перегруженных инструкций и «жёстких» шаблонов в пользу сбалансированных, гибких указаний.

• Динамическое подключение данных по принципу «just in time»: агент подгружает нужные фрагменты контекста в момент, когда они действительно важны.

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

По мнению авторов, context engineering — это не просто тренд, а фундаментальный сдвиг в проектировании ИИ-агентов. Даже по мере роста возможностей моделей, бережное управление вниманием остаётся ключом к стабильному и надёжному поведению.
1👍2💯1
О t-строках в Python 3.14

В юбилейной π-версии Python реализован новый подход к обработке строк, описанный в PEP-750, и уже вызвавший неоднозначную реакцию в сети. По сути, шаблонные строковые литералы, или t-строки (t"…") — литералы, которые выглядят как f-строки, но не вычисляются сразу же в str. Вместо этого они возвращают объект Template с раздельным доступом к статичной части и вставкам в неё. Это даёт библиотекам шанс корректно экранировать/параметризовать значения под конкретный контекст (SQL, HTML, shell и т.д.) и, якобы, тем самым снизить риск инъекций.

Например, t"Hello {name}" создаёт string.templatelib.Template, в котором доступны части строки и интерполяции, как объекты Interpolation(value, expression, conversion, format_spec). У Template нет __str__, поэтому его невозможно «случайно» напечатать как готовую строку — нужно явно вызвать обработчик (например, html(template) или sql(template), в соответствии с грамматикой принимающей стороны).

На самом деле — очень здравая языковая фича, позволяющая строить эффективную обработку выходных данных за счет:

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

• Запрета «тихой» конкатенации со строками (сложение Template + str запрещено, разрешено только Template + Template.

• Явного рендера за счет отсутствия __str__, заставляющего разработчика осознанно походить к выбору обработчиков.

• Композиционности. Обработчики не обязательно должны возвращать строки, что позволяет объединять их в цепочки. Можно вкладывать шаблоны и обрабатывать по уровням контекста (например, атрибуты HTML как dict → безопасная строка атрибутов).

В psycopg, например, уже подсуетились и реализовали параметризацию SQL-запросов через t-строки в текущем dev своей библиотеки. Их обработчик можно подсмотреть в _trstrings.py.

Пример простого обработчика, санитизирующего данные в контексте HTML/Text:

from html import escape
from string.templatelib import Template, Interpolation

def html(tmpl: Template) -> str:
out = []
for part in tmpl:
if isinstance(part, Interpolation):
out.append(escape(str(part.value)))
else:
out.append(part)
return "".join(out)

evil = "<noscript>alert(1)</noscript>"
assert html(t"<p>{evil}</p>") == "<p>&lt;noscript&gt;alert(1)&lt;/noscript&gt;</p>"


Однако, как и говорится в описании изменений, t-строки — это лишь механизм обработки строк, а не панацея от инъекций, неправильное использование которого позволит прострелить себе конечность не менее лихо, чем в случае с f-строками:

• Эффективность санитизации интерполяций — целиком зависит от правильного выбора или написания их обработчиков.

• Все выражения внутри блоков {…} вычисляются сразу же в лексическом скоупе, интерполяцией же становится результат этого вычисления. Поэтому t"{eval(request.get['a'])}" — это всё ещё RCE, вне зависимости от обработчиков. Похожая история — и с попаданием в Template или Interpolation входных данных при создании объектов этих классов из конструкторов (вообще, стоит этого по-возможности избегать, и пользоваться предложенным синтаксическим сахаром t"…").

• Конкатенация Template + Template разрешена. Это удобно, но может породить «вирусность» шаблонов и неочевидную логику сборки, если смешивать части, ожидающие разных политик экранирования.

• Формат-спецификаторы внутри {…} вычисляются до format_spec, что может привести к потере грамматического контекста, когда придёт время обработчика.

• Валидацию входных данных в соответствии с бизнес-логикой этот механизм не заменяет, и относится лишь ко второму эшелону эффективной обработки данных.

В общем, механизм годный, использовать стоит, но «думать всё равно придётся» (с) 😊
12🔥2