Праздничные роботы читают отчёт о счастье возле ёлки и подарков в новогодней атмосфере.

Создание готовых к применению программ магистратуры стало проще благодаря инструментарию NeMo Agent Toolkit.

От простого чата до многоагентного логического мышления и REST API в реальном времени.

Делиться

Изображение создано автором с помощью DALL-E 3

Когда я увидел, что Nvidia выпустила собственную платформу для агентов LLM, NeMo Agent Toolkit (или NAT), я очень обрадовался. Обычно мы считаем Nvidia компанией, которая подпитывает весь ажиотаж вокруг LLM своими графическими процессорами, поэтому очень интересно видеть, как они выходят за рамки аппаратного обеспечения и выходят на рынок программного обеспечения.

Уже существует множество фреймворков для агентов LLM: LangGraph, smolagents, CrewAI и DSPy, и это лишь некоторые из них. Однако NeMo Agent Toolkit несколько отличается. Я бы описал его как своего рода связующее звено, которое помогает объединить все части воедино и превратить их в готовое к использованию решение.

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

В этой статье я рассмотрю основные возможности инструментария NeMo Agent Toolkit на практике, начиная с простого приложения для завершения чата и постепенно переходя к иерархической агентской структуре, где один агент LLM может рекурсивно использовать других агентов в качестве инструментов. Поскольку сейчас праздничный сезон, я буду использовать общедоступные данные из Всемирного отчета о счастье, чтобы поддерживать позитивный настрой.

Настройка

Как обычно, начнём с настройки среды и установки пакета.

Сам базовый пакет довольно легковесный. Однако, как я уже упоминал, NAT предназначен для интеграции с различными LLM-фреймворками в вашем рабочем процессе. Поэтому для популярных библиотек, таких как LangChain, CrewAI и LlamaIndex, доступно несколько дополнительных плагинов. Самый актуальный список поддерживаемых плагинов всегда можно найти в официальной документации.
В этой статье мы будем использовать LangChain, поэтому нам также потребуется установить соответствующее расширение.

Совет: NAT работает НАМНОГО лучше и быстрее с UV. Изначально я пытался установить всё с помощью pip, и установка завершилась неудачей примерно через 20 минут ожидания. Настоятельно рекомендую не повторять моих ошибок.

Сначала создайте и активируйте виртуальную среду с помощью UV-развертки.

uv venv .venv_nat_uv —python 3.12 source .venv_nat_uv/bin/activate

Затем установите NAT с помощью плагина LangChain.

uv pip install «nvidia-nat[langchain]»

Если вы планируете запускать NAT из командной строки, вам также потребуется экспортировать соответствующие переменные среды. Поскольку я буду использовать антропные модели, мне нужно установить ключ API.

export ANTHROPIC_API_KEY=

Загрузка данных

Далее, давайте загрузим данные Всемирного отчета о счастье и рассмотрим их подробнее. Я подготовил небольшую вспомогательную функцию для загрузки набора данных и их небольшой очистки.

import pandas as pd def load_data(): df = pd.read_excel('whr2025_data.xlsx') df = df[df.Year >= 2019] df = df.drop(['Нижний усик', 'Верхний усик'], axis=1) df.columns = ['year', 'rank', 'country', 'happiness_score', 'impact_gdp', 'impact_social_support', 'impact_life_expectancy', 'impact_freedom', 'impact_generosity', 'impact_corruption', 'impact_residual'] return df df = load_data()

Этот набор данных содержит результаты Всемирного доклада о счастье. С 2019 по 2024 год. Для каждой страны и года приводится общий показатель уровня счастья, а также предполагаемый вклад нескольких лежащих в его основе факторов:

  • логарифм ВВП на душу населения,
  • социальная поддержка,
  • ожидаемая продолжительность здоровой жизни,
  • свобода выбора в жизни,
  • щедрость,
  • восприятие коррупции.

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

Пример завершения чата

Начнём с очень простого примера завершения чата. Архитектура здесь намеренно минималистична: один LLM без каких-либо дополнительных инструментов или агентов.

3b8c146f7d6649396da83c69b5143565

NeMo Agent Toolkit настраивается с помощью YAML-файлов, определяющих как рабочий процесс, так и базовые LLM-модули. Nvidia выбрала этот подход, поскольку он значительно упрощает экспериментирование с различными конфигурациями. В первом примере мы создадим файл chat_config.yml.

В общих чертах, наш конфигурационный файл будет состоять из двух основных разделов:

  • llms, где мы определяем языковые модели, которые хотим использовать.
  • Описание рабочего процесса, в котором мы описываем, как эти модели связаны между собой и как ведет себя агент.

Что касается LLM, NAT поддерживает несколько провайдеров «из коробки», включая OpenAI, Nvidia Inference Microservices и AWS Bedrock. Поскольку я хочу использовать антропную модель, самым простым вариантом здесь является LiteLLM, который выступает в качестве универсальной оболочки и позволяет нам подключаться практически к любому провайдеру.

В разделе «Рабочий процесс» мы укажем:

  • тип рабочего процесса (пока мы будем использовать самый простой вариант — завершение чата, но более сложные настройки агентов мы рассмотрим позже).
  • LLM, определенный выше, и
  • Системная подсказка, определяющая поведение агента.

Это дает нам надежный минимально жизнеспособный продукт (MVP) и стабильную основу для дальнейшего развития, прежде чем переходить к более сложным агентным приложениям.

