Lil’Log: автономные агенты на основе LLM
Конспект знаменитого поста Лилиан Венг (июнь 2023): агент = LLM + планирование + память + инструменты; разбор CoT и Tree of Thoughts, ReAct, Reflexion, Chain of Hindsight, видов памяти и ANN-поиска, MRKL, Toolformer, HuggingGPT, API-Bank, ChemCrow, Generative Agents, AutoGPT и ограничений агентов.
Коротко
Заголовок раздела «Коротко»- Венг предлагает схему, которая стала стандартной: агент (агентагентEN agentВ китайском встречается и «дайли» («посредник»), но в AI-контексте стандарт — «чжинэнти» (буквально «интеллектуальное тело»).) — это LLM в роли «мозга» плюс три компонента: планирование, память и инструменты.
- Планирование = разбиение задачи на подцели (CoT, Tree of Thoughts, внешний планировщик LLM+P) и самоанализ ошибок (ReAct, Reflexion, Chain of Hindsight, Algorithm Distillation).
- Память по аналогии с человеческой: сенсорная ≈ эмбеддинги входа, кратковременная ≈ контекст (in-context learning), долговременная ≈ внешнее векторное хранилище с быстрым приближённым поиском (LSH, ANNOY, HNSW, FAISS, ScaNN).
- Инструменты: от MRKL и Toolformer до вызова функций в API и HuggingGPT; качество использования инструментов меряют бенчмарки вроде API-Bank.
- Примеры: ChemCrow и агент для химических экспериментов, «Генеративные агенты» — 25 персонажей в песочнице в духе The Sims, AutoGPT и GPT-Engineer.
- Три главных ограничения: конечный контекст, трудности долгого планирования и ненадёжность естественного языка как интерфейса между LLM и программой.
Как читать вместе с курсом
Заголовок раздела «Как читать вместе с курсом»Это лучшая «карта местности» для модуля 8.3. Прочитайте пост перед уроком 8.3.1 «Агентный цикл и ReAct», чтобы увидеть целое, и вернитесь к разделам по ходу модуля: «Инструменты» — к 8.3.2, «Планирование» и «Память» — к 8.3.3, раздел о поиске ближайших соседей — к 8.2.1 «RAG».
Учтите возраст поста: середина 2023 года, эпоха GPT-4 и первых «автономных» демо. Тогда не было протокола протокол контекста моделипротокол контекста модели (MCP)EN Model Context Protocol (MCP)Открытый протокол (Anthropic, ноябрь 2024) на JSON-RPC 2.0 для подключения инструментов, ресурсов и промптов к LLM-приложениям., рассуждающих моделей и агентов, обученных RL на многошаговых задачах (урок 8.3.4), — но архитектурная схема и список проблем почти не устарели. Разделы AutoGPT и GPT-Engineer (длинные промпты целиком) новичку можно пролистать.
flowchart LR U["Задача пользователя"] --> LLM["LLM — «мозг» агента"] LLM <--> P["Планирование: подцели, самоанализ"] LLM <--> M["Память: контекст + векторное хранилище"] LLM <--> T["Инструменты: поиск, код, API"] T --> ENV["Внешний мир"] ENV -->|"наблюдения"| LLM
1. Планирование
Заголовок раздела «1. Планирование»Разбиение задачи
Заголовок раздела «Разбиение задачи»- Цепочка рассуждений (цепочка рассужденийцепочка рассужденийEN chain of thought (CoT), Wei и др., 2022): попросить модель «думать по шагам» — так она тратит больше вычислений на трудную задачу и сама дробит её на простые шаги.
- Tree of Thoughts (Yao и др., 2023): на каждом шаге порождать несколько вариантов мысли, получая дерево, и искать по нему в ширину или в глубину; каждое состояние оценивает классификатор (промптом) или голосование.
- Разбиение можно получить простым промптом («шаги для X: 1.»), инструкцией под задачу («напиши план романа») или от человека.
- LLM+P (Liu и др., 2023) отдаёт долгое планирование классическому планировщику: LLM переводит задачу на язык PDDL, планировщик строит план, LLM переводит план обратно на естественный язык. Работает, только если для области есть описание на PDDL и подходящий планировщик.
Самоанализ
Заголовок раздела «Самоанализ»- ReAct (Yao и др., 2023): пространство действий = действия в среде (например, поиск по Википедии) плюс свободный текст рассуждений. Траектория чередует «Мысль → Действие → Наблюдение». На задачах с поиском знаний и на задачах принятия решений ReAct лучше варианта без шага «Мысль». Это ровно цикл урока 8.3.1.
- Reflexion (Shinn и Labash, 2023): после каждой попытки эвристика решает, не пора ли остановить траекторию — если она слишком длинная без успеха («неэффективное планирование») или агент повторяет одно и то же действие с одним и тем же результатом (так авторы определяют «галлюцинацию»). Модель пишет «рефлексию» — вывод из неудачи по образцу двух примеров «неудачная траектория → полезный вывод», — и до трёх таких выводов кладутся в рабочую память следующей попытки. В среде AlfWorld галлюцинация оказалась более частой причиной неудач, чем неэффективное планирование.
- Chain of Hindsight (Liu и др., 2023): дообучение на последовательностях «несколько прошлых ответов с отзывами, упорядоченные от худшего к лучшему», чтобы модель усвоила тенденцию к улучшению. Чтобы не переобучиться, добавляют потерю на данных претрейна и случайно маскируют 0–5 % прошлых токенов.
- Algorithm Distillation (Laskin и др., 2023) переносит ту же идею в RL: модель учится на склеенной истории нескольких эпизодов, где агент постепенно становился лучше, и в итоге сама «учится в контексте». Нужно 2–4 эпизода в контексте; результат приближается к онлайн-методу RL² при обучении только на записанных данных.
2. Память
Заголовок раздела «2. Память»Венг сопоставляет виды человеческой памяти с устройством агента:
| Человек | Агент |
|---|---|
| сенсорная память (секунды) | эмбеддинги сырого входа — текста, картинок |
| кратковременная / рабочая (около 7 элементов, 20–30 с) | контекст модели, in-context learning (обучение в контекстеобучение в контекстеEN in-context learning (ICL)Модель решает новую задачу по примерам в промпте, без изменения весов. Ярко показано в статье о GPT-3 (2020).) |
| долговременная: явная (факты, события) и неявная (навыки) | внешнее векторное хранилище (векторная база данныхвекторная база данныхEN vector database) с быстрым поиском |
Для долговременной памяти нужен поиск максимального скалярного произведения (MIPS): найти в базе векторы, наиболее похожие на запрос. Точный перебор дорог, поэтому берут приближённый поиск ближайших соседей (приближённый поиск ближайших соседейприближённый поиск ближайших соседей (ANN)EN approximate nearest neighbor search (ANN)Поиск похожих векторов без полного перебора (HNSW, IVF, PQ) ценой небольшой потери полноты.):
- LSH — хеширование, при котором похожие векторы с высокой вероятностью попадают в одну корзину;
- ANNOY — лес случайных деревьев-разбиений пространства гиперплоскостями;
- HNSW (HNSWHNSW (иерархический граф «малого мира»)EN Hierarchical Navigable Small World (HNSW)Один из самых распространённых ANN-индексов в векторных БД — многослойный граф, по которому поиск спускается от редких верхних слоёв к плотным нижним; предложен Ю. Мальковым и Д. Яшуниным (arXiv:1603.09320).) — иерархия графов «тесного мира»: верхние слои дают «короткие пути», нижний содержит все точки;
- FAISS — кластеризация и векторное квантование: сначала грубо выбираем кластеры, потом ищем внутри;
- ScaNN — анизотропное квантование, которое сохраняет именно скалярное произведение с запросом.
Сравнения — на ann-benchmarks.com. Это та же техника, что в векторных базах из урока 8.2.1.
3. Инструменты
Заголовок раздела «3. Инструменты»- MRKL (Karpas и др., 2022): LLM — маршрутизатор, который направляет запрос подходящему «эксперту»: нейросети или символьному модулю (калькулятор, конвертер валют, погода). Опыт с калькулятором показал: словесные задачи труднее явных, потому что модель ошибается, извлекая аргументы. Вывод Венг: знать, когда и как вызывать инструмент, — главное, и это определяется силой LLM.
- TALM и Toolformer (Schick и др., 2023): дообучают модель вставлять вызовы API туда, где ответ API улучшает предсказание.
- Вызов функций в API и плагины ChatGPT (вызов инструментоввызов инструментовEN tool calling / function calling) — практическое воплощение той же идеи.
- HuggingGPT (Shen и др., 2023): ChatGPT как планировщик, который выбирает модели с Hugging Face. Четыре этапа: разбор запроса на задачи с зависимостями, выбор модели под задачу (как вопрос с вариантами ответа), выполнение, итоговый ответ. Проблемы: медленно (много вызовов), нужен длинный контекст, нестабильны и LLM, и внешние сервисы.
- API-Bank (Li и др., 2023): бенчмарк из 53 инструментов, 264 размеченных диалогов и 568 вызовов API. Три уровня: правильно вызвать известный API; найти нужный API по документации; спланировать цепочку вызовов для расплывчатой задачи (например, организовать поездку).
4. Примеры
Заголовок раздела «4. Примеры»- ChemCrow (Bran и др., 2023): LLM с 13 химическими инструментами в формате ReAct. Любопытная деталь: оценка силами LLM сочла GPT-4 и ChemCrow почти равными, а эксперты-химики — что ChemCrow заметно лучше. Модель-судья без экспертизы не видит ошибок — к этому вернётся урок о LLM-как-судье (7.3.2).
- Агент для научных экспериментов (Boiko и др., 2023): ищет в интернете, читает документацию, пишет код, управляет роботизированной лабораторией. Авторы проверили риски: из 11 запросов на синтез известных боевых отравляющих веществ агент принял 4 (36 %), 7 отклонил — 5 из них после веб-поиска.
- Генеративные агенты (Park и др., 2023): 25 персонажей, каждым управляет LLM. Архитектура: поток памяти (журнал наблюдений на естественном языке); поиск по свежести, важности (её оценивает сама LM) и релевантности; рефлексия — периодические обобщения памяти в выводы более высокого уровня; планирование и реакция. Возникло эмерджентное социальное поведение: слухи распространяются, персонажи помнят отношения, вместе устраивают вечеринку.
- AutoGPT и GPT-Engineer — демо «автономного» агента и генератора проектов. Венг показывает их системные промпты целиком и замечает, что большая часть кода AutoGPT занята разбором формата ответа модели.
5. Ограничения
Заголовок раздела «5. Ограничения»- Конечный контекст. История, инструкции и ответы API не помещаются; векторный поиск помогает, но уступает полному вниманию по выразительности.
- Долгое планирование. Агентам трудно планировать на большой истории, исследовать пространство решений и перестраивать план после неожиданной ошибки.
- Ненадёжный интерфейс на естественном языке. Модель ошибается в формате или «бунтует» — отказывается выполнять инструкцию; поэтому код демо в основном разбирает вывод модели.
Что изменилось к 2026 году (наше дополнение): формат ошибается реже благодаря структурированному выводу и ограниченному декодированию (структурированный выводструктурированный выводEN structured outputОтвет модели в машиночитаемом формате (обычно JSON по схеме), который код может разобрать и проверить.); инструменты описываются единым протоколом MCP; а устойчивость к ошибкам на длинных задачах повышают RL-обучением агентов (урок 8.3.4). Проблема длинного контекста решается не только векторной памятью, но и инженерией контекста (контекст-инжинирингконтекст-инжиниринг (context engineering)EN context engineeringРешение, какие токены и в каком порядке попадают в окно на каждом вызове — инструкции, примеры, документы, история, результаты инструментов.).
Что сделать руками
Заголовок раздела «Что сделать руками»Цикл ReAct помещается в 30 строк. Чтобы код работал без ключа API, вместо LLM здесь заранее записанные ответы; в уроке
8.3.1 вы замените fake_llm на вызов настоящей модели.
import re
# Инструменты агента: обычные функции Pythondef calculator(expr: str) -> str: return str(eval(expr, {"__builtins__": {}})) # только для учебного примера! eval небезопасен
FACTS = {"население Шанхая": "около 24,9 млн человек (2020)"}def search(query: str) -> str: return FACTS.get(query, "ничего не найдено")
TOOLS = {"calculator": calculator, "search": search}
# «Модель»: заранее записанные ответы вместо настоящей LLM, чтобы код работал без APISCRIPT = iter([ "Thought: нужно узнать население Шанхая\nAction: search[население Шанхая]", "Thought: 24,9 млн; посчитаю, сколько это в тысячах\nAction: calculator[24.9 * 1000]", "Thought: ответ готов\nFinal Answer: около 24 900 тысяч человек",])def fake_llm(prompt: str) -> str: return next(SCRIPT)
def react(question: str, max_steps: int = 5) -> str: prompt = f"Question: {question}\n" for step in range(max_steps): reply = fake_llm(prompt) # 1. модель думает и выбирает действие prompt += reply + "\n" if "Final Answer:" in reply: return reply.split("Final Answer:")[1].strip() name, arg = re.search(r"Action: (\w+)\[(.*)\]", reply).groups() observation = TOOLS[name](arg) # 2. программа выполняет инструмент prompt += f"Observation: {observation}\n" # 3. результат возвращается в контекст print(f"шаг {step}: {name}({arg!r}) -> {observation}") return "не успел за max_steps шагов"
print(react("Сколько тысяч человек живёт в Шанхае?"))Ожидаемый вывод:
шаг 0: search('население Шанхая') -> около 24,9 млн человек (2020)шаг 1: calculator('24.9 * 1000') -> 24900.0около 24 900 тысяч человекУпражнения по мотивам поста:
- Reflexion своими руками. Добавьте в цикл проверку «одно и то же действие с тем же наблюдением два раза подряд» (так Reflexion определяет галлюцинацию) и в этом случае дописывайте в промпт строку-вывод и начинайте попытку заново.
- Память генеративных агентов. Сохраните 20 «наблюдений» с эмбеддингами и оценкой важности 1–10 и реализуйте поиск по сумме трёх слагаемых: свежесть (экспоненциальное затухание), важность и косинусное сходство с запросом.
- Уровни API-Bank. Для своего агента из урока 8.3.2 придумайте по два теста на каждый уровень: «вызвать», «найти», «спланировать».
Словарик
Заголовок раздела «Словарик»| EN | RU |
|---|---|
| autonomous agent | автономный агент |
| planning, subgoal decomposition | планирование, разбиение на подцели |
| self-reflection | самоанализ (рефлексия) |
| Tree of Thoughts | «дерево мыслей» |
| ReAct: Thought / Action / Observation | ReAct: мысль / действие / наблюдение |
| short-term / long-term memory | кратковременная / долговременная память |
| maximum inner product search (MIPS) | поиск максимального скалярного произведения |
| approximate nearest neighbors (ANN) | приближённый поиск ближайших соседей |
| tool use, function calling | использование инструментов, вызов функций |
| router, expert module | маршрутизатор, модуль-эксперт |
| memory stream, retrieval by recency / importance / relevance | поток памяти; поиск по свежести / важности / релевантности |
| proof-of-concept | демонстрационный прототип |