LangChain Мультиагентные системы
Когда задача слишком сложна для обработки одним агентом, можно создать нескольких агентов с разными обязанностями и позволить им взаимодействовать как команда.
Зачем нужен мультиагентный подход
Проблемы с одним агентом:
- Слишком длинный system_prompt может привести к рассеиванию внимания модели
- Слишком много инструментов увеличивают вероятность того, что модель выберет неверный инструмент
- Разные типы задач требуют разных компетенций и стилей поведения
Мультиагентный подход: каждый агент сосредоточен на одной предметной области, а сложные задачи выполняются благодаря совместной работе.
Метод 1: субагент как инструмент
Скомпилируйте агента в CompiledStateGraph, затем зарегистрируйте его как инструмент у родительского агента:
Пример
load_dotenv()
from langchain.tools import tool
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
# Субагент 1: Эксперт по погоде
@tool
def get_weather(city: str) -> str:
"""Запросить погоду"""
data = {"Ханчжоу": "Солнечно, 25°C", "Пекин": "Облачно, 18°C"}
return data.get(city, f"{city}: данные временно недоступны")
weather_agent = create_agent(
model=model,
tools=[get_weather],
name="weather_expert", # Имя используется для идентификации и логирования
system_prompt="Вы эксперт по погоде, специализирующийся на ответах на вопросы о погоде. Отвечайте кратко.",
)
# Субагент 2: Эксперт по вычислениям
@tool
def calculate(expression: str) -> str:
"""Вычислить математические выражения"""
result = eval(expression, {"__builtins__": {}}, {})
return f"{expression} = {result}"
math_agent = create_agent(
model=model,
tools=[calculate],
name="math_expert",
system_prompt="Вы эксперт по математике, специализируетесь на математических вычислениях. Отвечайте кратко.",
)
# Родительский агент: Координатор
# Зарегистрируйте субагентов как инструменты
@tool
def ask_weather_expert(question: str) -> str:
"""Обратитесь к эксперту по погоде по вопросам, связанным с погодой.
Аргументы:
question: Вопросы о погоде
"""
result = weather_agent.invoke(
{"messages": [HumanMessage(content=question)]}
)
return result["messages"][-1].content
@tool
def ask_math_expert(question: str) -> str:
"""Проконсультируйтесь с экспертом по математике по вопросам математических вычислений.
Аргументы:
вопрос: Задачи на математические вычисления
"""
result = math_agent.invoke(
{"messages": [HumanMessage(content=question)]}
)
return result["messages"][-1].content
coordinator = create_agent(
model=model,
tools=[ask_weather_expert, ask_math_expert],
system_prompt="""Вы — ассистент-координатор. Выберите подходящего эксперта в зависимости от вопроса пользователя:
- Вопросы о погоде → используйте ask_weather_expert
- Задачи на математические вычисления → используйте ask_math_expert
- Если одновременно задействовано несколько предметных областей, консультируйтесь с каждым экспертом по очереди""",
)
# Тестовый составной вопрос
result = coordinator.invoke({
"messages": [HumanMessage(
content="Какая сегодня погода в Ханчжоу? Если температура 25 градусов, сколько это по Фаренгейту?"
"(Формула: Fahrenheit = Celsius × 9/5 + 32)"
)]
})
print(result["messages"][-1].content)
Результат выполнения:
根据天气专家的查询,杭州今天晴天,气温25°C. 换算成华氏度:25 × 9/5 + 32 = 77°F. 所以杭州今天25°C,相当于77°F,天气晴好。
Метод 2: Различение агентов с помощью параметра name
При встраивании субагента в качестве инструмента установка параметра name помогает отслеживать источник сообщений:
Пример
# 1. Имя используется в скомпилированном графе
# 2. Имя используется при встраивании в качестве узла подграфа в родительский граф
# 3. Все сообщения AI помечаются этим именем
agent = create_agent(
model=model,
tools=[...],
name="customer_service", # Назовите агента
)
Метод 3: Маршрутизация агентов с помощью промежуточного ПО
Более сложные мультиагентные сценарии могут реализовать динамическую маршрутизацию через промежуточное ПО:
Пример
# Определите наборы инструментов, используемые разными экспертами
general_tools = [tool_a, tool_b]
admin_tools = [tool_c, tool_d]
@before_model
def route_by_user_role(state, runtime):
"""Динамически переключать доступные инструменты в зависимости от роли пользователя"""
context = runtime.context
if context is None:
return None
user_role = context.get("user_role", "user")
# Разные роли видят разные инструменты
if user_role == "admin":
available_tools = general_tools + admin_tools
else:
available_tools = general_tools
# Примечание: before_model не может напрямую изменять инструменты,
# Это нужно реализовать вместе с wrap_model_call или request.override
return None
Паттерны архитектуры мультиагентных систем
| Паттерн | Структура | Применимый сценарий |
|---|---|---|
| Паттерн координатора | Один родительский Agent → несколько инструментов субагентов | Задачи, которые явно классифицируются по типу |
| Паттерн эстафеты | Выход Agent A → вход Agent B | Обработка в стиле конвейера (генерация → проверка → шлифовка) |
| Паттерн дебатов | Несколько Agent выдают результаты параллельно → обобщить и принять решения | Задачи, требующие многостороннего анализа |
Другие расширенияМультиагентная система увеличивает сложность и расход Token. Не используйте multi-agent только ради «multi-agent» — сначала попробуйте решить задачу с помощью одного Agent + хорошо спроектированного system_prompt и Middleware. Вводите multi-agent только тогда, когда вам действительно нужна изоляция доменов или независимый контекст.