Оркестрация мульти-агентных систем: Делегирование задач

50 минут Урок 18

Введение: От солиста к оркестру

Добро пожаловать в четвертый модуль. До этого момента мы работали с Gemini как с невероятно умным, но одиноким исполнителем. Вы отправляли промпт, модель думала и выдавала результат. Это отлично работает для суммаризации текста или написания простого кода. Но что происходит, когда задача становится слишком сложной?

Представьте, что вы просите одного человека: «Спроектируй архитектуру здания, рассчитай смету, нарисуй дизайн интерьера и согласуй документы с мэрией». Даже гений начнет ошибаться. Он потеряет фокус, перепутает контексты или упустит детали.

В разработке на базе LLM решение этой проблемы — Мульти-агентные системы (MAS). Сегодня мы разбираем сердце такой системы: Оркестрацию и Делегирование.

Ключевая идея урока: Мы больше не пытаемся создать один «Божественный Промпт» (God Prompt). Вместо этого мы создаем команду специализированных агентов (воркеров) и одного управляющего (оркестратора), который знает, кому и когда передать задачу.

Архитектура «Менеджер-Воркер»

Самый надежный паттерн для начала работы с агентами — это иерархическая структура. Давайте разберем её анатомию.

  • Оркестратор (Менеджер): Это агент, оснащенный моделью Gemini (обычно более мощной, например, Pro-версией), чья цель — не выполнять работу, а понимать её суть и планировать. Его системная инструкция запрещает писать код или искать информацию напрямую. Его единственные инструменты — это вызов других агентов.
  • Воркеры (Специалисты): Это агенты с узким фокусом. Например, «Агент-исследователь», «Агент-Python-разработчик», «Агент-рецензент». Они могут использовать более легкие модели (например, Flash) для скорости и экономии, так как их контекст ограничен одной задачей.
  • Протокол передачи (Handoff): Механизм, с помощью которого Менеджер передает контекст Воркеру и получает обратно структурированный результат.

В экосистеме Gemini 3 делегирование реализуется через механизм Function Calling (вызов функций). Для модели-менеджера другие агенты выглядят как инструменты (Tools).

python
import os
import google.generativeai as genai
from typing import List, Dict, Any

# Настройка API
genai.configure(api_key=os.environ["GOOGLE_API_KEY"])

# 1. Определение Воркеров (Специалистов)

# Системная инструкция для разработчика
coder_sys_instruct = """
Ты - Senior Python Developer. Твоя задача - писать чистый, документированный код 
по запросу. Не объясняй базовые вещи, выдавай только код и краткое описание архитектуры.
"""

# Системная инструкция для тестировщика
qa_sys_instruct = """
Ты - QA Engineer. Твоя задача - искать уязвимости и логические ошибки в коде. 
Ты получаешь код и возвращаешь список тестов или найденных багов.
"""

# 2. Определение функций-инструментов для Менеджера

# Эти функции будут реально вызывать других агентов (модели)
def call_coder_agent(task_description: str) -> str:
    """Вызывает агента-разработчика для написания кода."""
    model = genai.GenerativeModel('gemini-1.5-flash', system_instruction=coder_sys_instruct)
    response = model.generate_content(task_description)
    return f"[CODER OUTPUT]: {response.text}"

def call_qa_agent(code_to_test: str) -> str:
    """Вызывает агента-тестировщика для проверки кода."""
    model = genai.GenerativeModel('gemini-1.5-flash', system_instruction=qa_sys_instruct)
    response = model.generate_content(code_to_test)
    return f"[QA OUTPUT]: {response.text}"

# Словарь инструментов для регистрации
tools_for_manager = [call_coder_agent, call_qa_agent]

Логика делегирования: Как Менеджер принимает решения

В примере выше мы создали инструменты. Но как заставить Менеджера ими пользоваться правильно? Секрет кроется в системной инструкции Оркестратора.