llms: chat_llm: _type: litellm model_name: claude-sonnet-4-5-20250929 api_key: $ANTHROPIC_API_KEY temperature: 0.7 workflow: _type: chat_completion llm_name: chat_llm system_prompt: | Вы — опытный учёный в области изучения счастья. Вам доступен набор данных, содержащий данные Всемирного отчёта о счастье за период с 2019 по 2025 год. Ваша задача — проанализировать данные и предоставить информацию на основе запросов пользователей. Используйте набор данных, чтобы ответить на вопросы о рейтингах стран, тенденциях за эти годы и факторах, влияющих на показатели счастья.

Теперь пришло время запустить наше приложение. Мы можем сделать это с помощью одной команды CLI, указав путь к файлу конфигурации и задав вопрос для ввода.

nat run —config_file chat_config.yml —input «Как определяется счастье?»

После выполнения команды в консоли отобразится следующий вывод.

2025-12-24 18:07:34 — INFO — nat.cli.commands.start:192 — Запуск NAT из файла конфигурации: 'chat_config.yml' Сводка конфигурации: ——————— Тип рабочего процесса: chat_completion Количество функций: 0 Количество групп функций: 0 Количество LLM: 1 Количество встраиваемых модулей: 0 Количество памяти: 0 Количество хранилищ объектов: 0 Количество извлекающих модулей: 0 Количество стратегий TTC: 0 Количество поставщиков аутентификации: 0 2025-12-24 18:07:35 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-24 18:07:44 — INFO — nat.front_ends.console.console_front_end_plugin:102 — ————————————————— ['В докладе о мировом счастье счастье определяется как субъективное благополучие, измеряемое в основном с помощью вопроса оценки жизни по **лестнице Кантрила**, где респонденты оценивают свою текущую жизнь по шкале от 0 (худший из возможных) до 10 (лучший из возможных). Общий показатель счастья затем статистически объясняется шестью ключевыми факторами: ВВП на душу населения, социальная поддержка, ожидаемая продолжительность здоровой жизни, свобода выбора жизненного пути, щедрость и восприятие коррупции.'] —————————————————

Мы получили довольно неплохой ответ, основанный на общих знаниях модели. Теперь перейдем к следующему шагу и развернем его. Поскольку NAT разработан для приложений, готовых к использованию в производственной среде, мы можем легко предоставить наше решение в виде REST API. Позже в этой статье мы даже увидим, как превратить его в готовый к использованию пользовательский интерфейс.

Чтобы сделать нашего агента доступным через конечную точку API, мы можем использовать команду `nat serve`.

nat serve —config_file chat_config.yml

Теперь наше приложение доступно по адресу http://localhost:8000, и мы можем взаимодействовать с ним, используя Python. Формат API совместим с конечными точками OpenAI.

import requests import json # Тестирование конечной точки API response = requests.post( «http://localhost:8000/v1/chat/completions», headers={«Content-Type»: «application/json»}, json={ «messages»: [ { «role»: «user», «content»: «Сколько лет данных о счастье у нас есть?» } ], «stream»: False } ) # Анализ и отображение ответа if response.status_code == 200: result = response.json() print(result[«choices»][0][«message»][«content»]) else: print(f»Ошибка: {response.status_code}») print(response.text) # У нас есть данные о счастье за 7 лет, охватывающие период с 2019 по 2025 год.

Это даёт нам правдоподобный минимально жизнеспособный продукт (MVP), способный ответить на основные вопросы о данных о счастье. Однако для получения более глубоких аналитических выводов нашему агенту необходим контекст и доступ к фактическому набору данных. Следующим шагом станет оснащение его инструментами.

Добавление инструментов

Далее добавим пару инструментов, которые помогут нашему агенту анализировать данные Всемирного доклада о счастье. Мы предоставим нашему агенту две функции:

  • Функция get_country_stats возвращает все данные о счастье, отфильтрованные по конкретной стране.
  • Функция get_year_stats выводит обзор отчета о счастье за определенный год, включая самые счастливые и наименее счастливые страны, средний показатель счастья и факторы, влияющие на него.
e0d02cdb4b3472174f023e11f79e5c60

Добавление инструментов в набор инструментов NeMo Agent требует написания довольно большого количества шаблонного кода. Нам необходимо выполнить следующие шаги:

  1. Реализуйте функции на Python.
  2. Определите схему входных данных для каждой функции.
  3. Создайте соответствующие классы конфигурации.
  4. Оберните функции так, чтобы они были асинхронными и вызывались агентом.
  5. Обновите конфигурацию YAML.

К счастью, NAT предоставляет команду создания рабочего процесса, которая генерирует структуру, помогающую организовать ваш проект.

nat workflow create happiness_v1

Эта команда не генерирует всю реализацию автоматически, но создает структуру проекта со всеми необходимыми файлами. После ее выполнения будет создана следующая структура.

happiness_v1/ ├── 📄 pyproject.toml # Конфигурация пакета Python ├── 📁 configs/ # Конфигурация корневого уровня (символическая ссылка или копирование) │ └── config.yml # Конфигурация рабочего процесса NAT ├── 📁 data/ # Папка данных корневого уровня (пустая) │ └── 📁 src/ # Исходный код └── 📁 happiness_v1/ # Основной пакет ├── 📄 __init__.py # Инициализатор пакета (пустой) ├── 📄 happiness_v1.py # Реализация основных функций ├── 📄 register.py # Функция регистрация (точка входа) ├── 📁 configs/ # Конфигурация для конкретного пакета │ └── config.yml # Конфигурация рабочего процесса NAT └── 📁 data/ # Папка с данными пакета (пустая)

