ReAct промптинг: это схема, в которой языковая модель чередует рассуждение и действие. Она пишет мысль о том, что делать, выполняет действие, например поиск или вызов инструмента, читает результат и только потом решает, каким будет следующий шаг. Название: сокращение от Reason + Act («рассуждай и действуй»), оно пришло из работы Yao et al. 2022, «ReAct: Synergizing Reasoning and Acting in Language Models». К React, JavaScript-библиотеке для создания интерфейсов, она отношения не имеет.
Большинство ИИ-агентов, которые ходят по сайтам, запускают код или редактируют файлы, работают на какой-то версии этого цикла. Если один раз пройти его вручную, поведение агентов становится гораздо проще предсказывать и отлаживать.
Цикл Thought, Action, Observation
Промпт ReAct просит модель писать строки трёх видов.
- Thought (мысль): рассуждение о текущей ситуации и о том, какой информации не хватает.
- Action (действие): один вызов инструмента в фиксированном формате, например
search[query],read_file[path]илиfinish[answer]. - Observation (наблюдение): результат этого действия. Эту строку модель не пишет. Её добавляет ваша программа (или вы), выполнив действие и вставив в запись диалога настоящий вывод.
Затем вся запись снова уходит модели, и та пишет следующую мысль. Цикл заканчивается, когда модель выбирает завершающее действие. Модель сама никогда не запускает инструмент; она только просит, а решение, выполнять ли запрос, принимает код вокруг неё.
Почему рассуждение плюс действие лучше каждого по отдельности
В статье ReAct сравнили с промптами, которые только рассуждают (chain of thought), и промптами, которые только действуют (вызовы инструментов без записанных рассуждений). На ответах на вопросы и проверке фактов с инструментом поиска по Википедии одно лишь рассуждение часто строило уверенный аргумент на факте, который модель выдумала, а ReAct мог этот факт найти; лучшие результаты в ответах на вопросы дало сочетание ReAct с chain of thought, когда при неуверенном ответе одного метода переключались на другой. Одно лишь действие плохо справлялось с разбиением цели на части и со сведением найденного в ответ; записанные мысли держали план на виду. На двух интерактивных задачах, текстовой игре по дому и симуляции интернет-магазина, ReAct с одним-двумя примерами в промпте показал себя лучше обученных базовых систем, с которыми сравнивали авторы.
Общий вывод: chain of thought помогает модели планировать, инструменты дают ей факты, и ни того ни другого по отдельности не хватает для задачи, которой нужно и то и другое.
ReAct-агент, реплика за репликой
Блок ниже: небольшой агент для кода с двумя инструментами. Каждая вкладка: тот же диалог на шаг позже; строки Observation: это то, что программа вставила обратно после выполнения предыдущего действия. Метки Thought, Action и Observation оставлены на английском, потому что их ищет код ниже. Читайте ответы по порядку.
Thought: Я не знаю, какой тест падает и как. Запуск тестов покажет точное утверждение до того, как я начну читать код. Action: run_tests[tests/test_cart.py]
Обратите внимание на две вещи. Первое действие: запуск тестов, а не догадка; модель собрала доказательства, прежде чем читать код. И каждая мысль опирается на последнее наблюдение, а этого chain of thought сделать не может.
Попробуйте ReAct в чат-приложении
Чтобы увидеть цикл, код не нужен. В ChatGPT, Claude или Gemini инструментом можете быть вы: модель просит действие, вы его выполняете и вставляете результат.
Мысль: громкий вентилятор в простое обычно означает, что что-то в фоне нагружает процессор или вентилятору трудно охлаждать (пыль, закрытые вентиляционные отверстия). Если сначала проверить загрузку процессора, эти два случая разделятся.
Действие: откройте Диспетчер задач (Ctrl+Shift+Esc в Windows) или Мониторинг системы (Программы > Утилиты на Mac). Отсортируйте процессы по загрузке ЦП, подождите 30 секунд и назовите мне три верхних процесса и их процент загрузки ЦП.
Те же инструкции, но с настоящей функцией за каждым действием, и есть агент.
Минимальный цикл ReAct на Python
В коде программа отправляет запись диалога, находит в ответе строку Action, запускает соответствующую функцию, добавляет Observation и повторяет. Этот набросок использует Python SDK от OpenAI и системный промпт агента для кода из примера выше.
import re
import subprocess
from pathlib import Path
from openai import OpenAI
client = OpenAI()
MODEL = "your-model-id" # e.g. from your provider's model list
PROJECT = Path.cwd().resolve()
READABLE = {".py", ".md", ".txt", ".toml", ".cfg"}
def inside_project(arg):
# The model chooses arg: resolve it and refuse anything outside the project.
path = (PROJECT / arg).resolve()
if not path.is_relative_to(PROJECT):
raise ValueError(f"{arg} is outside the project")
return path
def run_tests(arg):
path = inside_project(arg)
if not (path.is_file() and path.name.startswith("test_") and path.suffix == ".py"):
raise ValueError(f"{arg} is not a test file")
result = subprocess.run(["pytest", str(path), "-q"], capture_output=True, text=True)
return result.stdout[-2000:]
def read_file(arg):
path = inside_project(arg)
if not path.is_file() or path.suffix not in READABLE:
raise ValueError(f"{arg} is not a file this agent may read")
return path.read_text()[:20000]
TOOLS = {"run_tests": run_tests, "read_file": read_file}
def react(task, system_prompt, max_steps=8):
transcript = f"Task: {task}\n"
for _ in range(max_steps):
response = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": transcript},
],
temperature=0,
)
text = response.choices[0].message.content
match = re.search(r"Action: (\w+)\[(.*)\]", text)
if not match:
return text
transcript += text[: match.end()] + "\n"
tool, arg = match.groups()
if tool == "finish":
return arg
try:
observation = TOOLS[tool](arg) if tool in TOOLS else f"Unknown tool: {tool}"
except Exception as error: # a missing file becomes an observation, not a crash
observation = f"Error: {error}"
transcript += f"Observation:\n{observation}\n"
return "Stopped after max_steps without an answer."
Здесь важны четыре детали. Запись обрезается сразу после Action, потому что модели иногда продолжают писать и выдумывают собственное Observation. Сбой инструмента (скажем, неверное имя файла) становится наблюдением, на которое модель может отреагировать, а не роняет цикл. Ограничение на число шагов останавливает модель, которая зациклилась. А вывод тестов обрезается, потому что огромный лог тестов заполнил бы контекстное окно; решать, что попадает в это окно, и есть контекст-инжиниринг.
Оба инструмента к тому же проверяют аргумент, прежде чем что-либо делать. Аргумент выбирает модель, поэтому ограничения должны жить в самом инструменте: inside_project отклоняет любой путь, ведущий за пределы папки проекта (в том числе через ../), run_tests принимает только файлы test_*.py, а read_file открывает лишь несколько типов файлов с кодом и текстом и возвращает не больше 20 000 символов, так что файл .env или SSH-ключ никогда не попадут в следующий запрос. Запуск pytest всё равно выполняет код вашего проекта, поэтому запускайте такого агента в контейнере или в одноразовой копии репозитория, но не на машине с секретами.
Современные API от OpenAI, Anthropic и Google также предлагают встроенный вызов инструментов: вы описываете каждый инструмент именем и JSON-схемой, и модель возвращает структурированный вызов инструмента вместо строки Action:. Цикл тот же; исчезает только разбор текста.
Безопасность в цикле ReAct
Агент читает текст, который написал не он: веб-страницы, файлы, вывод инструментов. В любом из них могут быть инструкции, адресованные модели, это промпт-инъекция. Давайте каждому инструменту минимально необходимый доступ (где можно, только чтение), просите человека подтверждать всё, что удаляет, отправляет или платит, и считайте запрошенные моделью действия непроверенным вводом, который нужно проверить, а не командами, которые можно выполнять вслепую.
Часто задаваемые вопросы
Что такое ReAct промптинг?
ReAct (сокращение от Reason + Act, «рассуждай и действуй»): это схема промптинга, при которой языковая модель пишет короткое рассуждение, затем действие, например поиск или вызов инструмента, а потом читает результат и только после этого рассуждает снова. Она пришла из работы Yao et al. 2022, «ReAct: Synergizing Reasoning and Acting in Language Models». К JavaScript-библиотеке React она отношения не имеет.
Что такое Thought, Action и Observation в ReAct?
Thought (мысль): рассуждение модели о том, что делать дальше. Action (действие): вызов инструмента в фиксированном формате, например search[python 3.13 release notes]. Observation (наблюдение): вывод инструмента, который ваша программа получает, выполнив действие, и добавляет в промпт. Цикл повторяется, пока модель не выберет завершающее действие со своим ответом.
Чем ReAct отличается от chain of thought?
Chain of thought рассуждает на основе того, что модель уже знает, поэтому неверный факт в начале цепочки так и остаётся неверным. ReAct перемежает рассуждение с действиями, которые добывают реальную информацию, так что модель может проверить факт, увидеть упавший тест или прочитать файл, прежде чем продолжить. В статье о ReAct обнаружили, что опора рассуждения на результаты поиска сократила число выдуманных фактов, которые давал один chain of thought.
Используют ли ИИ-агенты ReAct сегодня?
Цикл: да. Большинство агентов сегодня рассуждают, вызывают инструмент, читают результат и решают снова, и это и есть цикл ReAct. Изменился формат: вместо разбора строк Action: из текста в современных API есть встроенный вызов инструментов, при котором модель возвращает структурированный запрос к инструменту, а ваш код отправляет обратно результат.
Можно ли использовать ReAct в ChatGPT без кода?
Да, если играть роль инструмента самому. Попросите модель отвечать одной мыслью и одним действием и останавливаться. Вы выполняете действие (поиск, открыть файл, запустить команду), вставляете результат как наблюдение и повторяете. Это медленно, но точно показывает, как агент решает, что делать дальше.