Менеджер должен работать в цикле:

  1. Анализ: Получить запрос пользователя.
  2. Мысль (Reasoning): Решить, какой специалист нужен.
  3. Действие (Routing): Вызвать соответствующую функцию (tool use).
  4. Наблюдение: Получить ответ от функции (результат работы воркера).
  5. Синтез: Либо отдать финальный ответ пользователю, либо вызвать следующего агента.

Благодаря огромному контекстному окну Gemini, мы можем передавать всю историю переписки между агентами обратно в контекст Менеджера. Это позволяет ему помнить, что программист уже написал код, и теперь этот код нужно передать тестировщику.

python
# 3. Настройка Оркестратора

manager_sys_instruct = """
Ты - Технический Директор (CTO). 
Твоя цель - управлять разработкой ПО, используя доступных тебе сотрудников (инструменты).

Правила:
1. Если просят написать код -> делегируй call_coder_agent.
2. Получив код, ВСЕГДА отправляй его на проверку через call_qa_agent, прежде чем отдать пользователю.
3. Если найдены ошибки, верни задачу кодеру с комментариями QA.
4. Никогда не пиши код сам. Только управляй.
"""

manager_model = genai.GenerativeModel(
    'gemini-1.5-pro', 
    system_instruction=manager_sys_instruct,
    tools=tools_for_manager
)

# Эмуляция цикла работы агента (упрощенно)
chat = manager_model.start_chat(enable_automatic_function_calling=True)

user_request = "Нужен скрипт на Python для парсинга заголовков с новостного сайта."

# Благодаря enable_automatic_function_calling=True, библиотека сама:
# 1. Поймет, что нужно вызвать call_coder_agent
# 2. Выполнит функцию (запустит модель воркера)
# 3. Вернет результат менеджеру
# 4. Менеджер увидит результат, поймет правило #2 и вызовет call_qa_agent
# 5. Вернет финальный ответ

response = chat.send_message(user_request)
print(response.text)

Тонкости передачи контекста (Context Handoff)

Одна из самых частых ошибок при построении таких систем — потеря контекста или, наоборот, зашумление контекста.

Проблема: Если Менеджер просто перешлет Воркеру сообщение пользователя «Исправь это», Воркер не поймет, о чем речь, так как он не видел предыдущей работы.

Решение: При вызове функции-инструмента Менеджер должен явно сгенерировать аргументы, содержащие всю необходимую информацию. Gemini отлично справляется с извлечением нужных данных из истории диалога и упаковкой их в аргументы функции.

Существует два основных подхода к обмену данными:

  • Передача по значению (Pass by Value): Текст передается целиком в промпт воркера (как в нашем примере). Подходит для кода и коротких текстов.
  • Передача по ссылке (Pass by Reference): Если данных много (например, книга на 500 страниц), агенты обмениваются ссылками на файлы или записи в векторной базе данных, а не самим текстом.

Упражнение

Создайте систему 'Редакция блога'. Вам нужно реализовать Оркестратора (Главный редактор) и двух Воркеров: 1. 'Writer' (пишет черновик статьи по теме). 2. 'Editor' (проверяет стиль и исправляет ошибки). Сценарий: Пользователь просит 'Напиши статью про пользу зеленого чая'. Главред должен сначала поручить написание Райтеру, а затем полученный текст отдать Эдитору.

Обработка ошибок и циклы

Что если Воркер не справился? Например, 'Coder' написал код, который не запускается. В линейной цепи (Chain) процесс бы просто остановился или выдал ошибку пользователю. В агентной системе Менеджер может обработать это исключение.

В системном промпте Менеджера можно указать: «Если QA агент вернул список ошибок, не показывай их пользователю. Снова вызови Coder агента, передай ему код и список ошибок для исправления. Повторяй до 3-х раз».

Это превращает систему из простой конвейерной ленты в автономную петлю обратной связи (Feedback Loop). Именно способность к самокоррекции отличает настоящих агентов от простых скриптов.

Вопрос

В архитектуре Менеджер-Воркер, почему рекомендуется использовать более мощную модель (например, Gemini Pro) для Менеджера и более легкие (Flash) для Воркеров?