Давайте начнём создавать нашего агента. Первый шаг — реализация функций на Python. Я создал папку utils внутри src/happiness_v1 и добавил туда функции, которые агент должен использовать. Я также включил удобную вспомогательную функцию load_data, которую мы рассматривали ранее, и которую агент будет использовать в фоновом режиме для предварительной загрузки данных из отчёта о счастье.

from typing import Dict, List, Optional, Union def get_country_stats(df: pd.DataFrame, country: str) -> pd.DataFrame: «»» Получает статистику счастья для конкретной страны. Аргументы: df (pd.DataFrame): DataFrame, содержащий данные о счастье. country (str): Название страны для фильтрации. Возвращает: pd.DataFrame: Отфильтрованный DataFrame со статистикой для указанной страны. «»» return df[df['country'].str.contains(country, case=False)] def get_year_stats(df: pd.DataFrame, year: int) -> str: «»» Получает статистику счастья за конкретный год. Аргументы: df (pd.DataFrame): DataFrame, содержащий данные о счастье. year (int): Год для фильтрации. Возвращает: summary (str): Сводная статистика за указанный год. «»» year_df = df[df['year'] == year].sort_values('rank') top5_countries = f''' Топ-5 стран в {year} по рейтингу счастья: {year_df.head(5)[[«rank», «country», «happiness_score»]].to_string(index=False)} ''' bottom5_countries = f''' Нижние 5 стран в {year} по рейтингу счастья: {year_df.tail(5)[[«rank», «country», «happiness_score»]].to_string(index=False)} ''' scores_mean = f''' Средний показатель счастья в {year}: {year_df[['happiness_score', 'impact_gdp', 'impact_social_support', 'impact_life_expectancy', 'impact_freedom', 'impact_generosity', 'impact_corruption']].mean().to_string()} ''' return top5_countries + 'n' + bottom5_countries + 'n' + scores_mean def load_data(): df = pd.read_excel('whr2025_data.xlsx') df = df[df.Year >= 2019] df = df.drop(['Lower whisker', 'Upper whisker'], axis=1) df.columns = ['year', 'rank', 'country', 'happiness_score', 'impact_gdp', 'impact_social_support', 'impact_life_expectancy', 'impact_freedom', 'impact_generosity', 'impact_corruption', 'impact_residual'] return df

Теперь давайте определим входные схемы для наших инструментов. Для этого мы будем использовать Pydantic, указав как ожидаемые аргументы, так и их описания. Этот шаг критически важен, поскольку именно схема и описания позволяют LLM понимать, когда и как использовать каждый инструмент. Мы добавим этот код в src/happiness_v1/register.py.

from pydantic import BaseModel, Field class CountryStatsInput(BaseModel): country: str = Field( description=»Название страны для фильтрации данных отчета о счастье. Например: 'Финляндия', 'США', 'Индия'.» ) class YearStatsInput(BaseModel): year: int = Field( description=»Год для фильтрации данных отчета о счастье. Например: 2019, 2020, 2021.» )

Далее нам необходимо создать соответствующие классы конфигурации. Они определяют уникальные имена для инструментов, на которые мы позже будем ссылаться из конфигурации YAML.

from nat.data_models.function import FunctionBaseConfig class CountryStatsConfig(FunctionBaseConfig, name=»country_stats»): «»»Конфигурация для расчета статистики счастья по странам.»»» pass class YearStatsConfig(FunctionBaseConfig, name=»year_stats»): «»»Конфигурация для расчета статистики счастья по годам.»»» pass

Следующий шаг — обернуть наши функции Python, чтобы агент мог их вызывать. Пока что мы упростим задачу: загрузим данные, обернём функцию и укажем входную схему и конфигурацию. Как передавать и использовать параметры из YAML-конфигурации мы рассмотрим позже.

@register_function(config_type=CountryStatsConfig) async def country_stats_tool(config: CountryStatsConfig, builder: Builder): «»»Зарегистрируйте инструмент для расчета статистики счастья по странам.»»» df = load_data() async def _wrapper(country: str) -> str: result = get_country_stats(df, country) return result yield FunctionInfo.from_fn( _wrapper, input_schema=CountryStatsInput, description=»Получить статистику счастья для конкретной страны из данных Всемирного отчета о счастье.» ) @register_function(config_type=YearStatsConfig) async def year_stats_tool(config: YearStatsConfig, builder: Builder): «»»Зарегистрируйте инструмент для расчета статистики счастья по годам.»»» df = load_data() async def _wrapper(year: int) -> str: result = get_year_stats(df, year) return result yield FunctionInfo.from_fn( _wrapper, input_schema=YearStatsInput, description=»Получить статистику счастья за конкретный год из данных Всемирного доклада о счастье.» )

Наконец, нам нужно обновить конфигурацию YAML в файле src/happiness_v1/configs/config.yml. Сначала добавим раздел функций. Затем обновим тип рабочего процесса, чтобы использовать агента ReAct, который реализует один из наиболее распространенных шаблонов работы агентов, основанный на цикле «Мысль → Действие → Наблюдение». NAT также поддерживает несколько других типов рабочих процессов, таких как агенты рассуждений и агенты маршрутизатора.

