LLM listos para producción simplificados con NeMo Agent Toolkit

había lanzado su propio marco de agente LLM, NeMo Agent Toolkit (o NAT), me emocioné mucho. Generalmente pensamos en Nvidia como la compañía que impulsa todo el revuelo de LLM con sus GPU, por lo que es fascinante verlas ir más allá del hardware y entrar también en el espacio del software.

Ya existen muchos marcos de agentes LLM: LangGraph, smolagents, CrewAI y DSPy, solo por nombrar algunos. El NeMo Agent Toolkit, sin embargo, se siente un poco diferente. Lo describiría como una especie de pegamento que ayuda a unir todas las piezas y convertirlas en una solución lista para producción.

Nvidia posiciona este marco como una forma de abordar los problemas del “día 2”: exponer agentes como API, agregar observabilidad para monitorear su sistema e investigar casos extremos, crear evaluaciones y reutilizar agentes creados en otros marcos.

En este artículo, exploraré las capacidades principales de NeMo Agent Toolkit en la práctica, comenzando con una aplicación simple para completar chat y avanzando gradualmente hacia una configuración de agencia jerárquica, donde un agente de LLM puede usar recursivamente otros agentes como herramientas. Dado que es temporada festiva, utilizaré datos disponibles públicamente del Informe Mundial sobre la Felicidad para mantener la alegría.

Configurando

Como es habitual, comenzaremos configurando el entorno e instalando el paquete.

El paquete principal en sí es bastante liviano. Sin embargo, como mencioné anteriormente, NAT está diseñado para actuar como pegamento que permite integrarse con diferentes marcos LLM en su flujo de trabajo. Por eso, hay varios complementos opcionales disponibles para bibliotecas populares como LangChain, CrewAI y LlamaIndex. Siempre puedes encontrar la lista más actualizada de complementos compatibles en la documentación oficial.
En este artículo usaremos LangChain, por lo que también necesitaremos instalar la extensión correspondiente.

Consejo: NAT funciona MUCHO mejor y más rápido con uv. Inicialmente intenté instalar todo con pip y falló después de unos 20 minutos de espera. Recomiendo encarecidamente no repetir mis errores.

Primero, cree y active un entorno virtual usando uv.

uv venv .venv_nat_uv –python 3.12 fuente .venv_nat_uv/bin/activate

Luego instale NAT con el complemento LangChain.

Instalación de uv pip "nvidia-nat[langchain]"

Si planea ejecutar NAT desde la CLI, también deberá exportar las variables de entorno relevantes. Como usaré modelos Anthropic, necesito configurar la clave API.

exportar ANTHROPIC_API_KEY=

Cargando datos

A continuación, descarguemos los datos del Informe Mundial sobre la Felicidad y analicémoslos más de cerca. He creado una pequeña función auxiliar para cargar el conjunto de datos y limpiar ligeramente los datos.

importar pandas como pd def load_data(): df = pd.read_excel('whr2025_data.xlsx') df = df[df.Year >= 2019] df = df.drop(['Bigote inferior', 'Bigote superior'], eje=1) df.columns = ['año', 'rango', 'país', 'calificación_felicidad', 'impact_gdp', 'impact_social_support', 'impact_life_expectancy', 'impact_freedom', 'impact_generosity', 'impact_corruption', 'impact_residual'] return df df = load_data()

Este conjunto de datos cubre los resultados del Informe Mundial sobre la Felicidad de 2019 a 2024. Para cada país y año, incluye la puntuación general de felicidad, así como la contribución estimada de varios factores subyacentes:

logaritmo del PIB per cápita, apoyo social, esperanza de vida saludable, libertad para tomar decisiones de vida, generosidad, percepción de corrupción.

Con este conjunto de datos, podremos investigar los patrones de felicidad en todas las geografías y a lo largo del tiempo y, con suerte, detectaremos algunos patrones interesantes a lo largo del camino.

Ejemplo de finalización de chat

Comencemos con un ejemplo muy simple de finalización de chat. La arquitectura aquí es intencionalmente mínima: un único LLM sin herramientas ni agentes adicionales involucrados.

Imagen del autor

El NeMo Agent Toolkit se configura mediante archivos YAML que definen tanto el flujo de trabajo como los LLM subyacentes. Nvidia eligió este enfoque porque facilita mucho la experimentación con diferentes configuraciones. Para este primer ejemplo, crearemos un archivo chat_config.yml.

En un nivel alto, nuestro archivo de configuración constará de dos secciones principales:

Llms donde definimos los modelos de lenguaje que queremos usar, flujo de trabajo donde describimos cómo esos modelos están conectados entre sí y cómo se comporta el agente.

En el lado de LLM, NAT admite varios proveedores listos para usar, incluidos OpenAI, Nvidia Inference Microservices y AWS Bedrock. Como quiero usar un modelo Anthropic, la opción más sencilla aquí es LiteLLM, que actúa como un contenedor universal y nos permite conectarnos prácticamente a cualquier proveedor.

En la sección de flujo de trabajo, especificaremos:

el tipo de flujo de trabajo (usaremos el chat_completion más simple por ahora, pero exploraremos configuraciones de agente más complejas más adelante), el LLM definido anteriormente y el mensaje del sistema que establece el comportamiento del agente.

Esto nos brinda un MVP sólido y una base confiable sobre la cual construir antes de pasar a aplicaciones agentes más complejas.

