📱

Get Our Mobile App

Take your business learning on the go!

Download on the App StoreGet it on Google Play

12-Factor Agents: Patterns of reliable LLM applications — Dex Horthy, HumanLayer

AI Engineer17:06

Transcription

[Музыка] Кто здесь строит агентов? Поднимите руку, кто построил 10+ агентов? Кто-нибудь здесь построил около сотни агентов? Хорошо, у нас есть несколько. Отлично. Мне нравится. Итак, я думаю, многие из нас прошли этот путь построения агентов. И то, что случилось со мной, знаете, я решил, что хочу построить агента. Мы выяснили, что мы хотим, чтобы он делал. Мы хотим двигаться быстро. Мы разработчики, поэтому мы используем библиотеки. Мы не пишем все с нуля. И вы доводите это до 70-80%. Этого достаточно, чтобы вызвать восторг у генерального директора и добавить еще шесть человек в вашу команду. Но потом вы понимаете, что 70-80% недостаточно хорошо. И если вы хотите преодолеть этот барьер качества в 70-80%, вы находитесь на семи уровнях в стеке вызовов, пытаясь реверс-инжинирингом понять, как создается этот промпт, или как передаются эти инструменты? Откуда все это берется? И если вы такой же, как я, вы в конечном итоге просто выбрасываете все и начинаете с нуля. Или вы можете даже обнаружить, что это не та проблема, для которой подходят агенты. Я помню одного из первых агентов, которого я пытался построить, был агент DevOps. Я сказал: "Вот мой make-файл. Вы можете выполнять make-команды. Соберите проект". Не смог разобраться. Сделал все не в том порядке. Я думаю: "Круто, давайте исправим промпт". И за следующие два часа я добавил все больше и больше деталей о том, что было, и о каждом шаге, и о точном порядке, пока не дошел до точки, где я сказал: "Это точный порядок выполнения шагов сборки". Это было классное упражнение, но в конце я подумал: "Я мог бы написать bash-скрипт, чтобы сделать это примерно за 90 секунд". Не каждая проблема требует агента. И вот я нахожусь на этом пути. Я думаю, многие из вас прошли похожие пути. И то, что произошло, это я пошел и поговорил, пытаясь помочь людям строить лучшие, более надежные агенты. Я поговорил с более чем 100 основателями, строителями, инженерами. И я начал замечать закономерности. Одна из них заключалась в том, что большинство производственных агентов на самом деле не были такими уж "агентными". Это были в основном просто программы, но были эти основные вещи, которые делали многие люди. Были эти закономерности, которые делали их приложения на основе LLM действительно, действительно хорошими. И ни один из них не делал своего рода "чистого листа", переписывая все. Скорее, они брали эти небольшие модульные концепции, у которых не было названий и определений, и применяли их к существующему коду. И что действительно здорово в этом, так это то, что я не думаю, что вам нужен опыт в области ИИ, чтобы сделать это. Это основы программной инженерии. Ну, наверное, не основы, но так же, как Heroku пришлось определить, что значит строить облако. Мы даже не называли их "облачными" тогда, но так строились приложения, которые могли работать в облаке 10 лет назад. Я решил собрать то, что, по моему мнению, будет 12 факторами ИИ-агентов. Из всего, что я видел, работая в этой области. Итак, мы создали этот репозиторий на GitHub. Вы можете пойти и прочитать его. Оказывается, многие другие люди согласились и почувствовали то же самое. Итак, мы были на главной странице Hacker News весь день, 200 тысяч показов в социальных сетях. Я просто выставлю это и без комментариев. И для контекста, мы получили около 4000 звезд за месяц-два. Есть 14 активных контрибьюторов. Очень легко прочитать это и услышать разговор и сказать: "О, мы здесь, это разговор против фреймворков". Я не собираюсь критиковать фреймворки. Я бы думал об этом как о списке желаний, списке запросов на функции: как мы можем заставить фреймворки служить потребностям действительно хороших строителей, которым нужна действительно высокая надежность и которые хотят по-прежнему двигаться быстро. Итак, что я здесь делаю? Я хочу, чтобы вы забыли все, что знаете об агентах, и переосмыслили с первых принципов, как мы можем применить все, что мы узнали из программной инженерии, к практике построения действительно надежных агентов. Итак, мы немного изменим порядок. Если вы хотите все 12 факторов по порядку, это 30-минутный доклад, поэтому мы объединим некоторые вещи. В конце будет QR-код. Вы можете изучить его в свободное время. Фактор один, самые волшебные вещи, которые могут делать LLM. Это не имеет никакого отношения к циклам, операторам switch, коду, инструментам или чему-либо еще. Это преобразование предложения вроде этого в JSON, который выглядит так. Даже неважно, что вы делаете с этим JSON. Для этого существуют другие факторы. Но если вы это делаете, это одна часть, которую вы можете интегрировать в свое приложение уже сегодня. Фактор четыре. Это ведет прямо к... кто-нибудь читал эту статью "go to considered harmful" или, может быть, просто слышал о ней? Я никогда ее не читал. Но она была о том, что у нас было это абстракция в языке программирования C и ряде других языков программирования того времени, которая говорила, что эта штука "go to" делает код ужасным. Это неправильная абстракция. Никто не должен ее использовать. Я собираюсь рискнуть и сказать, что использование инструментов вредно. И я ставлю это в кавычки, потому что я не говорю о предоставлении агенту доступа к миру. Очевидно, это супер круто. Но я думаю, что все усложняет идея о том, что использование инструментов — это какая-то волшебная вещь, где некая эфирная инопланетная сущность взаимодействует со своей средой, потому что происходит то, что наш LLM выдает JSON. Мы передадим это некоторому детерминированному коду, который что-то сделает, а затем, возможно, мы вернем это обратно. Но опять же, это другие факторы. Так что, если у вас есть такие структуры, и вы можете заставить LLM выдать что-то, что их генерирует, тогда вы можете передать это в цикл вроде этого или оператор switch вроде этого. Нет ничего особенного в инструментах. Это просто JSON и код. Это фактор четыре. Фактор восемь, и мы объединим здесь пару вещей. Владение вашим потоком управления. И я хочу сделать шаг назад и поговорить о том, как мы сюда попали. Мы давно пишем DAG в программном обеспечении. Если вы писали оператор if, вы писали направленный граф. Код — это граф. Вы также можете быть знакомы с оркестраторами DAG. Кто-нибудь когда-нибудь использовал что-то вроде Airflow или Prefect или что-то подобное? Итак, такая концепция разбиения на узлы дает вам определенные гарантии надежности. Но то, что должны были делать агенты, и я думаю, многие люди говорят об этом, и я думаю, в некоторых случаях это реализовано, это то, что вам не нужно писать DAG. Вы просто говорите LLM: "Вот цель", и LLM найдет путь. И мы моделируем это как очень простой цикл. Знаете, LLM определяет следующий шаг. Вы наращиваете некоторое контекстное окно, пока LLM не скажет: "Эй, мы закончили". Итак, как это выглядит на практике, вы получаете событие. Вы передаете его в свой промпт. Он говорит, что вы хотите вызвать API, и вы получаете результат. Поместите это в контекстное окно. Передайте все обратно в промпт. Это самый наивный и простой способ построения агентов. И LLM вызовет несколько шагов, а затем в конечном итоге скажет: "Круто, мы выполнили все задачи из исходного события, которое, возможно, было сообщением пользователя с просьбой что-то сделать. Возможно, это сбой". Но затем мы получаем окончательный ответ. И наш материализованный DAG — это просто эти три шага по порядку. Оказывается, это не очень хорошо работает. Особенно когда речь идет о более длинных рабочих процессах. В основном это длинные контекстные окна. Есть и другие причины, которые можно было бы поднять. И люди говорят: "О, даже кто-нибудь вводил два миллиона токенов в Gemini раньше и пытался посмотреть, что произойдет?" Вы можете это сделать. Вы получите ответ. API вернет вам что-то. Но я не думаю, что кто-нибудь будет спорить с вами, что вы всегда будете получать более точные, лучшие, более надежные результаты, контролируя и ограничивая количество токенов, которые вы помещаете в это контекстное окно. Итак, это не совсем работает, но мы будем использовать это как нашу абстракцию для построения. Что такое агент на самом деле? У вас есть промпт, который дает инструкции о том, как выбрать следующий шаг. У вас есть оператор switch, который берет любой JSON, выданный моделью, и делает с ним что-то. У вас есть способ наращивать ваше контекстное окно. А затем у вас есть цикл, который определяет, когда, где, как и почему вы выходите. И если вы владеете своим потоком управления, вы можете делать забавные вещи, такие как break, switch, summarize, LM is judge и все такое. И это ведет прямо к тому, как мы управляем состоянием выполнения и бизнес-состоянием наших агентов. Многие инструменты предоставляют вам такие вещи, как текущий шаг, следующий шаг, количество попыток, все эти оркестраторы DAG, они все имеют такие концепции. Но у вас также есть ваше бизнес-состояние. Какие сообщения были отправлены? Какие данные мы показываем пользователю? Какие вещи мы ждем одобрения? И мы хотим иметь возможность запускать, приостанавливать, возобновлять эти вещи, как мы делаем для любых стандартных API. Это все просто программное обеспечение. И если вы можете поместить своего агента за REST API или сервер MCP и управлять этим циклом таким образом, чтобы обычный запрос поступал, и мы загружаем это контекстное окно в LLM. Мы позволим нашему агенту вызывать долгосрочные инструменты. Таким образом, мы можем прервать рабочий процесс, сериализовать это контекстное окно прямо в базу данных, потому что мы владеем контекстным окном. Мы вернемся к этому. А затем, когда мы запустим рабочий процесс, в конечном итоге он вернется с этим идентификатором состояния и результатом. Мы используем идентификатор состояния, чтобы загрузить состояние обратно из базы данных, а затем мы можем добавить результат к программе и отправить его обратно в LLM. Агент даже не узнает, что что-то произошло в фоновом режиме. Агенты — это просто программное обеспечение, так давайте строить программное обеспечение. И построение действительно хороших требует большой гибкости. И поэтому вы действительно хотите владеть этим внутренним циклом того, как все это собирается вместе. Это унификация. Это пауза и возобновление. Фактор два, я думаю, большинство людей находят его первым: вы действительно хотите владеть своими промптами. Есть хорошие абстракции, которые, если вы не хотите тратить много времени на написание промпта вручную, вы можете ввести, и вы получите действительно хороший набор примитивов и действительно хороший промпт. Например, это сделает вас потрясающим промптом, который вам пришлось бы учиться в школе промптинга три месяца, чтобы создать такой хороший промпт, но в конечном итоге, если вы хотите преодолеть какой-то барьер качества, вы будете писать каждый токен вручную. Потому что LLM — это чистые функции фокуса, и единственное, что определяет надежность вашего агента, — это то, насколько хорошие токены вы можете получить, а единственное, что определяет токены, которые вы получаете, помимо переобучения собственной модели и чего-то подобного, — это быть очень осторожным с тем, какие токены вы вводите. Я не знаю, что лучше. Я не знаю, как вы хотите построить свой промпт, но я знаю, что чем больше вещей вы можете попробовать, чем больше настроек вы можете протестировать и чем больше вещей вы можете оценить, тем вероятнее вы найдете что-то действительно, действительно хорошее. Владея своими промптами, вы также хотите владеть тем, как вы строите свое контекстное окно. Таким образом, вы можете использовать стандартный формат сообщений OpenAI или в данный момент, когда вы говорите LLM выбрать следующий шаг, ваша единственная задача — сообщить ему, что произошло до сих пор. Вы можете поместить всю эту информацию, как угодно, в одно сообщение пользователя и спросить: "Эй, что происходит дальше?" или поместить ее в системное сообщение. Таким образом, вы можете моделировать свое состояние событий, свою модель потока, как угодно, и преобразовывать ее в строку, как угодно. И некоторые из трассировок, которые мы используем в некоторых агентах, которые мы строим внутри компании, я расскажу об этом через секунду, могут выглядеть так. Но если вы не смотрите на каждый отдельный токен и если вы не оптимизируете плотность и ясность того, как вы передаете информацию LLM, вы можете упустить возможности и качество. Итак, LLM — это чистые функции, токены на входе, токены на выходе, и все, что делает агентов хорошими, — это инженерия контекста. Итак, у вас есть промпт, у вас есть память, у вас есть RAG, у вас есть история. Все это просто вопрос того, как мы получаем правильные токены в модель. Чтобы она дала нам действительно хороший ответ и решила проблему пользователя. Решила мою проблему в основном. Я не знаю, что лучше, но я знаю, что вы хотите попробовать все. Итак, давайте владеть построением вашего контекста. Это немного спорно. Поэтому это отдельный фактор. И способ сделать его хорошим — интегрировать его с другими факторами. Но вы можете, когда модель ошибается и вызывает API неправильно или вызывает API, который недоступен, вы можете взять вызов инструмента, который она сделала, и получить ошибку, связанную с ним, поместить это в контекстное окно и заставить ее попробовать снова. Кто-нибудь когда-нибудь имел с этим проблемы? Видели, как эта штука просто раскручивается, сходит с ума, теряет контекст и просто застревает? Вот почему вам нужно владеть своим контекстным окном. Не просто слепо добавляйте вещи. Если у вас есть ошибки, а затем вы получаете допустимый вызов инструмента, очистите все ожидающие ошибки. Суммируйте их. Не помещайте весь стек вызовов в ваш контекст. Подумайте, что вы хотите сказать модели, чтобы получить лучшие результаты. Связь с людьми с помощью инструментов. Это немного тонко. Но я видел, что это просто то, что я видел в дикой природе. Почти все избегают этого очень важного выбора в самом начале вывода, когда вы решаете между вызовом инструмента и сообщением человеку. Если вы можете перенести этот акцент на токен естественного языка, вы можете одним дать модели разные способы. Вы можете сказать: "Я закончил", или "Мне нужно уточнение", или "Мне нужно поговорить с менеджером", или что угодно, и дважды вы переносите намерение на генерацию первого токена и выборку на что-то, что является естественным языком, который модель понимает. Итак, ваши трассировки могут выглядеть так, если вы здесь включаете ввод человека. Это позволяет вам создавать агентов с автоматическим циклом. Я не буду об этом говорить. Если вы зайдете на сайт, там есть ссылка на этот пост. Я много об этом писал. Я не знаю, что лучше, но вам, вероятно, стоит попробовать все. Это контакт с людьми с помощью инструментов. Идет прямо в соответствии с триггерами из любого места и встречей с пользователями там, где они находятся. Люди не хотят иметь семь открытых вкладок с различными агентами в стиле ChatGPT. Просто позвольте людям отправлять электронные письма агентам, которых вы строите. Позвольте им общаться в Slack с агентами, которых вы строите. Discord, SMS, что угодно. Мы видим, как это набирает обороты повсюду. И у вас должны быть небольшие сфокусированные агенты. Итак, мы говорили об этой структуре и почему она не очень хорошо работает. Итак, что работает? То, что люди делают и что работает очень хорошо, — это микроагенты. Итак, у вас все еще есть в основном детерминированный DAG, и у вас есть эти очень маленькие циклы агентов с примерно 3-10 шагами. Мы делаем это в Human Layer. У нас есть бот, который управляет нашими развертываниями. Большая часть нашего конвейера развертывания — это детерминированный код CI/CD. Но когда мы доходим до точки, когда PR GitHub объединен и тесты проходят на разработке, прошу прощения, мы отправляем его в модель. Мы говорим: "Разверни эту штуку". Он говорит: "Круто, я разверну фронтенд". А затем вы можете отправить это человеку. Человек говорит: "На самом деле нет, сначала сделай бэкенд". Это преобразование естественного языка в JSON. Это следующий шаг в нашем рабочем процессе. Предлагается бэкенд, он утверждается, развертывается, затем агент знает: "Хорошо, мне нужно вернуться и развернуть фронтенд". Как только все это сделано и успешно, мы возвращаемся к детерминированному коду. Итак, теперь мы запустим сквозное тестирование против прода. Если это сделано, иначе мы передаем его обратно небольшому агенту отката, который внутри очень похож. Я не буду вдаваться в подробности, но вот как это работает в нашем канале Slack. Да, 100 инструментов, 20 шагов, легко. Управляемый контекст, четкие обязанности. Многие люди говорят: "Что, если LLM будут становиться умнее? Что, если я смогу ввести два миллиона токенов, и он сможет это сделать?" И я думаю, мы очень увидим что-то вроде этого, где вы начинаете с в основном детерминированного рабочего процесса и начинаете вставлять LLM в свой код, в свой бэкенд, в свою логику. Со временем LLM смогут выполнять более крупные и сложные задачи, пока весь этот конечный API или конвейер или что-то еще не будет полностью управляться агентом. Это здорово. Но вам все равно нужно знать, как инженерить эти вещи, чтобы получить лучшее качество. Это кто-то из Notebook LM, и это, по сути, их взгляд, и я думаю, они сделали это хорошо: найдите что-то, что находится на границе того, что модель может надежно делать, например, то, что она не всегда может сделать правильно, и если вы сможете добиться того, чтобы это было правильно надежно, потому что вы внедрили надежность в свою систему, тогда вы создадите что-то волшебное, и вы создадите что-то лучшее, чем то, что строят все остальные. Итак, это небольшие сфокусированные агенты. Здесь есть мем о stateless reducers. Я полагаю, кто-то действительно написал мне в Твиттере, что это не reducer, а transducer, потому что есть несколько шагов. Но, по сути, агенты должны быть stateless. Вы должны владеть состоянием, управлять им, как хотите. Итак, мы все еще ищем правильные абстракции. Есть пара постов в блогах, которые я привожу в статье. Фреймворки против библиотек. Есть очень старый пост с Ruby Comp о том, хотим ли мы дублирования или пытаемся разобраться в этих абстракциях? Если вы хотите создать 12-факторного агента, мы работаем над чем-то под названием create 12-factor agent, потому что я считаю, что агентам нужен не bootstrap. Вам не нужна обертка вокруг внутренней вещи. Вам нужно что-то вроде shad CN, которое как бы разворачивается, а затем я буду им владеть, и я буду владеть кодом, и меня это устраивает. Итак, в итоге, агенты — это программное обеспечение. Вы все можете создавать программное обеспечение. Кто-нибудь когда-нибудь писал оператор switch? Цикл while. Да. Хорошо. Итак, мы можем делать эти вещи. LLM — это stateless функции, что означает, что просто убедитесь, что вы помещаете правильные вещи в контекст, и вы получите лучшие результаты. Владейте своим состоянием и потоком управления и просто делайте это и просто понимайте это, потому что это даст вам гибкость. А затем найдите передовые технологии. Найдите способы делать вещи лучше, чем все остальные, тщательно отбирая то, что вы помещаете в модель, и как вы контролируете то, что выходит. И мои агенты лучше работают с людьми. Найдите способы позволить агентам сотрудничать с людьми. Есть сложные вещи в построении агентов, но вам, вероятно, стоит делать их в любом случае, по крайней мере, на данный момент, и вам стоит делать большинство из них. Я думаю, многие фреймворки пытаются убрать сложные ИИ-части проблемы, чтобы вы могли просто вставить их и использовать. И я думаю, должно быть наоборот. Я думаю, инструменты, которые мы получаем, должны убирать другие сложные части, чтобы мы могли тратить все наше время, сосредоточившись на сложных ИИ-частях, на правильном составлении промптов, на правильном потоке, на правильных токенах. Итак, причина, по которой я здесь, заключается в том, что я действительно управляю малым бизнесом. У нас есть стартап, где мы пытаемся помочь вам делать многое из того, что мы делаем в открытом доступе, это open source, и я думаю, это действительно важно, и нам нужно работать над этим вместе. Есть некоторые другие вещи, которые сложны, но не так важны и не так интересны. Вот что мы решаем в Human Layer. Работаем над чем-то под названием протокол A2. Подойдите ко мне, если хотите поговорить об этом, но это способ добиться консолидации вокруг того, как агенты могут связываться с людьми. Но в основном я просто люблю автоматизировать вещи. Я построил тонны и тонны агентов внутри для своих личных дел, для поиска квартир, для всех видов внутренних бизнес-дел, которые мы делаем в Human Layer. Итак, спасибо всем за просмотр. Давайте построим что-нибудь. Увидимся в коридоре. Я буду рад поболтать, если вы хотите обсудить агентов, построение, поток управления или что-либо из этого. Это 12-факторные агенты. [Аплодисменты]