функции: country_stats: _type: happiness_v1/country_stats year_stats: _type: happiness_v1/year_stats llms: chat_llm: _type: litellm model_name: anthropic/claude-sonnet-4-5-20250929 api_key: $ANTHROPIC_API_KEY temperature: 0.7 workflow: _type: react_agent llm_name: chat_llm tool_names: [country_stats, year_stats] verbose: true max_iterations: 5 parse_agent_response_max_retries: 2

Теперь мы можем установить пакет локально и запустить агент.

source .venv_nat_uv/bin/activate cd happiness_v1 uv pip install -e . cd .. nat run —config_file happiness_v1/src/happiness_v1/configs/config.yml —input «Is Denmark happier than Finland?»

При использовании антропной модели с агентом ReAct я столкнулся с проблемой, которая была исправлена в последней (ещё не стабильной) версии NAT. Мне пришлось внести исправления вручную.

После применения исправления все заработало как положено. Агент запросил данные по Дании и Финляндии, проанализировал результаты и дал обоснованный окончательный ответ, основанный на фактических данных Отчета о счастье. Добавление инструментов позволило агенту отвечать на более тонкие вопросы, касающиеся Отчета о счастье.

—————————— [АГЕНТ] Ввод агента: Дания счастливее Финляндии? Мысли агента: Мысль: Чтобы ответить на вопрос, счастливее ли Дания, чем Финляндия, мне нужны данные о счастье в обеих странах. Давайте начнем со статистики счастья Дании. Действие: country_stats Входные данные действия: {«country»: «Denmark»} —————————— 2025-12-25 11:32:52 — INFO — nat.agent.base:221 — —————————— [AGENT] Вызов инструментов: country_stats Входные данные инструмента: {'country': 'Denmark'} Ответ инструмента: год ранг страна показатель счастья влияние ВВП влияние социальной поддержки влияние ожидаемой продолжительности жизни влияние свободы влияние щедрости влияние коррупции влияние остаточного дохода 455 2024 2 Дания 7.5210 1.825000 1.748000 0.820000 0.95500 0.150000 0.48800 1.535000 456 2023 2 Дания 7.5830 1.908000 1.520000 0.699000 0.82300 0.204000 0.54800 1.881000 457 2022 2 Дания 7.5860 1.949000 1.548000 0.537000 0.73400 0.208000 0.52500 2.084000 458 2021 2 Дания 7.6360 1.953000 1.243000 0.777000 0.71900 0.188000 0.53200 2.226000 459 2020 3 Дания 7.6200 1.502000 1.108000 0.763000 0.68600 0.208000 0.48500 2.868000 460 2019 2 Дания 7.6456 1.326949 1.503449 0.979333 0.66504 0.242793 0.49526 2.432741 [6 строк x 11 столбцов] —————————— 11:32:52 — LiteLLM:INFO: utils.py:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 11:32:52 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 11:32:54 — INFO — nat.agent.react_agent.agent:193 — —————————— [AGENT] Ввод агента: Дания счастливее Финляндии? Мысли агента: Мысль: Теперь мне нужно получить статистику счастья Финляндии, чтобы сравнить ее с Данией. Действие: country_stats Входные данные действия: {«country»: «Finland»} —————————— 2025-12-25 11:32:54 — INFO — nat.agent.base:221 — —————————— [AGENT] Вызов инструментов: country_stats Входные данные инструмента: {'country': 'Finland'} Ответ инструмента: год ранг страна показатель счастья влияние ВВП влияние социальной поддержки влияние ожидаемой продолжительности жизни влияние свободы влияние щедрости влияние коррупции влияние остаточного дохода 563 2024 1 Финляндия 7.7360 1.74900 1.783000 0.824000 0.986000 0.11000 0.502000 1.782000 564 2023 1 Финляндия 7,7410 1,84400 1,572000 0,695000 0,859000 0,14200 0,546000 2,082000 565 2022 1 Финляндия 7,8040 1,88800 1,585000 0,535000 0,772000 0,12600 0,535000 2,363000 566 2021 1 Финляндия 7,8210 1,89200 1,258000 0,775000 0,736000 0,10900 0,534000 2.518000 567 2020 2 Финляндия 7.8420 1.44600 1.106000 0.741000 0.691000 0.12400 0.481000 3.253000 568 2019 1 Финляндия 7.8087 1.28519 1.499526 0.961271 0.662317 0.15967 0.477857 2.762835 [6 строк x 11 столбцов] —————————— 11:32:54 — LiteLLM:INFO: utils.py:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 11:32:54 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025—12-25 11:32:59 — INFO — nat.agent.react_agent.agent:193 — —————————— [AGENT] Ввод агента: Дания счастливее Финляндии? Мысли агента: Мысль: Теперь у меня есть данные о счастье как в Дании, так и в Финляндии. Анализируя рейтинги, можно заметить, что Финляндия неизменно занимает первое место в последние годы (2024, 2023, 2022, 2021 и 2019), в то время как Дания в 2020 году была на втором месте. Это указывает на то, что Финляндия в целом считается более счастливой, чем Дания, согласно рейтингам Всемирного доклада о счастье. Окончательный ответ: Нет, Дания не счастливее Финляндии. Согласно данным Всемирного доклада о счастье, Финляндия неизменно занимает первое место по уровню счастья в течение большинства последних лет (2024, 2023, 2022, 2021 и 2019), что делает её самой счастливой страной в мире. Хотя Дания также входит в число самых счастливых стран мира, Финляндия превосходит Данию в рейтинге счастья. —————————— 2025-12-25 11:32:59 — INFO — nat.front_ends.console.console_front_end_plugin:102 — ————————————————— Результат выполнения рабочего процесса: ['Нет, Дания не счастливее Финляндии. Согласно данным Всемирного доклада о счастье, Финляндия неизменно занимает первое место по уровню счастья в течение последних нескольких лет (2024, 2023, 2022, 2021 и 2019), что делает ее самой счастливой страной в мире. Хотя Дания также входит в число самых счастливых стран мира, Финляндия превосходит Данию в рейтинге счастья.'] —————————————————