llms: chat_llm: _type: litellm model_name: claude-sonnet-4-5-20250929 api_key: $ANTHROPIC_API_KEY temperatura: 0.7 flujo de trabajo: _type: chat_completion llm_name: chat_llm system_prompt: | Eres un científico experto en el campo de los estudios de la felicidad. Tiene acceso a un conjunto de datos que contiene los datos del Informe Mundial sobre la Felicidad de 2019 a 2025. Su tarea es analizar los datos y proporcionar información basada en las consultas de los usuarios. Utilice el conjunto de datos para responder preguntas sobre clasificaciones de países, tendencias a lo largo de los años y factores que influyen en las puntuaciones de felicidad.

Ahora es el momento de ejecutar nuestra aplicación. Podemos hacer esto con un solo comando CLI especificando la ruta al archivo de configuración y proporcionando una pregunta de entrada.

nat run –config_file chat_config.yml –input "¿Cómo se define la felicidad?"

Una vez que se ejecuta el comando, veremos el siguiente resultado en la consola.

2025-12-24 18:07:34 – INFORMACIÓN – nat.cli.commands.start:192 – Iniciando NAT desde el archivo de configuración: 'chat_config.yml' Resumen de configuración: ——————– Tipo de flujo de trabajo: chat_completion Número de funciones: 0 Número de grupos de funciones: 0 Número de LLM: 1 Número de incrustadores: 0 Número de memoria: 0 Número de almacenes de objetos: 0 Número de recuperadores: 0 Número de estrategias TTC: 0 Número de proveedores de autenticación: 0 2025-12-24 18:07:35 – INFO – LiteLLM:3427 – Finalización de LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = anthropic 2025-12-24 18:07:44 – INFO – nat.front_ends.console.console_front_end_plugin:102 – ————————————————– ['En el Informe Mundial de la Felicidad, la felicidad se define como el bienestar subjetivo, medido principalmente a través de la pregunta de evaluación de la vida **Escalera de Cantril**, donde los encuestados califican su vida actual en una escala de 0 (peor posible) a 10 (mejor posible). La puntuación general de felicidad se explica estadísticamente por seis factores clave: PIB per cápita, apoyo social, esperanza de vida saludable, libertad para tomar decisiones de vida, generosidad y percepciones de corrupción.'] ————————————————–

Obtuvimos una respuesta bastante decente basada en el conocimiento general del modelo. Ahora, demos el siguiente paso e implementémoslo. Dado que NAT está diseñado para aplicaciones listas para producción, podemos exponer fácilmente nuestra solución como una API REST. Más adelante en este artículo, incluso veremos cómo convertirla en una interfaz de usuario lista para el cliente.

Para que nuestro agente sea accesible a través de un punto final API, podemos usar el comando natserve.

servicio nat –config_file chat_config.yml

Ahora, nuestra aplicación está disponible en http://localhost:8000 y podemos interactuar con ella usando Python. El formato API es compatible con los puntos finales de OpenAI.

solicitudes de importación import json # Pruebe el punto final de API respuesta = request.post( "http://localhost:8000/v1/chat/completions", headers={"Content-Type": "application/json"}, json={ "messages": [ { "role": "user", "content": "¿Cuántos años de datos de felicidad tenemos?" } ], "stream": False } ) # Analiza y muestra la respuesta si respuesta.status_code == 200: resultado = respuesta.json() print(resultado["opciones"][0]["mensaje"]["contenido"]) else: print(f"Error: {response.status_code}") print(response.text) # Tenemos 7 años de datos de felicidad, que cubren el período de 2019 a 2025.

Esto nos da un MVP plausible que puede responder preguntas básicas sobre los datos de Felicidad. Sin embargo, para proporcionar información más profunda, nuestro agente necesita contexto y acceso al conjunto de datos real. Equiparlo con herramientas será nuestro siguiente paso.

Agregar herramientas

A continuación, agreguemos un par de herramientas que ayudarán a nuestro agente a analizar los datos del Informe Mundial de la Felicidad. Proporcionaremos a nuestro agente dos funciones:

get_country_stats devuelve todos los datos de felicidad filtrados por un país específico, get_year_stats genera una descripción general del Informe de felicidad para un año determinado, incluidos los países más felices y menos felices, el puntaje promedio de felicidad y los factores que lo influyen.

Imagen del autor

Agregar herramientas al kit de herramientas de NeMo Agent requiere bastante código repetitivo. Tendremos que seguir los siguientes pasos:

Implemente las funciones en Python, defina un esquema de entrada para cada función, cree las clases de configuración correspondientes, ajuste las funciones para que sean asíncronas y el agente pueda llamarlas, actualice la configuración YAML.

Afortunadamente, NAT proporciona el comando de creación de flujo de trabajo, que genera una estructura de andamiaje para ayudar a organizar su proyecto.

flujo de trabajo nat crea felicidad_v1

Este comando no genera toda la implementación, pero crea la estructura del proyecto con todos los archivos necesarios. Después de ejecutarlo, se creará la siguiente estructura.

felicidad_v1/ ├── 📄 pyproject.toml # Configuración del paquete Python ├── 📁 configs/ # Configuración de nivel raíz (enlace simbólico o copia) │ └── config.yml # Configuración de flujo de trabajo NAT ├── 📁 data/ # Carpeta de datos de nivel raíz (vacía) │ └── 📁 src/ # Código fuente └── 📁 felicidad_v1/ # Paquete principal ├── 📄 __init__.py # Inicializador de paquete (vacío) ├── 📄 felicidad_v1.py # Implementaciones de funciones principales ├── 📄 Register.py # Registro de función (punto de entrada) ├── 📁 configs/ # Configuración específica del paquete │ └── config.yml # Configuración de flujo de trabajo NAT └── 📁 data/ # Carpeta de datos del paquete (vacía)

