Что такое AI-агент и чем он отличается от чат-бота
Содержание курса
0 / 1 баллов
Соберите цикл агента
Готовый цикл даёт create_agent, и в реальном проекте писать его руками не нужно. Но пока он остаётся чёрным ящиком, отлаживать агента тяжело: непонятно, что именно уходит в модель и на каком шаге прогон срывается. Соберём этот цикл сами — один раз, чтобы дальше видеть его насквозь.
Задание
Реализуйте функцию run_agent(model, tools, task, max_steps).
Начните диалог с одного сообщения — запроса пользователя task. Дальше повторяйте: вызовите model.invoke(messages), добавьте полученный ответ в диалог, а затем разберите его заявки на вызовы. Если заявок нет, прогон закончен — верните текст ответа. Если есть, исполните каждую по очереди и добавьте её результат в диалог отдельным сообщением, после чего вызовите модель снова.
Число обращений к модели ограничено значением max_steps. Если лимит израсходован, а модель так и не ответила без заявок, верните строку "LIMIT_REACHED".
Что приходит в аргументах
model — объект с методом invoke(messages), принимающим текущий список сообщений. Возвращает ответ с двумя полями: text — обычный текст, и tool_calls — список заявок. Каждая заявка это словарь с ключами name (имя инструмента), args (словарь аргументов) и id.
tools — словарь: имя инструмента → функция. Функцию вызывают именованными аргументами из args, возвращает она строку.
Пример
def count_clients(threshold: int) -> str:
return "2"
# Модель просит инструмент, получает результат и отвечает текстом.
run_agent(model, {"count_clients": count_clients}, "Сколько клиентов?", 12)
# "Клиентов с балансом выше 1000 — двое."
# Модель на каждом шаге снова просит инструмент, лимит равен двум.
run_agent(model, {"count_clients": count_clients}, "Сколько клиентов?", 2)
# "LIMIT_REACHED"
Примечание
Формат сообщений в списке произвольный — проверяется только их количество. Важно, что после ответа модели с двумя заявками диалог вырастает на три сообщения: сам ответ и два результата. Если что-то из этого потерять, заглушка модели прервёт прогон с ошибкой.
Инструменты не бросают исключений и всегда возвращают строку, так что оборачивать их в try здесь не нужно. Ответ модели может содержать несколько заявок сразу — исполняйте их в том порядке, в каком они лежат в tool_calls.
model и tools приходят готовыми — создавать их не нужно. Разрешена только стандартная библиотека Python 3.12.
О данных в ответах
Используйте учебные данные. Не вставляйте пароли, токены, ключи доступа, паспортные и банковские данные, а также персональные данные других людей. Политика обработки данных.
- Примеры из условия
def _count_clients(threshold: int) -> str: return "2" _TOOLS = {"count_clients": _count_clients} # Модель просит инструмент, получает результат и отвечает текстом. _model = ScriptedModel([ ModelReply(tool_calls=[ {"name": "count_clients", "args": {"threshold": 1000}, "id": "c1"}, ]), ModelReply(text="Клиентов с балансом выше 1000 — двое."), ]) assert run_agent(_model, _TOOLS, "Сколько клиентов?", 12) == \ "Клиентов с балансом выше 1000 — двое.", "ожидался финальный текст модели" assert _model.seen_lengths == [1, 3], \ "второй вызов должен видеть запрос, ответ модели и результат инструмента" # Модель на каждом шаге снова просит инструмент — срабатывает лимит. _looping = ScriptedModel([ ModelReply(tool_calls=[ {"name": "count_clients", "args": {"threshold": 1000}, "id": "c1"}, ]) for _ in range(5) ]) assert run_agent(_looping, _TOOLS, "Сколько клиентов?", 2) == "LIMIT_REACHED", \ "лимит исчерпан, обычного ответа не было" assert len(_looping.seen_lengths) == 2, \ "модель должна быть вызвана ровно max_steps раз"
Как проверяется решение
Проверяются функции и их результаты. Собственный запуск выполняет ваш код без авторских тестов. Интерактивный запуск не влияет на оценку. Лимит сессии — 5 минут, процессорного времени — 10 секунд.
Отправьте решение, чтобы увидеть результаты тестов.