Совет: Не забудьте удалить пакет после завершения экспериментов, чтобы избежать конфликтов версий в дальнейшем.

uv pip uninstall happyness_v1

Полный код этой версии можно найти на GitHub.

Интеграция другого агента в качестве инструмента

Наш агент уже достаточно компетентен и может отвечать на простые вопросы о данных Всемирного доклада о счастье. Однако он всё ещё испытывает трудности с некоторыми типами вопросов, например, насколько счастливее люди в Финляндии по сравнению с людьми в Великобритании. В таких случаях агент, скорее всего, будет давать галлюцинации, поскольку ему не хватает базовых вычислительных навыков. К счастью, мы можем это исправить, предоставив агенту доступ к калькулятору.

У меня уже есть реализованный в LangGraph агент-калькулятор из предыдущего проекта. Это очень простой агент с одним инструментом, который выполняет произвольный код на Python. Если вам интересно, вы можете найти реализацию здесь.

Вот как это работает на практике.

from calculator.calculator_agent import calculate result = calculate(«Широта уровня счастья в Финляндии составляет 7,73%, а в Соединенном Королевстве — 6,73%. Насколько люди в Финляндии счастливее, чем в Соединенном Королевстве, в процентах?») print(«Результат:», result['final_result']) print(«Пояснение:», result['explanation']) # Результат: 14,86 # Пояснение: **Ответ:** Люди в Финляндии на **14,86%** счастливее, чем люди # в Соединенном Королевстве. # **Пояснение:** # — Показатель счастья в Финляндии: 7,73 # — Показатель счастья в Великобритании: 6,73 # — Абсолютная разница: 7,73 — 6,73 = 1,00 # — Расчет в процентах: (1,00 ÷ 6,73) × 100 = 14,86% # Это означает, что показатель счастья в Финляндии примерно на 14,86% выше, # чем показатель счастья в Великобритании.

Преимущество NeMo Agent Toolkit в том, что нам не нужно переписывать этот агент с нуля. С помощью нескольких небольших изменений мы можем интегрировать наш существующий агент-калькулятор на основе LangGraph непосредственно в рабочий процесс NAT. Давайте посмотрим, как это сделать дальше.

8fb86398f6a6fc1a569a92df168b4556

Во-первых, я внес небольшое изменение в реализацию агента-калькулятора, чтобы он мог работать с различными LLM-моделями, передаваемыми в качестве входных данных. Для этого я добавил две вспомогательные функции: create_calculator_agent и calculate_with_agent. Полную реализацию можно найти на GitHub.

Дальнейший процесс очень похож на добавление любого другого инструмента. Начнём с импорта агента калькулятора в файл register.py.

from happiness_v2.utils.calculator_agent import create_calculator_agent, calculate_with_agent

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

class CalculatorInput(BaseModel): question: str = Field( description=»Вопрос, связанный с математикой или вычислениями, необходимыми для статистики счастья.» ) class CalculatorAgentConfig(FunctionBaseConfig, name=»calculator_agent»): «»»Конфигурация для агента математического калькулятора.»»» pass

Теперь мы можем зарегистрировать функцию. На этот раз мы будем использовать объект-конструктор для загрузки выделенного LLM для агента-калькулятора (calculator_llm), который мы определим позже в конфигурации YAML. Поскольку этот агент реализован с помощью LangGraph, мы также указываем соответствующую обертку фреймворка.

@register_function(config_type=CalculatorAgentConfig, framework_wrappers=[LLMFrameworkEnum.LANGCHAIN]) async def calculator_agent_tool(config: CalculatorAgentConfig, builder: Builder): «»»Регистрирует агент калькулятора LangGraph в качестве инструмента NAT.»»» llm = await builder.get_llm(«calculator_llm», wrapper_type=LLMFrameworkEnum.LANGCHAIN) calculator_agent = create_calculator_agent(llm) async def _wrapper(question: str) -> str: # Используем агент калькулятора для обработки вопроса result = calculate_with_agent(question, calculator_agent) # Форматируем ответ как строку JSON response = { «calculation_steps»: result[«steps»], «final_result»: result[«final_result»], «explanation»: result[«explanation»] } return json.dumps(response, indent=2) yield FunctionInfo.from_fn( _wrapper, input_schema=CalculatorInput, description=»Выполнять сложные математические вычисления с помощью агента-калькулятора.» )

Последний шаг — обновление конфигурации YAML для включения нового инструмента и определение отдельной модели LLM для агента-калькулятора. Это позволит нам при необходимости использовать различные модели для рассуждений и вычислений.

функции: country_stats: _type: happinness_v2/country_stats year_stats: _type: happinness_v2/year_stats calculator_agent: _type: happinness_v2/calculator_agent llms: chat_llm: _type: litellm model_name: anthropic/claude-sonnet-4-5-20250929 api_key: $ANTHROPIC_API_KEY temperature: 0.7 calculator_llm: _type: litellm model_name: anthropic/claude-opus-4-5-20251101 api_key: $ANTHROPIC_API_KEY temperature: 0.7 workflow: _type: react_agent llm_name: chat_llm tool_names: [country_stats, year_stats, calculator_agent] verbose: true max_iterations: 5 parse_agent_response_max_retries: 2