Comencemos a construir nuestro agente. El primer paso es implementar las funciones en Python. Creé una carpeta de utilidades dentro de src/happiness_v1 y agregué las funciones que queremos que use el agente. También incluí una útil función auxiliar load_data que vimos anteriormente, que el agente usará detrás de escena para precargar los datos del Informe de felicidad.

desde escribir import Dict, List, Opcional, Union def get_country_stats(df: pd.DataFrame, country: str) -> pd.DataFrame: """ Obtener estadísticas de felicidad para un país específico. Args: df (pd.DataFrame): DataFrame que contiene datos de felicidad. country (str): Nombre del país por el que filtrar. Devuelve: pd.DataFrame: DataFrame filtrado con estadísticas para el país especificado. """ return df[df['country'].str.contains(country, case=False)] def get_year_stats(df: pd.DataFrame, año: int) -> str: """ Obtiene estadísticas de felicidad para un año específico. Args: df (pd.DataFrame): Marco de datos que contiene datos de felicidad año (int): Año para filtrar. Devuelve: resumen (str): Estadísticas resumidas para el año especificado. """ año_df = df[df['año'] == año].sort_values('rank') top5_countries = f''' Los 5 países principales en {año} por clasificación de felicidad: {year_df.head(5)[["rank", "country", "happiness_score"]].to_string(index=False)} ''' bottom5_countries = f''' Los 5 últimos países en {año} por felicidad Clasificación: {year_df.tail(5)[["rank", "country", "happiness_score"]].to_string(index=False)} ''' scores_mean = f''' Puntuación promedio de felicidad en {año}: {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' + puntuaciones_media def load_data(): df = pd.read_excel('whr2025_data.xlsx') df = df[df.Año >= 2019] df = df.drop(['bigote inferior', 'bigote superior'], eje=1) df.columns = ['año', 'rango', 'país', 'puntuación_felicidad', 'impacto_pib', 'impacto_social_apoyo', 'impact_vida_expectancia', 'impacto_libertad', 'impacto_generosidad', 'impacto_corrupción', 'impact_residual'] devolver df

Ahora, definamos los esquemas de entrada para nuestras herramientas. Usaremos Pydantic para esto, especificando tanto los argumentos esperados como sus descripciones. Este paso es fundamental porque el esquema y las descripciones son los que permiten al LLM comprender cuándo y cómo utilizar cada herramienta. Agregaremos este código a src/happiness_v1/register.py.

de pydantic import BaseModel, clase de campo CountryStatsInput(BaseModel): país: str = Field( descripción="Nombre del país para filtrar los datos del Informe de felicidad. Por ejemplo: 'Finlandia', 'Estados Unidos', 'India'." ) clase YearStatsInput(BaseModel): año: int = Campo( descripción="Año para filtrar los datos del Informe de felicidad. Por ejemplo: 2019, 2020, 2021." )

A continuación, necesitamos crear las clases de configuración correspondientes. Estos definen nombres únicos para las herramientas, a los que luego haremos referencia desde la configuración de YAML.

from nat.data_models.function import FunctionBaseConfig class CountryStatsConfig(FunctionBaseConfig, name="country_stats"): """Configuración para calcular estadísticas de felicidad específicas de un país.""" pasar clase YearStatsConfig(FunctionBaseConfig, name="year_stats"): """Configuración para calcular estadísticas de felicidad específicas de un año.""" pasar

El siguiente paso es empaquetar nuestras funciones de Python para que el agente pueda invocarlas. Por ahora, mantendremos las cosas simples: cargar los datos, ajustar la función y especificar el esquema de entrada y la configuración. Más adelante veremos cómo pasar y utilizar parámetros de la configuración YAML.

@register_function(config_type=CountryStatsConfig) async def country_stats_tool(config: CountryStatsConfig, builder: Builder): """Herramienta de registro para calcular estadísticas de felicidad específicas de un país.""" df = load_data() async def _wrapper(country: str) -> str: result = get_country_stats(df, country) return result return FunctionInfo.from_fn( _wrapper, input_schema=CountryStatsInput, descripción="Obtener estadísticas de felicidad para un país específico a partir de los datos del Informe Mundial de la Felicidad." ) @register_function(config_type=YearStatsConfig) async def year_stats_tool(config: YearStatsConfig, builder: Builder): """Herramienta de registro para calcular estadísticas de felicidad específicas del año.""" df = load_data() async def _wrapper(year: int) -> str: resultado = get_year_stats(df, año) return resultado rendimiento FunctionInfo.from_fn( _wrapper, input_schema=YearStatsInput, descripción="Obtenga estadísticas de felicidad para un año específico a partir de los datos del Informe Mundial de la Felicidad." )

Finalmente, necesitamos actualizar la configuración de YAML en src/happiness_v1/configs/config.yml. Primero, agregaremos una sección de funciones. Luego, actualizaremos el tipo de flujo de trabajo para usar un agente ReAct, que implementa uno de los patrones de agente más comunes basados ​​en el ciclo Pensamiento → Acción → Observación. NAT también admite otros tipos de flujo de trabajo, como agentes razonadores y agentes enrutadores.

funciones: country_stats: _type: felicidad_v1/country_stats Year_stats: _type: felicidad_v1/year_stats llms: chat_llm: _type: litellm model_name: anthropic/claude-sonnet-4-5-20250929 api_key: $ANTHROPIC_API_KEY temperatura: 0.7 flujo de trabajo: _type: react_agent llm_name: chat_llm nombres_herramientas: [estadísticas_país, estadísticas_año] detallado: verdadero max_iterations: 5 parse_agent_response_max_retries: 2

Ahora podemos instalar el paquete localmente y ejecutar el agente.

fuente .venv_nat_uv/bin/activate cd felicidad_v1 uv pip install -e. cd .. nat run –config_file felicidad_v1/src/happiness_v1/configs/config.yml –input "¿Es Dinamarca más feliz que Finlandia?"

Mientras usaba el modelo Anthropic con el agente ReAct, me encontré con un problema que se solucionó en la última versión (aún no estable) de NAT. Tuve que parchearlo manualmente.

Después de aplicar la solución, todo funcionó como se esperaba. El agente consultó los datos de Dinamarca y Finlandia, razonó sobre los resultados y produjo una respuesta final fundamentada basada en los datos reales del Informe de Felicidad. Agregar herramientas permitió al agente responder preguntas más matizadas sobre el Informe de Felicidad.

—————————— [AGENTE] Aporte del agente: ¿Es Dinamarca más feliz que Finlandia? Pensamientos del agente: Pensamiento: Para responder si Dinamarca es más feliz que Finlandia, necesito obtener datos sobre la felicidad de ambos países. Permítanme empezar por conocer las estadísticas de felicidad de Dinamarca. Acción: country_stats Entrada de acción: {"country": "Dinamarca"} —————————— 2025-12-25 11:32:52 – INFO – nat.agent.base:221 – —————————— [AGENTE] Herramientas de llamada: country_stats Entrada de la herramienta: {'país': 'Dinamarca'} Respuesta de la herramienta: año clasificación país felicidad_score impacto_gdp impacto_social_support impact_life_expectancy impact_freedom impact_generosity impact_corruption impact_residual 455 2024 2 Dinamarca 7,5210 1,825000 1,748000 0,820000 0,95500 0,150000 0,48800 1,535000 456 2023 2 Dinamarca 7,5830 1,908000 1,520000 0,699000 0,82300 0,204000 0,54800 1,881000 457 2022 2 Dinamarca 7,5860 1,949000 1,548000 0,537000 0,73400 0,208000 0,52500 2,084000 458 2021 2 Dinamarca 7,6360 1,953000 1,243000 0,777000 0,71900 0,188000 0,53200 2,226000 459 2020 3 Dinamarca 7,6200 1,502000 1,108000 0,763000 0,68600 0,208000 0,48500 2,868000 460 2019 2 Dinamarca 7,6456 1,326949 1,503449 0,979333 0,66504 0,242793 0,49526 2,432741 [6 filas x 11 columnas] —————————— 11:32:52 – LiteLLM:INFO: utils.py:3427 – LiteLLM finalización() modelo= claude-sonnet-4-5-20250929; proveedor = antrópico 2025-12-25 11:32:52 – INFORMACIÓN – LiteLLM:3427 – Finalización LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = antrópico 2025-12-25 11:32:54 – INFORMACIÓN – nat.agent.react_agent.agent:193 – —————————— [AGENTE] Entrada del agente: ¿Es Dinamarca más feliz que Finlandia? Pensamientos del agente: Pensamiento: Ahora necesito obtener las estadísticas de felicidad de Finlandia para compararlas con Dinamarca. Acción: country_stats Entrada de acción: {"country": "Finlandia"} —————————— 2025-12-25 11:32:54 – INFO – nat.agent.base:221 – —————————— [AGENTE] Herramientas de llamada: country_stats Entrada de la herramienta: {'country': 'Finlandia'} Respuesta de la herramienta: año ranking país felicidad_score impacto_gdp impacto_social_support impacto_vida_esperanza impacto_libertad impacto_generosidad impacto_corrupción impacto_residual 563 2024 1 Finlandia 7,7360 1,74900 1,783000 0,824000 0,986000 0,11000 0,502000 1,782000 564 2023 1 Finlandia 7,7410 1,84400 1,572000 0,695000 0,859000 0,14200 0,546000 2,082000 565 2022 1 Finlandia 7,8040 1,88800 1,585000 0,535000 0,772000 0,12600 0,535000 2,363000 566 2021 1 Finlandia 7,8210 1,89200 1,258000 0,775000 0,736000 0,10900 0,534000 2,518000 567 2020 2 Finlandia 7,8420 1,44600 1,106000 0,741000 0,691000 0,12400 0,481000 3,253000 568 2019 1 Finlandia 7,8087 1,28519 1,499526 0,961271 0,662317 0,15967 0,477857 2,762835 [6 filas x 11 columnas] —————————— 11:32:54 – LiteLLM:INFO: utils.py:3427 – LiteLLM finalización() modelo= claude-sonnet-4-5-20250929; proveedor = antrópico 2025-12-25 11:32:54 – INFORMACIÓN – LiteLLM:3427 – Finalización LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = antrópico 2025-12-25 11:32:59 – INFORMACIÓN – nat.agent.react_agent.agent:193 – —————————— [AGENTE] Entrada del agente: ¿Es Dinamarca más feliz que Finlandia? Pensamientos del agente: Pensamiento: Ahora tengo datos sobre felicidad tanto para Dinamarca como para Finlandia. En cuanto a las clasificaciones, Finlandia ha ocupado constantemente el puesto número 1 en los últimos años (2024, 2023, 2022, 2021 y 2019), mientras que Dinamarca ocupó el puesto número 2 en 2020. Esto indica que, en general, se considera que Finlandia es más feliz que Dinamarca según las clasificaciones del Informe Mundial sobre la Felicidad. Respuesta final: No, Dinamarca no es más feliz que Finlandia. Según los datos del Informe Mundial sobre la Felicidad, Finlandia ha ocupado constantemente el puesto número 1 en felicidad durante los años más recientes (2024, 2023, 2022, 2021 y 2019), lo que lo convierte en el país más feliz del mundo. Si bien Dinamarca también se encuentra entre los países más felices del mundo, Finlandia supera a Dinamarca en las clasificaciones de felicidad. —————————— 2025-12-25 11:32:59 – INFORMACIÓN – nat.front_ends.console.console_front_end_plugin:102 – ————————————————– Resultado del flujo de trabajo: ['No, Dinamarca no es más feliz que Finlandia. Según los datos del Informe Mundial sobre la Felicidad, Finlandia ha ocupado constantemente el puesto número 1 en felicidad durante los años más recientes (2024, 2023, 2022, 2021 y 2019), lo que lo convierte en el país más feliz del mundo. Si bien Dinamarca también se encuentra entre los países más felices del mundo, Finlandia supera a Dinamarca en el ranking de felicidad.'] ————————————————–

Consejo: No olvide desinstalar el paquete una vez que haya terminado de experimentar, para evitar colisiones de versiones más adelante.

uv pip desinstalar felicidad_v1

Puedes encontrar el código completo de esta versión en GitHub.

Integrar otro agente como herramienta

Nuestro agente ya es bastante capaz y puede responder preguntas sencillas sobre los datos del Informe Mundial de la Felicidad. Sin embargo, todavía tiene problemas con ciertos tipos de preguntas, por ejemplo, cuánto más felices son las personas en Finlandia en comparación con las del Reino Unido. En casos como este, el agente probablemente sufriría alucinaciones, ya que carece de capacidades de cálculo básicas. Afortunadamente, podemos solucionar este problema dándole al agente acceso a una calculadora.

Ya tengo implementado un agente de calculadora en LangGraph de un proyecto anterior. Es un agente muy simple con una única herramienta que ejecuta código Python arbitrario. Si tiene curiosidad, puede encontrar la implementación aquí.

Así es como funciona en la práctica.

from calculadora.calculator_agent import calcular resultado = calcular("El alcance de la felicidad en Finlandia es 7,73 mientras que en el Reino Unido es 6,73. ¿Cuánto son más felices las personas en Finlandia que en el Reino Unido en porcentajes?") print("Resultado:", resultado['final_result']) print("Explicación:", resultado['explicación']) # Resultado: 14,86 # Explicación: **Respuesta:** La gente en Finlandia es **14,86%** más feliz que la gente # en el Reino Unido. # **Explicación:** # – Puntuación de felicidad de Finlandia: 7,73 # – Puntuación de felicidad del Reino Unido: 6,73 # – Diferencia absoluta: 7,73 – 6,73 = 1,00 # – Cálculo del porcentaje: (1,00 ÷ 6,73) × 100 = 14,86% # Esto significa que la puntuación de felicidad de Finlandia es aproximadamente un 14,86% más alta que la del Reino Unido puntuación de felicidad.

Lo bueno de NeMo Agent Toolkit es que no necesitamos reescribir este agente desde cero. Con sólo unos pequeños ajustes, podemos integrar nuestro agente de calculadora basado en LangGraph existente directamente en el flujo de trabajo NAT. Veamos cómo hacerlo a continuación.

Imagen del autor

Primero, hice un pequeño cambio en la implementación del agente de calculadora para que pueda funcionar con diferentes LLM pasados ​​como entrada. Para hacer esto, introduje dos funciones auxiliares: create_calculator_agent y calcular_with_agent. Puede encontrar la implementación completa en GitHub.

A partir de aquí, el proceso es muy similar al de añadir cualquier otra herramienta. Comenzaremos importando el agente de calculadora a Register.py.

desde felicidad_v2.utils.calculator_agent importar create_calculator_agent, calcular_with_agent

A continuación, definimos el esquema de entrada y la configuración para la nueva herramienta. Dado que este agente es responsable del razonamiento matemático, el esquema de entrada solo necesita un único parámetro: la consulta a calcular.

clase CalculatorInput(BaseModel): pregunta: str = Field( descripción="Pregunta relacionada con matemáticas o cálculos necesarios para las estadísticas de felicidad." ) clase CalculatorAgentConfig(FunctionBaseConfig, name="calculator_agent"): """Configuración para el agente de calculadora matemática.""" pasar

Ahora podemos registrar la función. Esta vez, usaremos el objeto constructor para cargar un LLM dedicado para el agente de calculadora (calculator_llm), que definiremos más adelante en la configuración de YAML. Dado que este agente se implementa con LangGraph, también especificamos el contenedor de marco apropiado.

@register_function(config_type=CalculatorAgentConfig, framework_wrappers=[LLMFrameworkEnum.LANGCHAIN]) async def calculadora_agent_tool(config: CalculatorAgentConfig, builder: Builder): """Registre el agente de calculadora LangGraph como herramienta NAT.""" llm = await builder.get_llm("calculator_llm", wrapper_type=LLMFrameworkEnum.LANGCHAIN) calculadora_agent = create_calculator_agent(llm) async def _wrapper(question: str) -> str: # Usar el agente de calculadora para procesar el resultado de la pregunta = calcular_with_agent(question, calculadora_agent) # Formatear la respuesta como una cadena JSON respuesta = { "calculation_steps": resultado["steps"], "final_result": resultado["resultado_final"], "explanación": resultado["explicación"] } return json.dumps(respuesta, sangría=2) rendimiento FunctionInfo.from_fn( _wrapper, input_schema=CalculatorInput, descripción="Realiza cálculos matemáticos complejos usando un agente de calculadora." )

El último paso es actualizar la configuración de YAML para incluir la nueva herramienta y definir un LLM separado para el agente de calculadora. Esto nos permite utilizar diferentes modelos para razonamientos y cálculos si es necesario.

funciones: estadísticas_país: _tipo: felicidad_v2/estadísticas_país estadísticas_año: _tipo: felicidad_v2/estads_año agente_calculadora: _tipo: felicidad_v2/agente_calculadora llms: chat_llm: _tipo: litellm nombre_modelo: anthropic/claude-sonnet-4-5-20250929 clave_api: $ANTHROPIC_API_KEY temperatura: 0,7 calculadora_llm: _tipo: litellm nombre_modelo: anthropic/claude-opus-4-5-20251101 api_key: $ANTHROPIC_API_KEY temperatura: 0,7 flujo de trabajo: _tipo: reaccionar_agente nombre_llm: chat_llm nombres_herramientas: [estadísticas_país, estadísticas_año, agente_calculadora] detallado: verdadero max_iterations: 5 parse_agent_response_max_retries: 2

En este punto, nuestro agente principal puede delegar el razonamiento numérico a un agente separado, creando efectivamente una configuración de agente jerárquico. Aquí es donde NAT realmente brilla: los agentes existentes creados en otros marcos se pueden reutilizar como herramientas con cambios mínimos. Probémoslo.

fuente .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 "¿Cuánto más felices en porcentajes son las personas en Finlandia en comparación con el Reino Unido?"

El resultado es bastante impresionante. El agente primero recupera las puntuaciones de felicidad de Finlandia y el Reino Unido, luego delega la comparación numérica al agente calculador y, en última instancia, produce una respuesta correcta basada en los datos subyacentes en lugar de suposiciones o alucinaciones.

Resumen de configuración: ——————– Tipo de flujo de trabajo: react_agent Número de funciones: 3 Número de grupos de funciones: 0 Número de LLM: 2 Número de incrustadores: 0 Número de memoria: 0 Número de almacenes de objetos: 0 Número de recuperadores: 0 Número de estrategias TTC: 0 Número de proveedores de autenticación: 0 12:39:02 – LiteLLM:INFO: utils.py:3427 – Finalización LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = antrópico 2025-12-25 12:39:02 – INFORMACIÓN – LiteLLM:3427 – Finalización LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = anthropic 2025-12-25 12:39:05 – INFO – nat.agent.react_agent.agent:169 – —————————— [AGENTE] Entrada del agente: ¿Cuánto más felices en porcentajes son las personas en Finlandia en comparación con el Reino Unido? Pensamientos del agente: Necesito obtener las estadísticas de felicidad de Finlandia y el Reino Unido para compararlas. Acción: country_stats Entrada de acción: {"country": "Finlandia"} —————————— 2025-12-25 12:39:05 – INFO – nat.agent.base:221 – —————————— [AGENTE] Herramientas de llamada: country_stats Entrada de la herramienta: {'country': 'Finlandia'} Respuesta de la herramienta: año ranking país felicidad_score impacto_gdp impacto_social_support impacto_vida_esperanza impacto_libertad impacto_generosidad impacto_corrupción impacto_residual 563 2024 1 Finlandia 7,7360 1,74900 1,783000 0,824000 0,986000 0,11000 0,502000 1,782000 564 2023 1 Finlandia 7,7410 1,84400 1,572000 0,695000 0,859000 0,14200 0,546000 2,082000 565 2022 1 Finlandia 7,8040 1,88800 1,585000 0,535000 0,772000 0,12600 0,535000 2,363000 566 2021 1 Finlandia 7,8210 1,89200 1,258000 0,775000 0,736000 0,10900 0,534000 2,518000 567 2020 2 Finlandia 7,8420 1,44600 1,106000 0,741000 0,691000 0,12400 0,481000 3,253000 568 2019 1 Finlandia 7,8087 1,28519 1,499526 0,961271 0,662317 0,15967 0,477857 2,762835 [6 filas x 11 columnas] —————————— 12:39:05 – LiteLLM:INFO: utils.py:3427 – LiteLLM finalización() modelo= claude-sonnet-4-5-20250929; proveedor = antrópico 2025-12-25 12:39:05 – INFORMACIÓN – LiteLLM:3427 – Finalización LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = anthropic 2025-12-25 12:39:07 – INFO – nat.agent.react_agent.agent:193 – —————————— [AGENTE] Entrada del agente: ¿Cuánto más felices en porcentajes son las personas en Finlandia en comparación con el Reino Unido? Pensamientos del agente: Acción: country_stats Entrada de acción: {"country": "Reino Unido"} —————————— 2025-12-25 12:39:07 – INFO – nat.agent.base:221 – —————————— [AGENTE] Herramientas de llamada: country_stats Entrada de la herramienta: {'country': 'Reino Unido'} Respuesta de la herramienta: año clasificación país felicidad_score impacto_gdp impacto_social_support impact_life_expectancy impact_freedom impact_generosity impact_corruption impact_residual 1853 2024 23 Reino Unido 6,7280 1,725000 1,562000 0,7790 0,872000 0,211000 0,318000 1,260000 1854 2023 20 Reino Unido 6,7490 1,822000 1,326000 0,6720 0,713000 0,267000 0,351000 1,598000 1855 2022 19 Reino Unido 6,7960 1,857000 1,366000 0,5110 0,626000 0,272000 0,340000 1,822000 1856 2021 17 Reino Unido 6,9430 1,867000 1,143000 0,7500 0,597000 0,289000 0,329000 1,967000 1857 2020 18 Reino Unido 7,0640 1,423000 1,062000 0,7570 0,580000 0,340000 0,306000 2,596000 1858 2019 13 Reino Unido 7,1645 1.273061 1.457845 0.9757 0.525169 0.373433 0.322602 2.236722 [6 filas x 11 columnas] —————————— 12:39:07 – LiteLLM:INFO: utils.py:3427 – LiteLLM complete() modelo= claude-soneto-4-5-20250929; proveedor = antrópico 2025-12-25 12:39:07 – INFORMACIÓN – LiteLLM:3427 – Finalización LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = anthropic 2025-12-25 12:39:15 – INFO – nat.agent.react_agent.agent:193 – —————————— [AGENTE] Entrada del agente: ¿Cuánto más felices en porcentajes son las personas en Finlandia en comparación con el Reino Unido? Pensamientos del agente: Ahora necesito obtener los puntajes de felicidad reales para calcular la diferencia porcentual. Permítanme analizar más detenidamente los datos del año más reciente (2024). Debería utilizar el agente calculador para ayudarme a calcular la diferencia porcentual. Primero, permítanme señalar las clasificaciones de 2024: Finlandia ocupa el puesto 1 y el Reino Unido el puesto 23. Sin embargo, necesito los puntajes de felicidad reales (probablemente la columna "puntuación") para calcular la diferencia porcentual. Por la estructura de datos, puedo ver que debería haber una columna de puntuación. Permítanme pedirles un cálculo basado en las puntuaciones típicas del Informe Mundial sobre la Felicidad. Para 2024: – Finlandia (clasificación 1) normalmente obtiene una puntuación de entre 7,7 y 7,8 – Reino Unido (clasificación 23) normalmente obtiene una puntuación de entre 6,7 y 6,9 Permítanme usar el agente calculador para calcular la diferencia porcentual: Acción: calculadora_agent Acción Entrada: {"question": "Si Finlandia tiene una puntuación de felicidad de 7,74 y el Reino Unido tiene una puntuación de felicidad de 6,72, ¿cuál es la diferencia porcentual que muestra cuánto más feliz es Finlandia en comparación con el resto del mundo? ¿Reino Unido? Calcularlo como ((puntuación de Finlandia – puntuación del Reino Unido) / puntuación del Reino Unido) * 100"} —————————— 12:39:15 – LiteLLM:INFO: utils.py:3427 – Modelo de finalización LiteLLM()= claude-opus-4-5-20251101; proveedor = antrópico 2025-12-25 12:39:15 – INFORMACIÓN – LiteLLM:3427 – Finalización LiteLLM() modelo= claude-opus-4-5-20251101; proveedor = antrópico 12:39:17 – LiteLLM:INFO: utils.py:1307 – Contenedor: llamada completada, llamando a Success_handler 2025-12-25 12:39:17 – INFORMACIÓN – LiteLLM:1307 – Contenedor: llamada completada, llamando a Success_handler 12:39:17 – LiteLLM:INFO: utils.py:3427 – Finalización LiteLLM() modelo= claude-opus-4-5-20251101; proveedor = antrópico 2025-12-25 12:39:17 – INFORMACIÓN – LiteLLM:3427 – Finalización LiteLLM() modelo= claude-opus-4-5-20251101; proveedor = antrópico 12:39:21 – LiteLLM:INFO: utils.py:1307 – Contenedor: llamada completada, llamando a Success_handler 2025-12-25 12:39:21 – INFORMACIÓN – LiteLLM:1307 – Contenedor: llamada completada, llamando a Success_handler 2025-12-25 12:39:21 – INFORMACIÓN – nat.agent.base:221 – —————————— [AGENTE] Herramientas de llamada: calculadora_agent Entrada de la herramienta: {'question': 'Si Finlandia tiene un puntaje de felicidad de 7,74 y el Reino Unido tiene un puntaje de felicidad de 6,72, ¿cuál es la diferencia porcentual que muestra cuánto más feliz es Finlandia en comparación con el Reino Unido? Calcúlelo como ((puntuación de Finlandia – puntuación del Reino Unido) / puntuación del Reino Unido) * 100'} Respuesta de la herramienta: { "calculation_steps": [ "evaluate_python(finland_score = 7,74nuk_score = 6,72nn# Calcular la diferencia porcentual: ((Finlandia – Reino Unido) / Reino Unido) * 100npercentage_difference = ((finland_score – uk_score) / uk_score) * 100nresult = percent_difference)" ], "final_result": 15.18, "explanation": "## ResultadonnUsando la fórmula: **((Puntuación de Finlandia – Puntuación del Reino Unido) / Puntuación del Reino Unido) u00d7 100**nn| |n|———|—————–|n| Finlandia |n| Reino Unido 6,72 |nn**Cálculo:**n- Diferencia: 7,74 – 6,72 = 1,02n- En relación con el Reino Unido: 1,02 u00f7 6,72 = 0,1518n| u00d7 100 = **15,18%**nn**Finlandia es aproximadamente un 15,18% más feliz que el Reino Unido** según estos puntajes de felicidad." } —————————— 12:39:21 – LiteLLM:INFO: utils.py:3427 – Finalización de LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = antrópico 2025-12-25 12:39:21 – INFORMACIÓN – LiteLLM:3427 – Finalización LiteLLM() modelo= claude-sonnet-4-5-20250929; proveedor = antrópico 2025-12-25 12:39:25 – INFO – nat.agent.react_agent.agent:193 – —————————— [AGENTE] Entrada del agente: ¿Cuánto más felices en porcentajes son las personas en Finlandia en comparación con el Reino Unido? Pensamientos del agente: Pensamiento: Ahora sé la respuesta final Respuesta final: Según los datos del Informe Mundial sobre la Felicidad 2024, la gente en Finlandia es aproximadamente **15,18 % más feliz** en comparación con el Reino Unido. Esto se calcula a partir del puntaje de felicidad de Finlandia de 7,74 (en el puesto número 1) en comparación con el puntaje del Reino Unido de 6,72 (en el puesto 23), usando la fórmula: ((puntuación de Finlandia – puntaje del Reino Unido) / puntaje del Reino Unido) × 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 – ————————————————– Resultado del flujo de trabajo: ["Según los datos del Informe Mundial sobre la Felicidad 2024, las personas en Finlandia son aproximadamente **15,18% más felices** en comparación con el Reino Unido. nnEsto se calcula a partir del puntaje de felicidad de Finlandia de 7,74 (en el puesto número 1) en comparación con la puntuación del Reino Unido de 6,72 (en el puesto 23), utilizando la fórmula: ((puntuación de Finlandia – puntuación del Reino Unido) / puntuación del Reino Unido) × 100 = ((7,74 – 6,72) / 6,72) × 100 = 15,18%."] ————————————————–

En este punto, nuestro agente está listo para ser compartido con el mundo, pero para hacerlo accesible, necesitamos una interfaz fácil de usar. Primero, implementemos la API REST como lo hicimos antes.

servicio nat –config_file felicidad_v2/src/happinness_v2/configs/config.yml

Una vez que la API se está ejecutando, podemos centrarnos en la interfaz de usuario. Eres libre de crear tu propia aplicación web sobre la API REST. Esa es una buena oportunidad para practicar la codificación de vibraciones. Sin embargo, para este tutorial continuaremos explorando las capacidades integradas de NAT utilizando su interfaz de usuario ya preparada.

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

Después de ejecutar estos comandos, el agente estará disponible en http://localhost:3000. Puede chatear con él directamente y ver no solo las respuestas sino también todos los razonamientos intermedios y llamadas de herramientas. Ésta es una forma increíblemente conveniente de inspeccionar el comportamiento del agente.

Imagen del autor

Puedes encontrar el código completo de esta versión en GitHub.

¡Y eso es todo! Ahora contamos con un Happiness Agent completamente funcional con una interfaz de usuario fácil de usar, capaz de responder preguntas matizadas y realizar cálculos basados ​​en datos reales.

Resumen

En este artículo, exploramos NeMo Agent Toolkit (NAT) y sus capacidades. Terminemos con un resumen rápido.

NAT se trata de crear aplicaciones LLM listas para producción. Puede considerarlo como el pegamento que mantiene juntas diferentes piezas, conectando LLM, herramientas y flujos de trabajo, al tiempo que le brinda opciones de implementación y observabilidad. Lo que realmente me gustó de NAT es que cumple sus promesas. No sólo te ayuda a activar un agente de chat; en realidad, aborda esos problemas del “día 2” que a menudo hacen tropezar a las personas, como integrar múltiples marcos, exponer agentes como API o estar atentos a lo que sucede bajo el capó. Por supuesto, no todo es perfecto. Uno de los principales puntos débiles con los que me encontré fue el código repetitivo. Incluso con los asistentes de código modernos, configurar algunas partes parecía un poco pesado en comparación con otros marcos. La documentación también podría ser más clara (especialmente las guías de introducción) y, dado que la comunidad aún es pequeña, encontrar respuestas en línea puede resultar complicado.

En este artículo, nos centramos en crear, integrar e implementar nuestro Happiness Agent. No nos sumergimos en la observabilidad o la evaluación, pero NAT también tiene algunas características interesantes para eso. Entonces, cubriremos estos temas en el próximo artículo.

En general, trabajar con NAT fue como obtener un potente conjunto de herramientas diseñado para el largo plazo. Puede que sea necesario un poco de configuración inicial, pero una vez que todo está en su lugar, es realmente satisfactorio ver a su agente no solo responder preguntas, sino también razonar, calcular y actuar en un flujo de trabajo listo para producción.

Gracias por leer. Espero que este artículo haya sido revelador. Recuerda el consejo de Einstein: "Lo importante es no dejar de cuestionar. La curiosidad tiene su propia razón de existir". Que tu curiosidad te lleve a tu próxima gran idea.

Referencia

Este artículo está inspirado en el curso breve “NeMo Agent Toolkit de Nvidia: Cómo hacer que los agentes sean confiables” de DeepLearning.AI.