Створення агента ReAct у LangChain: виконавці, Scratchpads та їхні обмеження
Створіть агента ReAct, який використовує інструменти, подивіться, як агент та AgentExecutor ділять роботу, і дізнайтеся, чому LangGraph краще справляється з контрольним потоком, циклами та станом.
Що таке агент
Штучний інтелект-агент — це система, яка бере від людини загальну мету, а потім самостійно планує, приймає рішення та діє. Вона виконує послідовність кроків, використовуючи зовнішні інструменти, API чи джерела знань, зберігає контекст протягом усього процесу, міркує між кількома кроками, коригується при отриманні нової інформації та працює над досягненням бажаного результату.
У спрощеному вигляді агент — це LLM разом із деякими інструментами. LLM виконує міркування та прийняття рішень, а інструменти здійснюють дії.
Характеристики агента
- Орієнтований на мету. Ви вказуєте, чого хочете, а не як цього досягти.
- Самостійно планує. Агент розділяє проблему та впорядковує завдання без допомоги.
- Використовує інструменти. Він викликає API, калькулятори, засоби пошуку та подібне. LLM знає, які інструменти існують та коли кожен з них потрібен.
Агент у коді
Наведений нижче скрипт створює невеликий агент із двома інструментами: пошук у Інтернеті через DuckDuckGo та перевірка погоди, і ставить йому двокомпонентне запитання. Для отримання даних про погоду потрібен власний API-ключ від постачальника погодних даних; тут він показаний як замінник.
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
import requests
from langchain_community.tools import DuckDuckGoSearchRun
from langchain.agents import create_react_agent, AgentExecutor
from langchain import hub # It is a place from where we can get many type of prompts, so if we want any predefined prompt, we can get it from here
# Step 1: Creating tool definitions
search_tool = DuckDuckGoSearchRun()
@tool
def get_weather_data(city: str) -> str:
"""
This function fetches the current weather data for a given city
"""
url = f'https://api.weatherstack.com/current?access_key=4d1d8ae207a8c845a52df8a67bf3623e&query={city}'
response = requests.get(url)
return response.json()
llm = ChatOpenAI()
# Step 2: Pull the ReAct prompt from LangChain Hub
prompt = hub.pull("hwchase17/react") # pulls the standard ReAct agent prompt
# The agent which we are gonna make is a ReAct agent (reasoning + action = ReAct)
# ReAct is a design pattern
# Step 3: Create the ReAct agent manually with the pulled prompt
agent = create_react_agent(
llm=llm,
tools=[search_tool, get_weather_data],
prompt=prompt
)
# Step 4: Wrap it with AgentExecutor
agent_executor = AgentExecutor(
agent=agent,
tools=[search_tool, get_weather_data],
verbose=True # whatever the agent thinks, it will be visible to us
)
# Step 5: Invoke
response = agent_executor.invoke({"input": "Find the capital of Madhya Pradesh, then find it's current weather condition"})
print(response)
'''
Entering new AgentExecutor chain...
I should first find out the capital of Madhya Pradesh and then check the current weather condition for that city.
Action: duckduckgo_search
Action Input: "capital of Madhya Pradesh" Madhya Pradesh, state of India that is situated in the heart of the country. It has no coastline and no international frontier. Its physiography is characterized by low hills, extensive plateaus, and river valleys. The capital is Bhopal, in the west-central part of the state. Bhopal, city, capital of Madhya Pradesh state, central India. Situated in the fertile plain of the Malwa Plateau, the city lies just north of the Vindhya Range, along the slopes of a sandstone ridge. It is a major rail junction and has an airport. Pop. (2001) 1,437,354; (2011) 1,798,218. Bhopal was Indore (/ ɪ n ˈ d ɔːr / ⓘ; ISO: Indaura, Hindi: [ɪn̪d̪ɔːr]) is the largest and most populous city in the Indian state of Madhya Pradesh. [15] It is the commercial hub of Madhya Pradesh. It is consistently ranked as the cleanest city in India. [16] It serves as the headquarters of both the Indore District and the Indore Division.It is also considered the state education hub and ... In 1956, Bhopal became part of the state of Madhya Pradesh. Bhopal district was carved out on October 2, 1972, and is one of the 45 districts in the state. 4. Why is Bhopal famous? Bhopal is the capital city of the Indian state of Madhya Pradesh. It is known as the City of Lakes due to the presence of various natural and artificial lakes. In 1948, Madhya Bharat was created, with Indore designated as its summer capital and Gwalior as its winter capital. This arrangement highlights Indore's significance even then. However, Madhya Bharat was a temporary entity, and the map of central India was soon to be redrawn. The Creation of Madhya PradeshNow that I know the capital of Madhya Pradesh is Bhopal, I can use the get_weather_data function to check its current weather condition.
Action: get_weather_data
Action Input: Bhopal {'request': {'type': 'City', 'query': 'Bhopal, India', 'language': 'en', 'unit': 'm'}, 'location': {'name': 'Bhopal', 'country': 'India', 'region': 'Madhya Pradesh', 'lat': '23.267', 'lon': '77.400', 'timezone_id': 'Asia/Kolkata', 'localtime': '2025-05-01 17:52', 'localtime_epoch': 1746121920, 'utc_offset': '5.50'}, 'current': {'observation_time': '12:22 PM', 'temperature': 40, 'weather_code': 116, 'weather_icons': ['https://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png'], 'weather_descriptions': ['Partly Cloudy '], 'astro': {'sunrise': '05:47 AM', 'sunset': '06:48 PM', 'moonrise': '08:38 AM', 'moonset': '11:01 PM', 'moon_phase': 'Waxing Crescent', 'moon_illumination': 15}, 'air_quality': {'co': '510.6', 'no2': '1.665', 'o3': '180', 'so2': '10.175', 'pm2_5': '29.045', 'pm10': '68.635', 'us-epa-index': '2', 'gb-defra-index': '2'}, 'wind_speed': 12, 'wind_degree': 302, 'wind_dir': 'WNW', 'pressure': 1005, 'precip': 0, 'humidity': 7, 'cloudcover': 25, 'feelslike': 40, 'uv_index': 1, 'visibility': 6, 'is_day': 'yes'}}The current weather condition in Bhopal, Madhya Pradesh is partly cloudy with a temperature of 40°C.
Final Answer: The capital of Madhya Pradesh is Bhopal, and the current weather condition in Bhopal is partly cloudy with a temperature of 40°C.
> Finished chain.
{'input': "Find the capital of Madhya Pradesh, then find it's current weather condition", 'output': 'The capital of Madhya Pradesh is Bhopal, and the current weather condition in Bhopal is partly cloudy with a temperature of 40°C.'}
'''
response['output']
# The capital of Madhya Pradesh is Bhopal, and the current weather condition in Bhopal is partly cloudy with a temperature of 40°C.
П’ять пронумерованих кроків у скрипті охоплюють визначення інструментів, отримання стандартного запиту ReAct з хабу LangChain, створення агента, його обгортання в виконавець та його запуск. Трасування, надруковане в кінці, показує, що агент спочатку вирішує шукати столицю, а потім перевіряє погоду.
ReAct
LangChain підтримує кілька підходів до проектування агентів. Той, про який йдеться тут, — це ReAct, скорочення від Reasoning plus Acting. Він дозволяє моделі чергувати внутрішнє міркування, тобто процес формування думки, та зовнішні дії, такі як виклик інструментів, у структурованому циклі, який охоплює кілька кроків.
Модель не формує свою відповідь одразу. Вона міркує крок за кроком, вирішує, що робити далі, і може використовувати такі інструменти, як API, калькулятори чи пошук в Інтернеті, для отримання допомоги.
Ця схема підходить для:
- задач, які вимагають кількох кроків;
- завдань, що потребують використання інструментів;
- ситуації, коли потрібно, щоб логіка була видимою та піддається перевірці.
Як приклад, запитайте модель про населення столиці Франції. Спочатку вона робить висновок, що мусить визначити столицю, шукає інформацію, бачить, що відповідь — Париж, потім робить висновок, що їй потрібно населення Парижа, знову шукає та нарешті дає відповідь.
ReAct складається з п’яти елементів:
- Мислення. Приватна логіка агента, під час якої він оцінює поточний стан та планує наступний крок. Вона пояснює, чому обрано певний інструмент або що ще залишається невідомим.
- Дія. Рішення використати один із інструментів з доступного набору, вказане через функцію чи API для виклику.
- Вхідні дані для дії. Аргументи, які передаються цьому інструменту. Якщо дія —
search, вхідними даними є сам текст запиту, наприклад, інформація про погоду в Делі.
Шаблон запиту, який керує цим циклом, виглядає так:
Answer the following questions as best you can. You have access to the following tools:
{tools}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action …
(this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought:{agent_scratchpad} —
У цій шаблоні спостереження — це просто те, що повертається після виконання інструментом своїх функцій.
Робочий блок агента
Робочий блок функціонує як короткострокова пам’ять або робочий зошит агента. Він фіксує історію поточного завдання: попередні думки, виконані дії, такі як виклики інструментів, та спостереження, які були отримані.
Читаючи цей зошит, агент пам’ятає, що він вже з’ясував столицю Франції та тепер має знайти кількість населення Парижа. Це тимчасове зберігання, яке оновлюється щоразу, коли виконавець надсилає нову інформацію. Як тільки остаточна відповідь надсилається користувачеві, робочий блок зазвичай очищується або архівується, оскільки його завдання щодо цього завдання завершено.
Назва має сенс, якщо згадати, що LLM є безстановим. Він не може природним чином пам’ятати те, що сталося кілька секунд тому у циклі коду. Тому LangChain бере всю історію поточного циклу та знову вставляє її у запит щоразу, коли запитує агента, що робити далі.
Agent versus AgentExecutor
Ці дві частини виконують окремі завдання.
Агент — це мислитель, щось на кшталт менеджера проєктів. Він читає запит, розділяє його на менші кроки та вирішує, які інструменти потрібні. Його вхідні дані містять як запит користувача, так і все, що було зроблено досі.
AgentExecutor — це виконавець, більше схожий на асистента. Він слухає інструкції агента, фактично запускає код для кожного інструменту та повертає результати.
Інший спосіб поглянути на це: агент — це архітектор, який складає креслення, а виконавець — це бригада будівельників, яка зводить будівлю. Без агента немає плану, а без виконавця план ніколи не виходить за межі паперу.
Виконавець координує весь цикл:
- Він надсилає вхідні дані та попередні повідомлення агенту, щоб той знав про запитання та про те, що вже сталося.
- Він отримує наступну дію від агента.
- Він запускає відповідний інструмент із наданими даними.
- Він додає результати роботи інструменту до історії.
- Він надсилає оновлену історію разом із запитанням користувача назад агенту, і цей процес повторюється, поки агент не вказує «Остаточна відповідь».
Візьмімо запит на отримання температури в Делі та помножимо його на 10. Агент вирішує, що потрібен інструмент для отримання погодних даних, виконавець його викликає, надходять дані спостереження, агент вирішує, що потрібне множення, виконавець його виконує, і нарешті агент надає відповідь. Виконавець виконує все, що вирішує агент.
Обмеження цього підходу
Готовий виконавець підходить для простих випадків, але має серйозні слабкості, коли агенти стають більш складними. Нижче наведено порівняння з LangGraph — бібліотекою на основі графів від LangChain. Також зверніть увагу, що нові версії LangChain рекомендують використовувати LangGraph для агентів, тому перевіряйте актуальну документацію перед використанням старих класів виконавців.
1. Чорна скринька
Стандартний AgentExecutor вже попередньо налаштований. Достатньо надати йому інструменти та інструкції, і невидимий while-цикл продовжуватиме працювати, доки справа не буде завершена. Втрутитися в його роботу складно. Якщо ви хочете, щоб агент завжди запитував людину перед тим, як витрачати гроші, або дотримувався певної послідовності, наприклад спочатку крок А, потім крок B, екзекутор чинить опір, оскільки він розроблений для повної автономності.
Уявіть собі агента з інструментами search_flights та book_flight. Усередині екзекутора LangChain ШІ вирішує, що робити далі, у прихованому циклі. Якщо його попросити забронювати рейс, він може негайно здійснити пошук та бронювання без запиту, можливо, за тариф у десять тисяч доларів, тоді як користувач хотів спочатку схвалити будь-яку покупку. Проміжні кроки, такі як обов’язкове схвалення, неможливо суворо застосувати, оскільки потік керування є неявним та контролюється моделлю.
У LangGraph робочий процес визначається як послідовні кроки або вузли, такі як пошук рейсів, запит на схвалення та бронювання. Вони з’єднані так, що система повинна спочатку отримати схвалення, перш ніж здійснити бронювання. Це забезпечує повний контроль та полегшує застосування правил, додавання людських контрольних точок, повторних спроб чи умовних гілок.
2. Цикли та ланцюги
Справжні робочі процеси рідко є лінійними. Вони включають повернення назад, виправлення помилок та повторне оброблення наборів документів.
- Ланцюги LangChain переважно розроблені як орієнтовані ациклічні графи, тож дані передаються лише в одному напрямку.
- LangGraph створений для обробки циклів. Він моделює потік як карту, у якій вузли є функціями, а ребра — шляхами між ними.
Для завдання з відповідями на запитання щодо документів пайплайн LangChain може отримати документи, написати відповідь та повернути її. Якщо відповідь є неправильною або неповною, він не може автоматично повернутися для повторної заготівлі даних чи уточнення запиту без додаткової ручної логіки. Як тільки процес рухається далі, йому важко повернутися назад для вдосконалення.
LangGraph дозволяє явно створювати цикли: отримати дані, дати відповідь, перевірити якість, а якщо результат поганий — уточнити запит та знову отримати дані, повторюючи цей процес до отримання хорошого результату. Система може циклічно переходити між вузлами до досягнення певної умови, що підходить для завдань, які потребують ітерацій, корекцій та зворотного зв’язку.
3. Стан та стабільність зберігання
Це має найбільше значення для масштабованості.
Пам’ять LangChain переважно стосується контексту розмови, наприклад, зберігання попередніх повідомлень у чаті, щоб модель могла давати кращі відповіді. Вона не тісно пов’язана з процесом виконання завдань та не відстежує прогрес у виконанні завдання. Якщо її не зберегти спеціально, вона зазвичай втрачається під час перезапуску системи, тому довготривалі завдання не є надійними.
LangGraph розглядає пам’ять як повний стан процесу виконання завдань, а не лише історію чату. На кожному кроці він зберігає те, що було зроблено, які результати отримано та що буде далі. Якщо процес зупиняється на півдорозі, його можна продовжити саме з того місця, де він зупинився. Він також дозволяє призупиняти, перевіряти та редагувати стан за участю людини, або навіть повертатися до попереднього кроку, що робить складні багатокрокові завдання набагато надійнішими.
Уявіть собі тривале завдання, наприклад обробку десяти документів по одному, яке зупиняється на 7-му кроці. Без вбудованої функції зберігання всі дані втрачаються, і доводиться починати з нуля, без жодних записів про прогрес за замовчуванням. Завдяки збереженню стану після кожного кроку можна продовжити роботу з 7-го кроку. Також можна зупинитися, дати комусь можливість переглянути чи внести зміни до стану, а потім продовжити, або повернутися до попереднього кроку — це своєрідна подорож у часі. Довгі робочі процеси стають надійнішими, дозволяють продовжувати роботу та їх легше дебагувати чи аудитувати.
Головний висновок полягає у тому, що базовий виконувач ускладнює створення масштабованих агентів промислового рівня, саме тому існують інструменти на основі графів для виконання таких завдань.
Пов’язана література
- Знімки пам’яті агента, навички, занепад якості та обмеження пам’яті за гілками — Чотири доповнення до вбудованого шару пам’яті у вигляді векторної БД для кодуючих агентів: портативні знімки з можливістю об’єднання, активація навичок, занепад якості з перевіркою конфліктів та пам’ять, обмежена за гілками.
- Ваш перший агент LangGraph: асистент з футболу з інструментами та маршрутизацією — Покроковий посібник з LangGraph: спільний стан, інструменти, вузол планування, умовні краї та резюме у форматі Markdown, створене на основі фіктивного асистента зі статистикою футболу.