На этом этапе наш основной агент может делегировать вычисление чисел отдельному агенту, фактически создавая иерархическую агентную структуру. Именно здесь NAT действительно проявляет себя во всей красе: существующие агенты, созданные в других фреймворках, могут быть повторно использованы в качестве инструментов с минимальными изменениями. Давайте попробуем.

source .venv_nat_uv/bin/activate cd happinness_v2 uv pip install -e . cd .. nat run —config_file happinness_v2/src/happinness_v2/configs/config.yml —input «Насколько в процентах счастливее люди в Финляндии по сравнению с Соединенным Королевством?»

Результат весьма впечатляющий. Сначала агент получает данные об уровне счастья в Финляндии и Великобритании, затем передает вычисление численных значений агенту-калькулятору, в конечном итоге выдавая правильный ответ, основанный на исходных данных, а не на предположениях или иллюзиях.

Сводка конфигурации: ——————— Тип рабочего процесса: react_agent Количество функций: 3 Количество групп функций: 0 Количество LLM: 2 Количество встраивающих модулей: 0 Количество памяти: 0 Количество хранилищ объектов: 0 Количество извлекающих модулей: 0 Количество стратегий TTC: 0 Количество поставщиков аутентификации: 0 12:39:02 — LiteLLM:INFO: utils.py:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 12:39:02 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 12:39:05 — INFO — nat.agent.react_agent.agent:169 — —————————— [AGENT] Ввод агента: Насколько в процентах счастливее люди в Финляндии по сравнению с Соединенным Королевством? Мысли агента: Мне нужно получить статистику счастья как для Финляндии, так и для Соединенного Королевства, чтобы сравнить их. Действие: country_stats Входные данные действия: {«country»: «Finland»} —————————— 2025-12-25 12:39:05 — INFO — nat.agent.base:221 — —————————— [AGENT] Вызов инструментов: country_stats Входные данные инструмента: {'country': 'Finland'} Ответ инструмента: год ранг страна показатель счастья влияние ВВП влияние социальной поддержки влияние ожидаемой продолжительности жизни влияние свободы влияние щедрости влияние коррупции влияние остаточного дохода 563 2024 1 Финляндия 7.7360 1.74900 1.783000 0.824000 0.986000 0.11000 0.502000 1.782000 564 2023 1 Финляндия 7,7410 1,84400 1,572000 0,695000 0,859000 0,14200 0,546000 2,082000 565 2022 1 Финляндия 7,8040 1,88800 1,585000 0,535000 0,772000 0,12600 0,535000 2,363000 566 2021 1 Финляндия 7,8210 1,89200 1,258000 0,775000 0,736000 0,10900 0,534000 2.518000 567 2020 2 Финляндия 7.8420 1.44600 1.106000 0.741000 0.691000 0.12400 0.481000 3.253000 568 2019 1 Финляндия 7.8087 1.28519 1.499526 0.961271 0.662317 0.15967 0.477857 2.762835 [6 строк x 11 столбцов] —————————— 12:39:05 — LiteLLM:INFO: utils.py:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 12:39:05 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025—12-25 12:39:07 — INFO — nat.agent.react_agent.agent:193 — —————————— [AGENT] Agent input: How much happier in percentages are people in Finland compared to the United Kingdom? Мысли агента: Действие: country_stats Ввод действия: {«country»: «United Kingdom»} —————————— 2025-12-25 12:39:07 — INFO — nat.agent.base:221 — —————————— [АГЕНТ] Вызов инструментов: country_stats Ввод инструмента: {'country': 'United Kingdom'} Ответ инструмента: год рейтинг страна показатель счастья влияние ВВП влияние социальной поддержки влияние ожидаемой продолжительности жизни влияние свободы влияние щедрости влияние коррупции влияние остаточного дохода 1853 2024 23 Великобритания 6.7280 1.725000 1.562000 0.7790 0.872000 0.211000 0.318000 1.260000 1854 2023 20 Соединенное Королевство 6.7490 1.822000 1.326000 0.6720 0.713000 0.267000 0.351000 1.598000 1855 2022 19 Соединенное Королевство 6.7960 1.857000 1.366000 0.5110 0.626000 0.272000 0.340000 1.822000 1856 2021 17 Соединенное Королевство 6.9430 1.867000 1.143000 0.7500 0.597000 0.289000 0.329000 1.967000 1857 2020 18 Великобритания 7.0640 1.423000 1.062000 0.7570 0.580000 0.340000 0.306000 2.596000 1858 2019 13 Великобритания 7.1645 1.273061 1.457845 0.9757 0.525169 0.373433 0.322602 2.236722 [6 строк x 11 столбцов] —————————— 12:39:07 — LiteLLM:INFO: utils.py:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 12:39:07 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 12:39:15 — INFO — nat.agent.react_agent.agent:193 — —————————— [AGENT] Ввод агента: Насколько в процентах счастливее жители Финляндии по сравнению с жителями Великобритании? Мысли агента: Теперь мне нужно получить фактические показатели счастья, чтобы рассчитать процентную разницу. Давайте я внимательнее изучу данные за последний год (2024). Мне следует использовать агента-калькулятор, чтобы помочь мне рассчитать процентную разницу. Во-первых, позвольте мне отметить рейтинги за 2024 год: Финляндия занимает 1-е место, а Великобритания — 23-е. Однако мне нужны фактические показатели счастья (вероятно, столбец «оценка»), чтобы рассчитать процентную разницу. Судя по структуре данных, там должен быть столбец «оценка». Позвольте мне попросить рассчитать это на основе типичных показателей Всемирного доклада о счастье. На 2024 год: — Финляндия (1-е место) обычно набирает около 7,7-7,8 баллов — Великобритания (23-е место) обычно набирает около 6,7-6,9 баллов. Давайте воспользуемся калькулятором, чтобы вычислить процентную разницу: Действие: calculator_agent Входные данные действия: {«вопрос»: «Если показатель счастья в Финляндии составляет 7,74, а в Соединенном Королевстве — 6,72, какова процентная разница, показывающая, насколько счастливее Финляндия по сравнению с Великобританией? Рассчитайте ее как ((показатель счастья Финляндии — показатель счастья Великобритании) / показатель счастья Великобритании) * 100»} —————————— 12:39:15 — LiteLLM:INFO: utils.py:3427 — LiteLLM completion() model= claude-opus-4-5-20251101; provider = anthropic 2025-12-25 12:39:15 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-opus-4-5-20251101; provider = anthropic 12:39:17 — LiteLLM:INFO: utils.py:1307 — Wrapper: Completed Call, calling success_handler 2025-12-25 12:39:17 — INFO — LiteLLM:1307 — Wrapper: Completed Call, calling success_handler 12:39:17 — LiteLLM:INFO: utils.py:3427 — LiteLLM completion() model= claude-opus-4-5-20251101; provider = anthropic 2025-12-25 12:39:17 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-opus-4-5-20251101; provider = anthropic 12:39:21 — LiteLLM:INFO: utils.py:1307 — Wrapper: Completed Call, calling success_handler 2025-12-25 12:39:21 — INFO — LiteLLM:1307 — Wrapper: Completed Call, calling success_handler 2025-12-25 12:39:21 — INFO — nat.agent.base:221 — —————————— [AGENT] Calling tools: calculator_agent Tool's input: {'question': 'If Finland has a happiness score of 7.74 and the United Kingdom has a happiness score of 6.72, what is the percentage difference showing how much happier Finland is compared to the UK? Вычислите это как ((оценка Финляндии — оценка Великобритании) / оценка Великобритании) * 100'} Ответ инструмента: { «calculation_steps»: [ «evaluate_python(finland_score = 7.74nuk_score = 6.72nn# Вычислите процентную разницу: ((Финляндия — Великобритания) / Великобритания) * 100nпроцентная_разница = ((оценка Финляндии — оценка Великобритании) / оценка Великобритании) * 100nрезультат = процентная_разница)» ], «final_result»: 15.18, «explanation»: «## РезультатnnИспользуя формулу: **((оценка Финляндии — оценка Великобритании) / оценка Великобритании) = 100**nn| Страна | Оценка счастья |n|———|——————|n| Финляндия | 7.74 |n| Соединенное Королевство | 6.72 |nn**Расчет:**n- Разница: 7.74 — 6.72 = 1.02n- Относительно Великобритании: 1.02 = 6.72 = 0.1518n- В процентах: 0.1518 = 100 = **15.18%**nn**Финляндия примерно на 15.18% счастливее, чем Соединенное Королевство** на основе этих показателей счастья.» } —————————— 12:39:21 — LiteLLM:INFO: utils.py:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025-12-25 12:39:21 — INFO — LiteLLM:3427 — LiteLLM completion() model= claude-sonnet-4-5-20250929; provider = anthropic 2025—12-25 12:39:25 — INFO — nat.agent.react_agent.agent:193 — —————————— [AGENT] Ввод агента: Насколько в процентах счастливее жители Финляндии по сравнению с жителями Великобритании? Мысли агента: Мысль: Теперь я знаю окончательный ответ. Окончательный ответ: Согласно данным Всемирного доклада о счастье за 2024 год, жители Финляндии примерно на **15,18% счастливее** по сравнению с жителями Великобритании. Это рассчитано на основе показателя счастья в Финляндии, равного 7,74 (1-е место), по сравнению с показателем Великобритании, равным 6,72 (23-е место), с использованием формулы: ((Показатель Финляндии — Показатель Великобритании) / Показатель Великобритании) × 100 = ((7,74 — 6,72) / 6,72) × 100 = 15,18%. —————————— 2025-12-25 12:39:25 — INFO — nat.front_ends.console.console_front_end_plugin:102 — ————————————————— Результат рабочего процесса: [«Согласно данным Всемирного отчета о счастье за 2024 год, жители Финляндии примерно на **15,18% счастливее**, чем жители Великобритании. nnЭто рассчитано на основе показателя счастья Финляндии 7,74 (1-е место) по сравнению с показателем Великобритании 6,72 (23-е место) с использованием формулы: ((Показатель Финляндии — Показатель Великобритании) / Показатель Великобритании) × 100 = ((7,74 — 6,72) / 6,72) × 100 = 15,18%.»] —————————————————

