📱

Get Our Mobile App

Take your business learning on the go!

Download on the App StoreGet it on Google Play

Build Systems, Not Code - Angie Jones, Agentic AI Foundation

AI Engineer19:39

Transcription

В последнее время я много занимаюсь созданием агентов для операционных задач. И вот однажды вечером в пятницу, когда я работал, я увидел закат. А потом пришло время ужина, и оно прошло. И тут меня осенило. Я был в этом знакомом потоке разработки. И азарт от создания вернулся. Многие из нас, кто пишет код с помощью агентов, испытывают это тихое чувство страха. Как будто они забирают все интересные части создания, оставляя нам неприглядную работу, но позвольте мне дать вам небольшой совет. Пусть они это сделают. Потому что, если вы подниметесь всего на один уровень выше, вы обнаружите, что азарт все еще здесь. Когда вы создаете агентов, а не просто используете их для написания кода, вы начинаете заниматься архитектурой агентных систем. И вы понимаете, что строительные блоки разные, но дисциплина та же. Итак, я обнаруживаю, что сейчас использую те же инженерные мышцы, что и до появления генеративного ИИ. И мне это очень нравится. Итак, я собираюсь пройтись по процессу проектирования агента. Я покажу вам, где инженерные навыки по-прежнему играют роль. Итак, агент — это агент по подбору жилья, который занимается поиском дома. И если бы вы сделали это как одноразовый запрос, который указывает агенту на некоторые объявления и просит его ранжировать их, я имею в виду, это сработает, но вы, вероятно, не найдете дом за день, верно? Поэтому вы хотите построить это как агентную систему, которую можно повторно использовать. Ту, которая может сохранять знания вне сеанса. Вы знаете, она могла бы перезагрузить или запросить эти знания позже, чтобы принимать решения даже в новом контексте. Итак, думая о том, как спроектировать агента, первый инженерный навык, который я применил, — это системное мышление. Итак, агент — это не система, верно? Это часть системы. И эта система имеет файлы и инструменты, людей, даже других агентов. Таким образом, агент по подбору жилья находится внутри чего-то большего, и он извлекает объявления и сигналы о районах. Он взвешивает их против того, что меня волнует, а затем возвращает мне ранжированный короткий список. Итак, я часто слышу, как люди говорят: «Просто позвольте вашему агенту по написанию кода создать его, верно?» И я думаю, что это ошибка. Да, мой агент по написанию кода может создать его, но прежде чем позволить ему это сделать, мне нужно подумать обо всей среде, всей системе, верно? Я хочу подумать о том, в чем заключается работа этого агента? От чего он зависит? Что произойдет, если он сломается? И я хочу относиться к нему как к любому другому компоненту, у которого есть границы и обязанности, есть зависимости, понимаете? И способы, которыми он может потерпеть неудачу. И весь этот мыслительный процесс — это инженерия. Второй навык — это проектирование рабочего процесса. Итак, традиционное программное обеспечение полно рабочих процессов. У нас есть конвейеры CI/CD, верно? У нас есть жизненные циклы билетов, что угодно. Агентные системы нуждаются в таком же дизайне. Как бы мы все ни любили команду /goal, агенту нужно больше, чем цель, ему нужен путь. Когда мы говорим: «Просмотри это объявление», это цель, но рабочий процесс определяет, что на самом деле должно произойти, верно? [кашляет] Например, агент должен собрать то, что ему нужно, он должен взвесить объявление против моих критериев, а затем действовать, верно? И каждый запуск заканчивается одним из трех способов. Либо он остановится, либо повторит попытку, либо эскалирует. Итак, этот путь формирует остальную часть архитектуры. Как только я увижу, как работа проходит через систему, я смогу принимать лучшие решения о том, какой контекст нужен агенту, какие части я хочу, чтобы агент обрабатывал напрямую, и когда инструмент или человек должны взять на себя управление. Мы все знаем опасность одной гигантской вещи, которая делает все, верно? Мы смеемся, когда видим один гигантский класс или большую старую функцию, которая делает слишком много, верно? Или раздутый сервис с миллионом конечных точек. Мы называем это запахами кода. Ну, у агентных систем есть своя версия этого. Это гигантские запросы. И это начинается довольно невинно. Например, в файле инструкций я могу сказать агенту по подбору жилья, как оценить объявление. Справедливо. Но потом я сталкиваюсь с крайним случаем, поэтому возвращаюсь. Добавляю заметку для этого. А потом вспоминаю правило безопасности, верно? Так что, конечно, это должно быть там. Я горжусь тем, что даже помню, как это туда добавить, верно? А потом, о да, есть еще одно очень важное исключение. И прежде чем вы это заметите, этот запрос будет делать все. И ваш инженерный «паучий» инстинкт уже знает, что это беспорядок. Так почему бы вам не сделать шаг назад, чтобы разложить его, верно? Декомпозиция означает выявление отдельных задач, которые скрываются внутри этого одного блока, и их разделение на отдельные части. Итак, если я посмотрю на запросы для агента по подбору жилья в целом, они включают в себя многоразовый процесс извлечения и нормализации объявления, а затем у них будет фиксированный формат для написания короткого списка. В нем есть небольшой раздел о том, как рассчитать время в пути, а затем объемная подзадача об исследовании района. Это четыре разные задачи, упакованные в один запрос. И тогда вы удивляетесь, почему ваш агент дрейфует и не придерживается сценария. Сценарий слишком длинный. Итак, я не говорю, что вам нужно разделять вещи ради самого разделения, но суть в том, чтобы сделать каждую часть более понятной, верно? Таким образом, проще ставить задачи. Проще вносить изменения, когда это необходимо. Теперь декомпозиция — это разделение системы. Разделение ответственности — это размещение каждой обязанности в правильном месте. И вот здесь создание агентов начинает казаться мне очень знакомым, потому что в традиционном программном обеспечении мы задавали такие вопросы, как: должно ли это жить в контроллере или в сервисном слое? Или, знаете ли, это бизнес-логика или представление? Итак, при создании агентов у вас могут возникнуть те же вопросы. Просто есть разные места, куда можно поместить вещи. Итак, процесс нормализации объявления, должен ли он оставаться скрытым в запросе? Или, может быть, он станет навыком, верно? Я хочу, чтобы каждое объявление в коротком списке было отформатировано одинаково. Так что этот структурированный вывод, вероятно, должен быть определен в схеме. Разве вы не сделали бы так, если бы сами кодировали систему? Я бы сделал. А затем часть, которая рассчитывает время в пути, может быть помещена в приятный маленький скучный скрипт. А исследование района — это достаточно объемно, им, вероятно, должен заниматься суб-агент. Теперь вы используете лучшие инструменты для работы, и становится яснее, где что найти в системе. Модульность также важна в агентных системах. Точно так же, как у нас есть многоразовые функции, классы и библиотеки, теперь я также думаю о многоразовых возможностях агентов. И самый наглядный пример этого — навык агента. Так что создание навыка для нормализации объявлений очень полезно, когда вам нужно расширить обязанности агентов. Например, что, если я расширю поиск дома на три города? Каждый из этих рынков может загрузить один и тот же навык. Итак, я написал его один раз, и все они могут его использовать повторно. Таким образом, это стало компонентом, который я могу повторно использовать в разных агентах или даже делиться с другими людьми. Похоже на то, как мы полагаемся на пакеты. А затем суб-агенты — это еще один тип многоразового модуля. Итак, многие люди, с которыми я разговариваю, не совсем понимают смысл суб-агентов. Архитектурно они похожи на функции, верно? Вы даете им одну конкретную задачу, вы вызываете их, когда это нужно сделать, и они могут сделать это очень хорошо, потому что это все, что находится в их области видимости, верно? Они не несут контекст всего сеанса с собой. Так что, например, наш суб-агент по исследованию района, мы можем вставить его в любой рынок или рабочий процесс, и он работает, знаете ли, для того, что он должен делать. Он хорош в любом районе. Но, как и во всем, решение о том, что должно быть модулем, требует некоторого суждения, верно? Не все должно быть повторно использовано. Некоторые инструкции локальны для данного рабочего процесса, верно? Возможно, не стоит абстрагировать, потому что иногда это стоит больше, чем экономит. Но это просто еще одно инженерное решение здесь, верно? Агентные системы имеют такие же компромиссы. Алгоритмическое мышление. Это один из самых важных навыков в проектировании агентных систем. То, что агент может что-то сделать, не означает, что он должен это делать, верно? Некоторые задачи лучше решаются обычным кодом. Например, расчет времени в пути или удаление дубликатов объявлений, которые я уже видел, модель агента лучше справляется с такими вещами, как нечеткие, знаете ли, нечеткие вещи, суждения, неоднозначность, рассуждения над нечетким вводом. И игнорирование этого различия — вот где я вижу, как многие агентные системы становятся сложнее, чем были раньше. Итак, вы используете модель, вы передаете ей всю задачу для выполнения, а затем расстраиваетесь, когда результат каждый день отличается. Но некоторые из этих вещей можно решить с помощью обычного кода, верно? Это будет дешевле, это будет надежнее. Обещаю вам, ИИ не изобрел автоматизацию, верно? Мы можем использовать код, продолжая использовать эти системы. Итак, мое эмпирическое правило здесь: если у задачи есть точный ответ, используйте код. Если требуется интерпретация или суждение, тогда вы можете поручить это агенту, верно? Итак, используйте код для детерминизма, используйте агентов для суждений, а затем используйте людей для авторитета. Итак, агент решает, какие объявления стоит рассмотреть подробнее, код рассчитывает время в пути, отфильтровывает те, которые я уже видел, а затем я тот, кто одобряет фактическое бронирование тура по дому. Свободный текст подходит, когда его читает только человек. Но когда другая система должна действовать на основе вывода агента, тогда лучше иметь контракт, обычно. Итак, мы уже делаем это везде в программном обеспечении. Всякий раз, когда две системы общаются, между ними есть согласованная форма, да? Итак, агентным системам нужна та же дисциплина. Например, когда агент по подбору жилья оценивает дом, он не должен просто передавать сообщение и считать, что дело сделано, верно? Это приятно читать мне в данный момент, но это тупик для системы. Если решение зарыто где-то в наших сеансах, ничто ниже по потоку не сможет его надежно найти. Вместо этого оно записывается в структурированную форму в памяти агента. И я использую Compendium Wiki для этого для моего слоя памяти агента на большинстве моих агентов. Но здесь есть решение, оценка, причина, и поскольку это структурировано, эта память становится доступной для запросов. Так что позже я могу спросить агента по подбору жилья: «Покажи мне все дома с оценкой четыре или выше, с временем в пути 15 минут или меньше, верно?» И он действительно может это получить, потому что оценка и время в пути находятся в известных местах. Они не заперты в сеансовом разговоре. И не только мне нужно получить эту информацию. Мой шаг короткого списка в системе читает те же поля без участия человека. Таким образом, вывод агента является входными данными для следующего шага. И, следовательно, контракт делает этот переход безопасным. И знаете, самое приятное то, что определение формы заставляет вас быть действительно четким и конкретным. Потому что, если вы не можете сказать, как должен выглядеть вывод, то, вероятно, вы еще не полностью понимаете, что вы просите агента произвести. Итак, запрос может выполниться один раз и быть завершенным, верно? Но полезная агентная система должна уметь работать в реальных условиях, где веб-хуки срабатывают дважды, или запуск не завершается по какой-либо причине, и вам нужно повторить поток. Итак, агент должен отслеживать свое состояние. Было ли это действие уже предпринято? Если да, изменился ли ввод, верно? Если нет, сеанс дал сбой или что-то вроде того, какие части этого я могу безопасно повторить? И это не исключение, верно? Это происходит все время. Итак, вам нужно спроектировать для идемпотентности, то есть когда вы можете выполнить одно и то же действие дважды, и второе выполнение не вызовет беспорядка. И мы часто делаем это в традиционном программном обеспечении. Но с агентами они добавляют небольшую ловушку, потому что вы не можете доверять модели, потому что ее выходные данные могут варьироваться, верно? Так что повторная попытка рискует тем, что агент фактически перефразирует запрос ровно настолько, что это может выглядеть как совершенно новая задача. Так что вам придется обеспечить это в системе. Давайте посмотрим на пример с нашим агентом. Итак, предположим, приходит новое объявление, и агент по подбору жилья хочет отправить электронное письмо моему риелтору, чтобы спросить о просмотре. Итак, после этого действия агент должен записать в память, что он отправил это электронное письмо, верно? А затем агент идет в мой календарь и хочет просто заблокировать это время на всякий случай. Но он сбоит, прежде чем успевает предпринять это действие. Итак, этот запуск выполнен только наполовину. Позже запускается проверка кода. Кстати, вам нужно проводить проверку кода с этими вещами, чтобы поддерживать их в рабочем состоянии, но во время проверки кода она замечает, что письмо было отправлено, но календарь так и не был заблокирован. Итак, она повторяет задачу. Но она не должна снова отправлять электронное письмо моему риелтору, верно? Это уже произошло. Я не хочу быть надоедливым клиентом, вы знаете, я отправляю все эти электронные письма. Так что ей нужно просто завершить ту часть, которая не произошла, а именно [кашляет] блокировка моего календаря. Но она знает это только потому, что проверяет, что записала система, верно? Так что, если мы запустим это снова, агент просто завершит то, что отсутствует, вместо того, чтобы создавать беспорядок. Моделирование угроз — очень важный навык при проектировании агентных систем. Все сейчас на нервах по поводу этих вещей, верно? Но инженерия безопасности уже научила нас основам. Нам нужно проверять ваши входные данные, знаете ли, предоставлять минимальные необходимые привилегии, и устанавливать границы вокруг того, чего может коснуться действие. Итак, агентные системы нуждаются во всем этом. Наш агент по подбору жилья будет потреблять много контента от незнакомцев, верно? Агент должен читать текст объявления от продавца, темы форумов и отзывы о районах от анонимных людей в Интернете. Так что нам нужно рассматривать все это как недоверенный ввод и четко дать понять агенту, что это доказательства, а не инструкции. А затем, после рассмотрения входных данных, вы также хотите подумать о том, какие границы следует установить вокруг того, что агент способен делать. Например, наш агент может читать объявления и создавать короткие списки весь день. Делай что хочешь, верно? Но я не хочу, чтобы он автономно отправлял электронные письма продавцам, бронировал туры или, упаси боже, подавал предложения от моего имени, верно? Так что эти действия должны быть заблокированы за моим одобрением, верно? И когда вы проводите эту стену, вы уменьшаете радиус поражения и, надеюсь, минимизируете свое подверженность риску. Теперь каждый инженер может понять, каково это — унаследовать систему, которую вы едва понимаете. Это одна из ключевых причин, по которой я не позволяю своему агенту по написанию кода проектировать моих других агентов, потому что я знаю, что он будет собран таким образом, что технически работает, но не поддается сопровождению, верно? Вероятно, будет гигантский запрос, и даже если агент разложит его, я не знаю. Я просто не убежден, что он правильно разделит ответственность. Знаете, у меня проблемы с доверием. Что я могу сказать? Итак, в моих агентных системах я гарантирую, что сопровождаемость встроена в саму систему. Каждый уровень системы имеет файл D агента, объясняющий рабочий процесс и где находится политика, вспомогательные ресурсы, такие как навыки, скрипты и суб-агенты, и, самое главное, как поддерживать его память в актуальном состоянии. Таким образом, любой, человек или агент, может войти в систему и сориентироваться, не нуждаясь в обратной инженерии кучи запросов. Фактически, это и есть тест. Я проектирую своего агента так, чтобы даже в новом контексте он мог сразу же приступить к работе в системе и начать с нуля, зная точно, что делать. И это тоже очень помогает. Так что всякий раз, когда мне нужно изменить систему, верно? Так что я могу практически взять любой каркас и сказать: «Обнови этого агента, чтобы он делал XYZ». И поскольку система так хорошо спроектирована, шансы на ее успешное обновление намного выше. Если он случайно столкнется с какими-либо проблемами при попытке обновления, это сигнал для меня о том, что мне нужно улучшить сопровождаемость системы. Таким образом, проектирование агентов — это инженерия программного обеспечения. Примитивы разные, но дисциплина та же. Нам все еще нужно понимать систему. Нам нужно определить рабочий процесс и знать, что в него входит. Нам все еще нужно разбить проблему и разместить обязанности в правильном месте, сделать правильные вещи многоразовыми, определить, какие актеры лучше всего подходят для каких задач, определить контракты, управлять состоянием, проектировать для безопасности и сделать систему понятной. Вот почему создание агентов может дать вам тот же азарт от создания программного обеспечения. Мы все еще строим. Мы просто поднялись на уровень выше. Большое спасибо.