На данном этапе наш агент готов к тому, чтобы им поделились со всем миром, но для обеспечения доступности нам необходим удобный пользовательский интерфейс. Для начала, давайте развернем REST API, как мы это делали ранее.

nat serve —config_file happinness_v2/src/happinness_v2/configs/config.yml

После запуска API мы можем сосредоточиться на пользовательском интерфейсе. Вы можете свободно создавать собственные веб-приложения на основе REST API. Это хорошая возможность попрактиковаться в программировании с использованием Vibe. Однако в этом руководстве мы продолжим изучать встроенные возможности NAT, используя их готовый пользовательский интерфейс.

git clone https://github.com/NVIDIA/NeMo-Agent-Toolkit-UI.git cd NeMo-Agent-Toolkit-UI npm ci NEXT_TELEMETRY_DISABLED=1 npm run dev

После выполнения этих команд агент станет доступен по адресу http://localhost:3000. Вы сможете напрямую общаться с ним и видеть не только ответы, но и все промежуточные рассуждения и вызовы инструментов. Это невероятно удобный способ изучить поведение агента.

a7d9c8bb884c067796e13a90c303ad45

Полный код этой версии можно найти на GitHub.

Вот и всё! Теперь у нас есть полностью функциональный Агент Счастья с удобным пользовательским интерфейсом, способный отвечать на сложные вопросы и выполнять вычисления на основе реальных данных.

Краткое содержание

В этой статье мы рассмотрели NeMo Agent Toolkit (NAT) и его возможности. Давайте подведем итоги вкратце.

  • NAT — это инструмент для создания готовых к использованию в производственной среде приложений LLM. Его можно рассматривать как связующее звено, объединяющее различные компоненты, инструменты и рабочие процессы LLM, а также предоставляющее возможности развертывания и мониторинга.
  • Что мне действительно понравилось в NAT, так это то, что он выполняет свои обещания. Он не просто помогает запустить чат-агента; он действительно решает те проблемы «второго дня», которые часто ставят людей в тупик, такие как интеграция нескольких фреймворков, предоставление доступа к агентам через API или отслеживание того, что происходит «под капотом».
  • Конечно, не всё идеально. Одна из главных проблем, с которой я столкнулся, — это шаблонный код. Даже с современными помощниками по написанию кода настройка некоторых частей казалась несколько громоздкой по сравнению с другими фреймворками. Документация также могла бы быть понятнее (особенно руководства по началу работы), а поскольку сообщество всё ещё небольшое, найти ответы в интернете может быть сложно.

В этой статье мы сосредоточились на создании, интеграции и развертывании нашего Агента счастья. Мы не углублялись в вопросы мониторинга или оценки, но NAT также обладает некоторыми полезными функциями для этого. Поэтому мы рассмотрим эти темы в следующей статье.

В целом, работа с NAT ощущается как получение мощного набора инструментов, рассчитанного на долгосрочную эксплуатацию. Возможно, потребуется некоторая предварительная настройка, но как только все будет настроено, очень приятно видеть, как ваш агент не просто отвечает на вопросы, но и рассуждает, рассчитывает и действует в рамках готового к использованию рабочего процесса.

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

Ссылка

Данная статья вдохновлена кратким курсом «Nvidia's NeMo Agent Toolkit: Making Agents Reliable» от DeepLearning.AI.

Источник: towardsdatascience.com

✅ Найденные теги: Agent Toolkit, NeMo, Инструментарий, Магистратура, новости, Программы, Создание

ОСТАВЬТЕ СВОЙ КОММЕНТАРИЙ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Фото сгенерированных лиц: исследование показывает, что люди не могут отличить настоящие лица от сгенерированных
Нейросети построили капитализм за трое суток: 100 агентов Claude заперли…
Скетч: цифровой осьминог и виртуальный мир внутри компьютера с человечком.
Сцена с жестами пальцами, где один жест символизирует "VPN", а другой "KHP".
‼️Paramount купила Warner Bros. Discovery — сумма сделки составила безумные…
Скриншот репозитория GitHub "Claude Scientific Skills" AI для научных исследований.
Структура эффективного запроса Claude с элементами задачи, контекста и референса.
Эскиз и готовая веб-страница платформы для AI-дизайна в современном темном режиме.
ideipro logotyp
Image Not Found
Звёздное небо с галактиками и туманностями, космос, Вселенная, астрофотография.

Система оповещения обсерватории Рубина отправила 800 000 сигналов в первую ночь наблюдений.

Астрономы будут получать оповещения о небесных явлениях в течение нескольких минут после их обнаружения. Теренс О'Брайен, редактор раздела «Выходные». Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной…

Мар 2, 2026
Женщина с длинными тёмными волосами в синем свете, нейтральный фон.

Расследование в отношении 61-фунтовой машины, которая «пожирает» пластик и выплевывает кирпичи.

Обзор компактного пресса для мягкого пластика Clear Drop — и что будет дальше. Шон Холлистер, старший редактор Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 2, 2026
Черный углеродное волокно с текстурой плетения, отражающий свет.

Материал будущего: как работает «бессмертный» композит

Учёные из Университета штата Северная Каролина представили композит нового поколения, способный самостоятельно восстанавливаться после серьёзных повреждений.  Речь идёт о модифицированном армированном волокном полимере (FRP), который не просто сохраняет прочность при малом весе, но и способен «залечивать» внутренние…

Мар 2, 2026
Круглый экран с изображением замка и горы, рядом электронная плата.

Круглый дисплей Waveshare для креативных проектов

Круглый 7-дюймовый сенсорный дисплей от Waveshare создан для разработчиков и дизайнеров, которым нужен нестандартный экран.  Это IPS-панель с разрешением 1 080×1 080 пикселей, поддержкой 10-точечного ёмкостного сенсора, оптической склейкой и защитным закалённым стеклом, выполненная в круглом форм-факторе.…

Мар 2, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых