From 91cc1ded860ca909034692eda24fbd723f060293 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Tue, 4 Nov 2025 12:19:38 -0800 Subject: [PATCH 01/15] renumbering notebooks and add mcp notebook to unit tests Signed-off-by: Bryan Bednarski --- examples/README.md | 9 ++--- .../notebooks/2_bringing_your_own_agent.ipynb | 2 +- .../notebooks/3_adding_tools_to_agents.ipynb | 3 +- ...pynb => 4_mcp_setup_and_integration.ipynb} | 2 +- ...pynb => 5_multi_agent_orchestration.ipynb} | 2 +- ...ervability_evaluation_and_profiling.ipynb} | 11 ++++++ ...ipynb => 7_optimize_model_selection.ipynb} | 6 --- examples/notebooks/README.md | 8 ++-- .../notebooks/tests/test_notebooks_e2e.py | 37 ++++++++++++------- 9 files changed, 46 insertions(+), 34 deletions(-) rename examples/notebooks/{7_mcp_setup_and_integration.ipynb => 4_mcp_setup_and_integration.ipynb} (98%) rename examples/notebooks/{4_multi_agent_orchestration.ipynb => 5_multi_agent_orchestration.ipynb} (99%) rename examples/notebooks/{5_observability_evaluation_and_profiling.ipynb => 6_observability_evaluation_and_profiling.ipynb} (99%) rename examples/notebooks/{6_optimize_model_selection.ipynb => 7_optimize_model_selection.ipynb} (99%) diff --git a/examples/README.md b/examples/README.md index a85052e41..89e2185f5 100644 --- a/examples/README.md +++ b/examples/README.md @@ -119,11 +119,10 @@ To run the examples, install the NeMo Agent toolkit from source, if you haven't 1. [Getting Started](notebooks/1_getting_started_with_nat.ipynb) - Getting started with the NeMo Agent toolkit 2. [Bringing Your Own Agent](notebooks/2_bringing_your_own_agent.ipynb) - Bringing your own agent to the NeMo Agent toolkit 3. [Adding Tools and Agents](notebooks/3_adding_tools_to_agents.ipynb) - Adding tools to your agentic workflow -4. [Multi-Agent Orchestration](notebooks/4_multi_agent_orchestration.ipynb) - Setting up a multi-agent orchestration workflow -5. [Observability, Evaluation, and Profiling](notebooks/5_observability_evaluation_and_profiling.ipynb) - Instrumenting with observability, evaluation and profiling tools -6. [Optimizing Model Selection, Parameters, and Prompts](notebooks/6_optimize_model_selection.ipynb) - Use NAT Optimize to compare models, parameters, and prompt variations -7. [MCP Client and Servers Setup](notebooks/7_mcp_setup_and_integration.ipynb) - Deploy and integrate MCP clients and servers with NeMo Agent toolkit workflows - +4. [MCP Client and Servers Setup](notebooks/4_mcp_setup_and_integration.ipynb) - Deploy and integrate MCP clients and servers with NeMo Agent toolkit workflows +5. [Multi-Agent Orchestration](notebooks/5_multi_agent_orchestration.ipynb) - Setting up a multi-agent orchestration workflow +6. [Observability, Evaluation, and Profiling](notebooks/6_observability_evaluation_and_profiling.ipynb) - Instrumenting with observability, evaluation and profiling tools +7. [Optimizing Model Selection, Parameters, and Prompts](notebooks/7_optimize_model_selection.ipynb) - Use NAT Optimize to compare models, parameters, and prompt variations #### Brev Launchables diff --git a/examples/notebooks/2_bringing_your_own_agent.ipynb b/examples/notebooks/2_bringing_your_own_agent.ipynb index 0126389ed..c7aeb7870 100644 --- a/examples/notebooks/2_bringing_your_own_agent.ipynb +++ b/examples/notebooks/2_bringing_your_own_agent.ipynb @@ -857,7 +857,7 @@ "\n", "# 3.0) Next Steps\n", "\n", - "Next, look at \"Adding Tools to NeMo Agent Toolkit Agents\" where you will interactively learn how to create your own tools and agents with NAT." + "The next exercise in this series is `3_adding_tools_to_agents.ipynb` where you will interactively learn how to create your own tools and agents with NAT." ] } ], diff --git a/examples/notebooks/3_adding_tools_to_agents.ipynb b/examples/notebooks/3_adding_tools_to_agents.ipynb index 07d92b469..94001215e 100644 --- a/examples/notebooks/3_adding_tools_to_agents.ipynb +++ b/examples/notebooks/3_adding_tools_to_agents.ipynb @@ -1234,8 +1234,7 @@ "\n", "# 4.0) Next Steps\n", "\n", - "\n", - "What we've shown here are powerful concepts that allow agents to be integrated easily with other APIs, services, and institutional data sources. But once agents are equipped with the tools they need to properly address user queries, we begin to wonder how and where to draw the line between one agent and another, and the concept of multi-agent systems and multi-agent orchestration takes center stage. In the next notebook, we will show how easily multi-agent orchestration can be coordinated using NAT and also show a quick demo of multi-modal asset handling with NAT agents." + "In the next notebook in our series: `4_mcp_setup_and_integration.ipynb` we will demonstrate how distributed sets of tools can be hosted on MCP servers and used by MCP clients." ] } ], diff --git a/examples/notebooks/7_mcp_setup_and_integration.ipynb b/examples/notebooks/4_mcp_setup_and_integration.ipynb similarity index 98% rename from examples/notebooks/7_mcp_setup_and_integration.ipynb rename to examples/notebooks/4_mcp_setup_and_integration.ipynb index f7887bc9e..3a82e0238 100644 --- a/examples/notebooks/7_mcp_setup_and_integration.ipynb +++ b/examples/notebooks/4_mcp_setup_and_integration.ipynb @@ -1217,7 +1217,7 @@ "\n", "MCP servers follow the MCP protocol, and therefore can be used by any MCP client, not only NAT MCP clients. As a follow-up exercise, try connecting an MCP server to your Agentic IDE like VS Code GitHub co-pilot, Cursor, Windsurf or Claude Code.\n", "\n", - "Continue learning how to fully utilize the NVIDIA NeMo Agent toolkit by exploring the other documentation and advanced agents in the `examples` directory." + "Continue with the notebook series with `5_multi_agent_orchestration.ipynb`. Once agents are equipped with the tools they need to properly address user queries, we find a need to draw the line between one agent and another, and the concept of multi-agent systems and multi-agent orchestration takes center stage. In the next notebook, we will show how easily multi-agent orchestration can be coordinated using NAT and also show a quick demo of multi-modal asset handling with NAT agents." ] } ], diff --git a/examples/notebooks/4_multi_agent_orchestration.ipynb b/examples/notebooks/5_multi_agent_orchestration.ipynb similarity index 99% rename from examples/notebooks/4_multi_agent_orchestration.ipynb rename to examples/notebooks/5_multi_agent_orchestration.ipynb index 892deb8f6..f17497714 100644 --- a/examples/notebooks/4_multi_agent_orchestration.ipynb +++ b/examples/notebooks/5_multi_agent_orchestration.ipynb @@ -1882,7 +1882,7 @@ "\n", "# 4.0) Next Steps\n", "\n", - "The next notebook in this series is Tracing, Evaluating, and Profiling your Agent" + "The next notebook in this series is `6_observability_evaluation_and_profiling.ipynb` where we will demonstrate how to equip your agent with profiling instrumentation for improved observability over your platform." ] } ], diff --git a/examples/notebooks/5_observability_evaluation_and_profiling.ipynb b/examples/notebooks/6_observability_evaluation_and_profiling.ipynb similarity index 99% rename from examples/notebooks/5_observability_evaluation_and_profiling.ipynb rename to examples/notebooks/6_observability_evaluation_and_profiling.ipynb index 8e5653c3a..46e18db4d 100644 --- a/examples/notebooks/5_observability_evaluation_and_profiling.ipynb +++ b/examples/notebooks/6_observability_evaluation_and_profiling.ipynb @@ -47,6 +47,7 @@ " - [4.3) Running the Profiler](#run-profiler)\n", " - [4.4) Understanding Profiler Output Files](#understand-profiler-output-files)\n", "- [5.0) Notebook Summary](#summary)\n", + "- [6.0) Next Steps](#next-steps)\n", "\n", "Note: In Google Colab use the Table of Contents tab to navigate.\n" ] @@ -1881,6 +1882,16 @@ "source": [ "These three pillars—observability, evaluation, and profiling—work together to provide a complete picture of your agent's behavior, accuracy, and performance, enabling you to build production-ready AI applications with confidence." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# 6.0) Next steps\n", + "\n", + "Continue learning with the next notebook in our series: `7_optimize_model_selection.ipynb` where we will demonstrate how `nat optimize` can bne used to identify the best set of models, parameters, and prompts, for your use case." + ] } ], "metadata": { diff --git a/examples/notebooks/6_optimize_model_selection.ipynb b/examples/notebooks/7_optimize_model_selection.ipynb similarity index 99% rename from examples/notebooks/6_optimize_model_selection.ipynb rename to examples/notebooks/7_optimize_model_selection.ipynb index e726cbe5e..2549a4907 100644 --- a/examples/notebooks/6_optimize_model_selection.ipynb +++ b/examples/notebooks/7_optimize_model_selection.ipynb @@ -2030,12 +2030,6 @@ "\n", "Continue learning how to fully utilize the NVIDIA NeMo Agent toolkit by exploring the other documentation and advanced agents in the `examples` directory." ] - }, - { - "cell_type": "markdown", - "id": "ce0f363c", - "metadata": {}, - "source": [] } ], "metadata": { diff --git a/examples/notebooks/README.md b/examples/notebooks/README.md index a4db47507..e404001d9 100644 --- a/examples/notebooks/README.md +++ b/examples/notebooks/README.md @@ -24,10 +24,10 @@ We showcase the building blocks that make up the agentic system, including tools 1. [Getting Started](1_getting_started_with_nat.ipynb) - Getting started with the NeMo Agent toolkit 2. [Bringing Your Own Agent](2_bringing_your_own_agent.ipynb) - Bringing your own agent to the NeMo Agent toolkit 3. [Adding Tools and Agents](3_adding_tools_to_agents.ipynb) - Adding tools to your agentic workflow -4. [Multi-Agent Orchestration](4_multi_agent_orchestration.ipynb) - Setting up a multi-agent orchestration workflow -5. [Observability, Evaluation, and Profiling](5_observability_evaluation_and_profiling.ipynb) - Instrumenting with observability, evaluation and profiling tools -6. [Optimizing Model Selection, Parameters, and Prompts](6_optimize_model_selection.ipynb) - Use NAT Optimize to compare models, parameters, and prompt variations -7. [MCP Client and Servers Setup](7_mcp_setup_and_integration.ipynb) - Deploy and integrate MCP clients and servers with NeMo Agent toolkit workflows +4. [MCP Client and Servers Setup](4_mcp_setup_and_integration.ipynb) - Deploy and integrate MCP clients and servers with NeMo Agent toolkit workflows +5. [Multi-Agent Orchestration](5_multi_agent_orchestration.ipynb) - Setting up a multi-agent orchestration workflow +6. [Observability, Evaluation, and Profiling](6_observability_evaluation_and_profiling.ipynb) - Instrumenting with observability, evaluation and profiling tools +7. [Optimizing Model Selection, Parameters, and Prompts](7_optimize_model_selection.ipynb) - Use NAT Optimize to compare models, parameters, and prompt variations We recommend opening these notebooks in a Jupyter Lab environment or Google Colab environment. diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index bc7208250..d06f20a34 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import shutil import subprocess from pathlib import Path @@ -24,17 +25,19 @@ "second_agent_attempt", "third_agent_attempt", "retail_sales_agent", - "tmp_workflow" + "tmp_workflow", + "mcp_dev_workflow", + "nat_simple_calculator" ] # Other files produced by notebooks, relative to the notebooks directory, please keep this list sorted _OTHER_FILES = [ - "average_daily_revenue.png", # bar chart produced by notebooks 4 and 5 - # Descriptions of fictitious electronic devices used in RAG examples in notebooks 3, 4 and 5 + "average_daily_revenue.png", # bar chart produced by notebooks 5 and 6 + # Descriptions of fictitious electronic devices used in RAG examples in notebooks 3, 5 and 6 "data/rag/product_catalog.md", - # Retail sales data for devices described in data/rag/product_catalog.md used in notebooks 3, 4 and 5 + # Retail sales data for devices described in data/rag/product_catalog.md used in notebooks 3, 5 and 6 "data/retail_sales_data.csv", - # The `eval_output` files are output from evaluation in 5_observability_evaluation_and_profiling + # The `eval_output` files are output from evaluation in 6_observability_evaluation_and_profiling "eval_output/accuracy_output.json", "eval_output/groundedness_output.json", "eval_output/relevance_output.json", @@ -42,7 +45,7 @@ "eval_output/workflow_output.json", "langchain_agent.py", # Example existing agent being incorporated into NAT in 2_bringing_your_own_agent "nat_embedded.py", # Python script generated by 1_getting_started_with_nat, runs the workflow via the Python API - # The `profile_output` files are output from profiling in 5_observability_evaluation_and_profiling + # The `profile_output` files are output from profiling in 6_observability_evaluation_and_profiling "profile_output/all_requests_profiler_traces.json", "profile_output/gantt_chart.png", "profile_output/inference_optimization.json", @@ -50,9 +53,10 @@ "profile_output/workflow_output.json", "profile_output/workflow_profiling_metrics.json", "profile_output/workflow_profiling_report.txt", - "revenue_across_stores.png", # Chart produced by notebooks 4 and 5 - "sales_trend.png", # line chart produced by notebooks 4 and 5 + "revenue_across_stores.png", # Chart produced by notebooks 5 and 6 + "sales_trend.png", # line chart produced by notebooks 5 and 6 "search_agent.yml", # Workflow generated by 2_bringing_your_own_agent, uses Tavily to perform searches + "simple_calculator/", # Example code directory created by 4_mcp_setup_and_integration ] @@ -86,7 +90,10 @@ def _delete_other_files(notebooks_dir: Path): for file in _OTHER_FILES: file_path = notebooks_dir / file if file_path.exists(): - file_path.unlink() + if file_path.is_dir(): + shutil.rmtree(file_path) + else: + file_path.unlink() def _cleanup_all(notebooks_dir: Path): @@ -128,12 +135,14 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec [ pytest.param("1_getting_started_with_nat.ipynb", ["getting_started"], 120, id="1_getting_started_with_nat"), pytest.param("3_adding_tools_to_agents.ipynb", ["retail_sales_agent"], 300, id="3_adding_tools_to_agents"), - pytest.param("4_multi_agent_orchestration.ipynb", ["retail_sales_agent"], 120, - id="4_multi_agent_orchestration"), - pytest.param("5_observability_evaluation_and_profiling.ipynb", ["retail_sales_agent"], + pytest.param("4_mcp_setup_and_integration.ipynb", ["mcp_dev_workflow", "nat_simple_calculator"], 300, + id="4_mcp_setup_and_integration"), + pytest.param("5_multi_agent_orchestration.ipynb", ["retail_sales_agent"], 120, + id="5_multi_agent_orchestration"), + pytest.param("6_observability_evaluation_and_profiling.ipynb", ["retail_sales_agent"], 1000, - id="5_observability_evaluation_and_profiling"), - pytest.param("6_optimize_model_selection.ipynb", ["tmp_workflow"], 300, id="6_optimize_model_selection"), + id="6_observability_evaluation_and_profiling"), + pytest.param("7_optimize_model_selection.ipynb", ["tmp_workflow"], 300, id="7_optimize_model_selection"), ]) def test_notebooks(notebooks_dir: Path, notebook_file_name: str, expected_packages: list[str], timeout_seconds: int): _run_notebook(notebooks_dir / notebook_file_name, From 809d04d7c3de14611a6f4ac17dc7dbbd1e180677 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Tue, 4 Nov 2025 12:20:29 -0800 Subject: [PATCH 02/15] precommit Signed-off-by: Bryan Bednarski --- examples/notebooks/tests/test_notebooks_e2e.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index d06f20a34..e7b058496 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -135,7 +135,8 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec [ pytest.param("1_getting_started_with_nat.ipynb", ["getting_started"], 120, id="1_getting_started_with_nat"), pytest.param("3_adding_tools_to_agents.ipynb", ["retail_sales_agent"], 300, id="3_adding_tools_to_agents"), - pytest.param("4_mcp_setup_and_integration.ipynb", ["mcp_dev_workflow", "nat_simple_calculator"], 300, + pytest.param("4_mcp_setup_and_integration.ipynb", ["mcp_dev_workflow", "nat_simple_calculator"], + 300, id="4_mcp_setup_and_integration"), pytest.param("5_multi_agent_orchestration.ipynb", ["retail_sales_agent"], 120, id="5_multi_agent_orchestration"), From 84fd5ffad61999cafa7a7a505431852941d93daa Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Tue, 4 Nov 2025 12:40:36 -0800 Subject: [PATCH 03/15] typo Signed-off-by: Bryan Bednarski --- .../notebooks/6_observability_evaluation_and_profiling.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/notebooks/6_observability_evaluation_and_profiling.ipynb b/examples/notebooks/6_observability_evaluation_and_profiling.ipynb index 46e18db4d..90b4fc2a6 100644 --- a/examples/notebooks/6_observability_evaluation_and_profiling.ipynb +++ b/examples/notebooks/6_observability_evaluation_and_profiling.ipynb @@ -1890,7 +1890,7 @@ "\n", "# 6.0) Next steps\n", "\n", - "Continue learning with the next notebook in our series: `7_optimize_model_selection.ipynb` where we will demonstrate how `nat optimize` can bne used to identify the best set of models, parameters, and prompts, for your use case." + "Continue learning with the next notebook in our series: `7_optimize_model_selection.ipynb` where we will demonstrate how `nat optimize` can be used to identify the best set of models, parameters, and prompts, for your use case." ] } ], From 2fef69d5c1d2d600139ad884c06784823ebd2888 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Tue, 4 Nov 2025 18:38:35 -0800 Subject: [PATCH 04/15] renamed to remove numbers Signed-off-by: Bryan Bednarski --- examples/README.md | 14 +-- examples/notebooks/README.md | 14 +-- ...nts.ipynb => adding_tools_to_agents.ipynb} | 0 ...nt.ipynb => bringing_your_own_agent.ipynb} | 0 ...t.ipynb => getting_started_with_nat.ipynb} | 0 ....ipynb => mcp_setup_and_integration.ipynb} | 115 ++++++++++++++---- ....ipynb => multi_agent_orchestration.ipynb} | 0 ...ervability_evaluation_and_profiling.ipynb} | 0 ...n.ipynb => optimize_model_selection.ipynb} | 0 .../notebooks/tests/test_notebooks_e2e.py | 30 ++--- 10 files changed, 123 insertions(+), 50 deletions(-) rename examples/notebooks/{3_adding_tools_to_agents.ipynb => adding_tools_to_agents.ipynb} (100%) rename examples/notebooks/{2_bringing_your_own_agent.ipynb => bringing_your_own_agent.ipynb} (100%) rename examples/notebooks/{1_getting_started_with_nat.ipynb => getting_started_with_nat.ipynb} (100%) rename examples/notebooks/{4_mcp_setup_and_integration.ipynb => mcp_setup_and_integration.ipynb} (92%) rename examples/notebooks/{5_multi_agent_orchestration.ipynb => multi_agent_orchestration.ipynb} (100%) rename examples/notebooks/{6_observability_evaluation_and_profiling.ipynb => observability_evaluation_and_profiling.ipynb} (100%) rename examples/notebooks/{7_optimize_model_selection.ipynb => optimize_model_selection.ipynb} (100%) diff --git a/examples/README.md b/examples/README.md index 89e2185f5..85ab47768 100644 --- a/examples/README.md +++ b/examples/README.md @@ -116,13 +116,13 @@ To run the examples, install the NeMo Agent toolkit from source, if you haven't [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NVIDIA/NeMo-Agent-Toolkit/) -1. [Getting Started](notebooks/1_getting_started_with_nat.ipynb) - Getting started with the NeMo Agent toolkit -2. [Bringing Your Own Agent](notebooks/2_bringing_your_own_agent.ipynb) - Bringing your own agent to the NeMo Agent toolkit -3. [Adding Tools and Agents](notebooks/3_adding_tools_to_agents.ipynb) - Adding tools to your agentic workflow -4. [MCP Client and Servers Setup](notebooks/4_mcp_setup_and_integration.ipynb) - Deploy and integrate MCP clients and servers with NeMo Agent toolkit workflows -5. [Multi-Agent Orchestration](notebooks/5_multi_agent_orchestration.ipynb) - Setting up a multi-agent orchestration workflow -6. [Observability, Evaluation, and Profiling](notebooks/6_observability_evaluation_and_profiling.ipynb) - Instrumenting with observability, evaluation and profiling tools -7. [Optimizing Model Selection, Parameters, and Prompts](notebooks/7_optimize_model_selection.ipynb) - Use NAT Optimize to compare models, parameters, and prompt variations +1. [Getting Started](notebooks/getting_started_with_nat.ipynb) - Getting started with the NeMo Agent toolkit +2. [Bringing Your Own Agent](notebooks/bringing_your_own_agent.ipynb) - Bringing your own agent to the NeMo Agent toolkit +3. [Adding Tools and Agents](notebooks/adding_tools_to_agents.ipynb) - Adding tools to your agentic workflow +4. [MCP Client and Servers Setup](notebooks/mcp_setup_and_integration.ipynb) - Deploy and integrate MCP clients and servers with NeMo Agent toolkit workflows +5. [Multi-Agent Orchestration](notebooks/multi_agent_orchestration.ipynb) - Setting up a multi-agent orchestration workflow +6. [Observability, Evaluation, and Profiling](notebooks/observability_evaluation_and_profiling.ipynb) - Instrumenting with observability, evaluation and profiling tools +7. [Optimizing Model Selection, Parameters, and Prompts](notebooks/optimize_model_selection.ipynb) - Use NAT Optimize to compare models, parameters, and prompt variations #### Brev Launchables diff --git a/examples/notebooks/README.md b/examples/notebooks/README.md index e404001d9..4b1bbbb5f 100644 --- a/examples/notebooks/README.md +++ b/examples/notebooks/README.md @@ -21,13 +21,13 @@ Through this series of notebooks, we demonstrate how you can use the NVIDIA NeMo We showcase the building blocks that make up the agentic system, including tools, agents, workflows, and observability. -1. [Getting Started](1_getting_started_with_nat.ipynb) - Getting started with the NeMo Agent toolkit -2. [Bringing Your Own Agent](2_bringing_your_own_agent.ipynb) - Bringing your own agent to the NeMo Agent toolkit -3. [Adding Tools and Agents](3_adding_tools_to_agents.ipynb) - Adding tools to your agentic workflow -4. [MCP Client and Servers Setup](4_mcp_setup_and_integration.ipynb) - Deploy and integrate MCP clients and servers with NeMo Agent toolkit workflows -5. [Multi-Agent Orchestration](5_multi_agent_orchestration.ipynb) - Setting up a multi-agent orchestration workflow -6. [Observability, Evaluation, and Profiling](6_observability_evaluation_and_profiling.ipynb) - Instrumenting with observability, evaluation and profiling tools -7. [Optimizing Model Selection, Parameters, and Prompts](7_optimize_model_selection.ipynb) - Use NAT Optimize to compare models, parameters, and prompt variations +1. [Getting Started](getting_started_with_nat.ipynb) - Getting started with the NeMo Agent toolkit +2. [Bringing Your Own Agent](bringing_your_own_agent.ipynb) - Bringing your own agent to the NeMo Agent toolkit +3. [Adding Tools and Agents](adding_tools_to_agents.ipynb) - Adding tools to your agentic workflow +4. [MCP Client and Servers Setup](mcp_setup_and_integration.ipynb) - Deploy and integrate MCP clients and servers with NeMo Agent toolkit workflows +5. [Multi-Agent Orchestration](multi_agent_orchestration.ipynb) - Setting up a multi-agent orchestration workflow +6. [Observability, Evaluation, and Profiling](observability_evaluation_and_profiling.ipynb) - Instrumenting with observability, evaluation and profiling tools +7. [Optimizing Model Selection, Parameters, and Prompts](optimize_model_selection.ipynb) - Use NAT Optimize to compare models, parameters, and prompt variations We recommend opening these notebooks in a Jupyter Lab environment or Google Colab environment. diff --git a/examples/notebooks/3_adding_tools_to_agents.ipynb b/examples/notebooks/adding_tools_to_agents.ipynb similarity index 100% rename from examples/notebooks/3_adding_tools_to_agents.ipynb rename to examples/notebooks/adding_tools_to_agents.ipynb diff --git a/examples/notebooks/2_bringing_your_own_agent.ipynb b/examples/notebooks/bringing_your_own_agent.ipynb similarity index 100% rename from examples/notebooks/2_bringing_your_own_agent.ipynb rename to examples/notebooks/bringing_your_own_agent.ipynb diff --git a/examples/notebooks/1_getting_started_with_nat.ipynb b/examples/notebooks/getting_started_with_nat.ipynb similarity index 100% rename from examples/notebooks/1_getting_started_with_nat.ipynb rename to examples/notebooks/getting_started_with_nat.ipynb diff --git a/examples/notebooks/4_mcp_setup_and_integration.ipynb b/examples/notebooks/mcp_setup_and_integration.ipynb similarity index 92% rename from examples/notebooks/4_mcp_setup_and_integration.ipynb rename to examples/notebooks/mcp_setup_and_integration.ipynb index 3a82e0238..b5920f2d3 100644 --- a/examples/notebooks/4_mcp_setup_and_integration.ipynb +++ b/examples/notebooks/mcp_setup_and_integration.ipynb @@ -196,6 +196,17 @@ "fi" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "4de74aa0", + "metadata": {}, + "outputs": [], + "source": [ + "# install tomli-w to edit pyproject.toml and rename the package\n", + "!uv pip install tomli-w" + ] + }, { "cell_type": "markdown", "id": "00419290", @@ -222,6 +233,56 @@ " import subprocess\n", " from pathlib import Path\n", "\n", + " def rename_package_in_pyproject(pyproject_path: Path, suffix: str = \"_notebook\") -> str:\n", + " \"\"\"\n", + " Rename the package in pyproject.toml to avoid conflicts with existing installations.\n", + " \n", + " Args:\n", + " pyproject_path: Path to the pyproject.toml file\n", + " suffix: Suffix to append to the package name\n", + " \n", + " Returns:\n", + " The new package name, or None if renaming failed\n", + " \"\"\"\n", + " try:\n", + " # Try Python 3.11+ built-in tomllib first\n", + " try:\n", + " import tomllib as tomli\n", + " except ImportError:\n", + " import tomli\n", + " import tomli_w\n", + " except ImportError:\n", + " print(\"Warning: Could not import toml library, package name will not be modified\")\n", + " return None\n", + " \n", + " try:\n", + " # Read the current pyproject.toml\n", + " with open(pyproject_path, 'rb') as f:\n", + " config = tomli.load(f)\n", + " \n", + " # Get the original package name\n", + " original_name = config.get('project', {}).get('name')\n", + " if not original_name:\n", + " print(\"Warning: No package name found in pyproject.toml\")\n", + " return None\n", + " \n", + " # Create new unique name\n", + " new_name = f\"{original_name}{suffix}\"\n", + " \n", + " # Update the package name\n", + " config['project']['name'] = new_name\n", + " \n", + " # Write back to pyproject.toml\n", + " with open(pyproject_path, 'wb') as f:\n", + " tomli_w.dump(config, f)\n", + " \n", + " print(f\"✓ Renamed package from '{original_name}' to '{new_name}' to avoid conflicts\")\n", + " return new_name\n", + " \n", + " except Exception as e:\n", + " print(f\"Warning: Could not modify package name: {e}\")\n", + " return None\n", + "\n", " # Detect if running in Colab\n", " try:\n", " import google.colab # type: ignore # noqa: F401\n", @@ -287,9 +348,16 @@ " # Optional: Install dependencies if there's a pyproject.toml\n", " pyproject_file = dest_path / \"pyproject.toml\"\n", " if pyproject_file.exists():\n", + " # Rename package to avoid conflicts\n", + " new_name = rename_package_in_pyproject(pyproject_file)\n", + " \n", " print(\"\\nInstalling example package in editable mode...\")\n", " get_ipython().system(f'pip install --no-deps -e {dest_path}')\n", - " print(f\"✓ Installed package from: {dest_path}\")\n", + " \n", + " if new_name:\n", + " print(f\"✓ Installed package as '{new_name}' from: {dest_path}\")\n", + " else:\n", + " print(f\"✓ Installed package from: {dest_path}\")\n", "\n", " print(f\"\\nYou can now edit the files in: {dest_path}\")\n", " else:\n", @@ -336,10 +404,18 @@ " # Install the example package\n", " pyproject_file = example_path / \"pyproject.toml\"\n", " if pyproject_file.exists():\n", + " # Rename package to avoid conflicts\n", + " new_name = rename_package_in_pyproject(pyproject_file)\n", + " \n", " print(\"\\nInstalling example package in editable mode...\")\n", " print(f\"Installing from: {example_path}\")\n", - " get_ipython().system(f'pip install --no-deps -e {example_path}')\n", - " print(\"✓ Installed package\")\n", + " # get_ipython().system(f'pip install --no-deps -e {example_path}')\n", + " get_ipython().system(f'pip install --no-deps {example_path}') # remove editable mode so that nat workflow delete works\n", + " \n", + " if new_name:\n", + " print(f\"✓ Installed package as '{new_name}'\")\n", + " else:\n", + " print(\"✓ Installed package\")\n", "\n", " # Get the example folder name\n", " example_name = Path(example_code_path).name\n", @@ -969,17 +1045,6 @@ "When you serve a workflow that includes an `mcp_client` function group, the NeMo Agent toolkit exposes an HTTP endpoint to inspect the tools configured on the client side and whether each tool is available on the connected server. We can inspect this workflow and as follows:" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "22754f85", - "metadata": {}, - "outputs": [], - "source": [ - "# let's kill anything using port 8000 in case it's already running\n", - "!lsof -ti:8000 | xargs kill -9" - ] - }, { "cell_type": "code", "execution_count": null, @@ -1005,6 +1070,14 @@ " --name \"My MCP Server\"" ] }, + { + "cell_type": "markdown", + "id": "b5d33205", + "metadata": {}, + "source": [ + "Wait about 10 seconds before running the next cell..." + ] + }, { "cell_type": "markdown", "id": "4c34f7ed", @@ -1024,11 +1097,14 @@ ] }, { - "cell_type": "markdown", - "id": "b5d33205", + "cell_type": "code", + "execution_count": null, + "id": "22754f85", "metadata": {}, + "outputs": [], "source": [ - "Wait about 10 seconds before running the next cell..." + "# let's kill anything using port 8000 in case it's already running\n", + "!lsof -ti:8000 | xargs kill -9" ] }, { @@ -1039,10 +1115,7 @@ "outputs": [], "source": [ "%%bash --bg\n", - "nat serve --config_file ./mcp_dev_workflow/configs/mcp_config.yml \\\n", - " --host 0.0.0.0 \\\n", - " --port 8000 \\\n", - " --name \"My MCP Client\"" + "nat serve --config_file ./mcp_dev_workflow/configs/mcp_config.yml" ] }, { diff --git a/examples/notebooks/5_multi_agent_orchestration.ipynb b/examples/notebooks/multi_agent_orchestration.ipynb similarity index 100% rename from examples/notebooks/5_multi_agent_orchestration.ipynb rename to examples/notebooks/multi_agent_orchestration.ipynb diff --git a/examples/notebooks/6_observability_evaluation_and_profiling.ipynb b/examples/notebooks/observability_evaluation_and_profiling.ipynb similarity index 100% rename from examples/notebooks/6_observability_evaluation_and_profiling.ipynb rename to examples/notebooks/observability_evaluation_and_profiling.ipynb diff --git a/examples/notebooks/7_optimize_model_selection.ipynb b/examples/notebooks/optimize_model_selection.ipynb similarity index 100% rename from examples/notebooks/7_optimize_model_selection.ipynb rename to examples/notebooks/optimize_model_selection.ipynb diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index e7b058496..a2a8f69f6 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -56,7 +56,7 @@ "revenue_across_stores.png", # Chart produced by notebooks 5 and 6 "sales_trend.png", # line chart produced by notebooks 5 and 6 "search_agent.yml", # Workflow generated by 2_bringing_your_own_agent, uses Tavily to perform searches - "simple_calculator/", # Example code directory created by 4_mcp_setup_and_integration + # "simple_calculator/", # Example code directory created by 4_mcp_setup_and_integration ] @@ -90,10 +90,10 @@ def _delete_other_files(notebooks_dir: Path): for file in _OTHER_FILES: file_path = notebooks_dir / file if file_path.exists(): - if file_path.is_dir(): - shutil.rmtree(file_path) - else: - file_path.unlink() + # if file_path.is_dir(): + # shutil.rmtree(file_path) + # else: + file_path.unlink() def _cleanup_all(notebooks_dir: Path): @@ -133,17 +133,17 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec @pytest.mark.parametrize( "notebook_file_name, expected_packages, timeout_seconds", [ - pytest.param("1_getting_started_with_nat.ipynb", ["getting_started"], 120, id="1_getting_started_with_nat"), - pytest.param("3_adding_tools_to_agents.ipynb", ["retail_sales_agent"], 300, id="3_adding_tools_to_agents"), - pytest.param("4_mcp_setup_and_integration.ipynb", ["mcp_dev_workflow", "nat_simple_calculator"], + pytest.param("getting_started_with_nat.ipynb", ["getting_started"], 120, id="getting_started_with_nat"), + pytest.param("adding_tools_to_agents.ipynb", ["retail_sales_agent"], 300, id="adding_tools_to_agents"), + pytest.param("mcp_setup_and_integration.ipynb", ["mcp_dev_workflow", "nat_simple_calculator_notebook"], 300, - id="4_mcp_setup_and_integration"), - pytest.param("5_multi_agent_orchestration.ipynb", ["retail_sales_agent"], 120, - id="5_multi_agent_orchestration"), - pytest.param("6_observability_evaluation_and_profiling.ipynb", ["retail_sales_agent"], + id="mcp_setup_and_integration"), + pytest.param("multi_agent_orchestration.ipynb", ["retail_sales_agent"], 120, + id="multi_agent_orchestration"), + pytest.param("observability_evaluation_and_profiling.ipynb", ["retail_sales_agent"], 1000, - id="6_observability_evaluation_and_profiling"), - pytest.param("7_optimize_model_selection.ipynb", ["tmp_workflow"], 300, id="7_optimize_model_selection"), + id="observability_evaluation_and_profiling"), + pytest.param("optimize_model_selection.ipynb", ["tmp_workflow"], 300, id="optimize_model_selection"), ]) def test_notebooks(notebooks_dir: Path, notebook_file_name: str, expected_packages: list[str], timeout_seconds: int): _run_notebook(notebooks_dir / notebook_file_name, @@ -156,5 +156,5 @@ def test_notebooks(notebooks_dir: Path, notebook_file_name: str, expected_packag @pytest.mark.usefixtures("nvidia_api_key", "tavily_api_key") def test_2_bringing_your_own_agent(notebooks_dir: Path): # This test is the same as the others but requires a Tavily API key to run - _run_notebook(notebooks_dir / "2_bringing_your_own_agent.ipynb", + _run_notebook(notebooks_dir / "bringing_your_own_agent.ipynb", expected_packages=["first_agent_attempt", "second_agent_attempt", "third_agent_attempt"]) From ba364e1a21fa94bf8f5a2216a1bcc2f11dba6c2c Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Tue, 4 Nov 2025 20:33:48 -0800 Subject: [PATCH 05/15] unit test support for mcp notebook Signed-off-by: Bryan Bednarski --- .../notebooks/mcp_setup_and_integration.ipynb | 72 +++++++++++++------ .../notebooks/tests/test_notebooks_e2e.py | 10 +-- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/examples/notebooks/mcp_setup_and_integration.ipynb b/examples/notebooks/mcp_setup_and_integration.ipynb index b5920f2d3..85e8bf276 100644 --- a/examples/notebooks/mcp_setup_and_integration.ipynb +++ b/examples/notebooks/mcp_setup_and_integration.ipynb @@ -303,7 +303,9 @@ " print(\" - Enter a branch name (e.g., 'develop', 'main') to clone and install\")\n", " print(\"=\" * 60)\n", "\n", - " branch_name = input(\"\\nEnter your choice: \").strip()\n", + " branch_name = os.getenv(\"NAT_NOTEBOOK_INSTALL_MODE\", \"\").strip()\n", + " if not branch_name:\n", + " branch_name = input(\"\\nEnter your choice: \").strip()\n", "\n", " # Default to 'main' if empty\n", " if not branch_name:\n", @@ -499,13 +501,23 @@ "id": "c8e1c22d", "metadata": {}, "source": [ - "Wait about 10 seconds before running the next cell...\n", - "\n", "The `--bg` command will run your server in the background of the notebook, so you might not see confirmation that the server is running. To see the startup logs, you can remove this flag and run the cell again. However, subsequent steps require the server to be run as a background process.\n", "\n", "Next, we will list the set of available tools from `simple_calculator` MCP server." ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "c2d15d0d", + "metadata": {}, + "outputs": [], + "source": [ + "# Wait about 10 seconds before running the next cell...\n", + "import time\n", + "time.sleep(10)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -513,8 +525,8 @@ "metadata": {}, "outputs": [], "source": [ - "# For streamable-http transport (default)\n", - "!nat mcp client tool list --url http://localhost:9901/mcp" + "%%bash\n", + "nat mcp client tool list --url http://localhost:9901/mcp" ] }, { @@ -572,11 +584,15 @@ ] }, { - "cell_type": "markdown", - "id": "9b013a00", + "cell_type": "code", + "execution_count": null, + "id": "111c81a7", "metadata": {}, + "outputs": [], "source": [ - "Wait about 10 seconds before running the next cell..." + "# Wait about 10 seconds before running the next cell...\n", + "import time\n", + "time.sleep(10)" ] }, { @@ -629,11 +645,15 @@ ] }, { - "cell_type": "markdown", - "id": "664a9ed6", + "cell_type": "code", + "execution_count": null, + "id": "7ce2eebb", "metadata": {}, + "outputs": [], "source": [ - "Wait about 10 seconds before running the next cell..." + "# Wait about 10 seconds before running the next cell...\n", + "import time\n", + "time.sleep(10)" ] }, { @@ -954,11 +974,15 @@ ] }, { - "cell_type": "markdown", - "id": "feae920e", + "cell_type": "code", + "execution_count": null, + "id": "b7efca58", "metadata": {}, + "outputs": [], "source": [ - "Wait about 10 seconds before running the next cell..." + "# Wait about 10 seconds before running the next cell...\n", + "import time\n", + "time.sleep(10)" ] }, { @@ -1071,11 +1095,15 @@ ] }, { - "cell_type": "markdown", - "id": "b5d33205", + "cell_type": "code", + "execution_count": null, + "id": "7dc57c53", "metadata": {}, + "outputs": [], "source": [ - "Wait about 10 seconds before running the next cell..." + "# Wait about 10 seconds before running the next cell...\n", + "import time\n", + "time.sleep(10)" ] }, { @@ -1119,11 +1147,15 @@ ] }, { - "cell_type": "markdown", - "id": "4835e115", + "cell_type": "code", + "execution_count": null, + "id": "cc1de7ca", "metadata": {}, + "outputs": [], "source": [ - "Wait about 10 seconds before running the next cell..." + "# Wait about 10 seconds before running the next cell...\n", + "import time\n", + "time.sleep(10)" ] }, { diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index a2a8f69f6..cf710e5b3 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -13,9 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import shutil import subprocess from pathlib import Path +import os import pytest @@ -90,9 +90,6 @@ def _delete_other_files(notebooks_dir: Path): for file in _OTHER_FILES: file_path = notebooks_dir / file if file_path.exists(): - # if file_path.is_dir(): - # shutil.rmtree(file_path) - # else: file_path.unlink() @@ -118,9 +115,12 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec str(notebook_path.absolute()), ] + env = os.environ.copy() + env["NAT_NOTEBOOK_INSTALL_MODE"] = "local" + # Ideally if the notebook times out we want jupyter to catch it and exit gracefully with the most informative error # possible. However in the potential situation where jupyter itself hangs, we add a 10s buffer to the timeout. - result = subprocess.run(cmd, check=False, capture_output=True, text=True, timeout=timeout_seconds + 10) + result = subprocess.run(cmd, check=False, capture_output=True, text=True, timeout=timeout_seconds + 10, env=env) assert result.returncode == 0, f"Notebook execution failed:\n{result.stderr}" for package in expected_packages: From 0aec5d4f52839b061f114fbe46a60cbde2f52e30 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 10:24:49 -0800 Subject: [PATCH 06/15] cleanup for unit tests Signed-off-by: Bryan Bednarski --- .../notebooks/adding_tools_to_agents.ipynb | 2 +- .../notebooks/bringing_your_own_agent.ipynb | 2 +- .../notebooks/getting_started_with_nat.ipynb | 2 +- .../notebooks/mcp_setup_and_integration.ipynb | 28 +++++++++++-------- .../notebooks/multi_agent_orchestration.ipynb | 2 +- ...servability_evaluation_and_profiling.ipynb | 2 +- .../notebooks/tests/test_notebooks_e2e.py | 4 +-- 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/examples/notebooks/adding_tools_to_agents.ipynb b/examples/notebooks/adding_tools_to_agents.ipynb index 94001215e..65c9a8723 100644 --- a/examples/notebooks/adding_tools_to_agents.ipynb +++ b/examples/notebooks/adding_tools_to_agents.ipynb @@ -1234,7 +1234,7 @@ "\n", "# 4.0) Next Steps\n", "\n", - "In the next notebook in our series: `4_mcp_setup_and_integration.ipynb` we will demonstrate how distributed sets of tools can be hosted on MCP servers and used by MCP clients." + "In the next notebook in our series: `mcp_setup_and_integration.ipynb` we will demonstrate how distributed sets of tools can be hosted on MCP servers and used by MCP clients." ] } ], diff --git a/examples/notebooks/bringing_your_own_agent.ipynb b/examples/notebooks/bringing_your_own_agent.ipynb index c7aeb7870..e380b41ab 100644 --- a/examples/notebooks/bringing_your_own_agent.ipynb +++ b/examples/notebooks/bringing_your_own_agent.ipynb @@ -857,7 +857,7 @@ "\n", "# 3.0) Next Steps\n", "\n", - "The next exercise in this series is `3_adding_tools_to_agents.ipynb` where you will interactively learn how to create your own tools and agents with NAT." + "The next exercise in this series is `adding_tools_to_agents.ipynb` where you will interactively learn how to create your own tools and agents with NAT." ] } ], diff --git a/examples/notebooks/getting_started_with_nat.ipynb b/examples/notebooks/getting_started_with_nat.ipynb index 16769269c..068eb6352 100644 --- a/examples/notebooks/getting_started_with_nat.ipynb +++ b/examples/notebooks/getting_started_with_nat.ipynb @@ -591,7 +591,7 @@ "\n", "# 3.0) Next Steps\n", "\n", - "If you already have agents codified and don't need NAT to bring up your first agent, we also support bringing existing agents into the NAT framework. In the next notebook of this series, \\\"Bringing Your Own Agent into NeMo Agent Toolkit\\\" (2_bringing_your_own_agent.ipynb), we will walk you through adapting existing agents into NAT." + "If you already have agents codified and don't need NAT to bring up your first agent, we also support bringing existing agents into the NAT framework. In the next notebook of this series, `bringing_your_own_agent.ipynb`, we will walk you through adapting existing agents into NAT." ] } ], diff --git a/examples/notebooks/mcp_setup_and_integration.ipynb b/examples/notebooks/mcp_setup_and_integration.ipynb index 85e8bf276..e334f5683 100644 --- a/examples/notebooks/mcp_setup_and_integration.ipynb +++ b/examples/notebooks/mcp_setup_and_integration.ipynb @@ -204,7 +204,7 @@ "outputs": [], "source": [ "# install tomli-w to edit pyproject.toml and rename the package\n", - "!uv pip install tomli-w" + "!uv pip install tomli tomli-w" ] }, { @@ -335,7 +335,7 @@ "\n", " # Get the example folder name (e.g., \"simple_calculator\")\n", " example_name = Path(example_code_path).name\n", - " dest_path = base_path / example_name\n", + " dest_path = base_path / f\"{example_name}_notebook\"\n", "\n", " if source_path.exists():\n", " # Remove destination if it already exists\n", @@ -429,13 +429,18 @@ " print(f\" {example_path / 'configs/config.yml'}\")\n", "\n", " # Optionally copy configs to working directory for easy access\n", - " if in_colab:\n", - " dest_path = base_path / example_name\n", - " if dest_path.exists():\n", - " shutil.rmtree(dest_path)\n", - " shutil.copytree(example_path, dest_path)\n", - " print(f\"\\nAlso copied example to: {dest_path}\")\n", - " print(f\"Use configs from: {dest_path / 'configs/config.yml'}\")\n", + " dest_path = base_path / f\"{example_name}_notebook\"\n", + " if dest_path.exists():\n", + " shutil.rmtree(dest_path)\n", + " shutil.copytree(example_path, dest_path)\n", + " print(f\"\\nAlso copied example to: {dest_path}\")\n", + " print(f\"Use configs from: {dest_path / 'configs/config.yml'}\")\n", + "\n", + " # Remove existing repo if it exists\n", + " if repo_path.exists():\n", + " print(f\"Removing existing repository at: {repo_path}\")\n", + " shutil.rmtree(repo_path)\n", + "\n", "\n", " except subprocess.CalledProcessError as e:\n", " print(f\"✗ Error cloning repository: {e.stderr}\")\n", @@ -525,8 +530,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%bash\n", - "nat mcp client tool list --url http://localhost:9901/mcp" + "!nat mcp client tool list --url http://localhost:9901/mcp" ] }, { @@ -1322,7 +1326,7 @@ "\n", "MCP servers follow the MCP protocol, and therefore can be used by any MCP client, not only NAT MCP clients. As a follow-up exercise, try connecting an MCP server to your Agentic IDE like VS Code GitHub co-pilot, Cursor, Windsurf or Claude Code.\n", "\n", - "Continue with the notebook series with `5_multi_agent_orchestration.ipynb`. Once agents are equipped with the tools they need to properly address user queries, we find a need to draw the line between one agent and another, and the concept of multi-agent systems and multi-agent orchestration takes center stage. In the next notebook, we will show how easily multi-agent orchestration can be coordinated using NAT and also show a quick demo of multi-modal asset handling with NAT agents." + "Continue with the notebook series with `multi_agent_orchestration.ipynb`. Once agents are equipped with the tools they need to properly address user queries, we find a need to draw the line between one agent and another, and the concept of multi-agent systems and multi-agent orchestration takes center stage. In the next notebook, we will show how easily multi-agent orchestration can be coordinated using NAT and also show a quick demo of multi-modal asset handling with NAT agents." ] } ], diff --git a/examples/notebooks/multi_agent_orchestration.ipynb b/examples/notebooks/multi_agent_orchestration.ipynb index f17497714..c273b988a 100644 --- a/examples/notebooks/multi_agent_orchestration.ipynb +++ b/examples/notebooks/multi_agent_orchestration.ipynb @@ -1882,7 +1882,7 @@ "\n", "# 4.0) Next Steps\n", "\n", - "The next notebook in this series is `6_observability_evaluation_and_profiling.ipynb` where we will demonstrate how to equip your agent with profiling instrumentation for improved observability over your platform." + "The next notebook in this series is `observability_evaluation_and_profiling.ipynb` where we will demonstrate how to equip your agent with profiling instrumentation for improved observability over your platform." ] } ], diff --git a/examples/notebooks/observability_evaluation_and_profiling.ipynb b/examples/notebooks/observability_evaluation_and_profiling.ipynb index 90b4fc2a6..868c930c9 100644 --- a/examples/notebooks/observability_evaluation_and_profiling.ipynb +++ b/examples/notebooks/observability_evaluation_and_profiling.ipynb @@ -1890,7 +1890,7 @@ "\n", "# 6.0) Next steps\n", "\n", - "Continue learning with the next notebook in our series: `7_optimize_model_selection.ipynb` where we will demonstrate how `nat optimize` can be used to identify the best set of models, parameters, and prompts, for your use case." + "Continue learning with the next notebook in our series: `optimize_model_selection.ipynb` where we will demonstrate how `nat optimize` can be used to identify the best set of models, parameters, and prompts, for your use case." ] } ], diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index cf710e5b3..8c73f112d 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -27,7 +27,7 @@ "retail_sales_agent", "tmp_workflow", "mcp_dev_workflow", - "nat_simple_calculator" + "simple_calculator_notebook" ] # Other files produced by notebooks, relative to the notebooks directory, please keep this list sorted @@ -116,7 +116,7 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec ] env = os.environ.copy() - env["NAT_NOTEBOOK_INSTALL_MODE"] = "local" + env["NAT_NOTEBOOK_INSTALL_MODE"] = "develop" # Ideally if the notebook times out we want jupyter to catch it and exit gracefully with the most informative error # possible. However in the potential situation where jupyter itself hangs, we add a 10s buffer to the timeout. From 5685d178ddb38cc3c39d39209d2e6da8725ce6b5 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 10:44:15 -0800 Subject: [PATCH 07/15] rename to simple_calculator_notebook for no naming conflict in workflow cleanup Signed-off-by: Bryan Bednarski --- .../notebooks/mcp_setup_and_integration.ipynb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/notebooks/mcp_setup_and_integration.ipynb b/examples/notebooks/mcp_setup_and_integration.ipynb index e334f5683..4b82651e8 100644 --- a/examples/notebooks/mcp_setup_and_integration.ipynb +++ b/examples/notebooks/mcp_setup_and_integration.ipynb @@ -474,7 +474,7 @@ "\n", "## 1.1) Starting the server with default settings\n", "\n", - "First, let's install the `simple_calculator` example from NAT source.\n", + "First, let's install the `simple_calculator` example from NAT source as `simple_calculator_notebook`, which we can edit and run.\n", "\n", "We recommend using the 'develop' branch in Google Colab." ] @@ -498,7 +498,7 @@ "source": [ "%%bash --bg\n", "# Then let's start up the simple calculator MCP server.\n", - "nat mcp serve --config_file ./simple_calculator/configs/config.yml" + "nat mcp serve --config_file ./simple_calculator_notebook/configs/config.yml" ] }, { @@ -508,7 +508,7 @@ "source": [ "The `--bg` command will run your server in the background of the notebook, so you might not see confirmation that the server is running. To see the startup logs, you can remove this flag and run the cell again. However, subsequent steps require the server to be run as a background process.\n", "\n", - "Next, we will list the set of available tools from `simple_calculator` MCP server." + "Next, we will list the set of available tools from `simple_calculator_notebook` MCP server." ] }, { @@ -542,7 +542,7 @@ "\n", "You can also use the `sse` (Server-Sent Events) transport for backwards compatibility through the `--transport` flag, for example:\n", "```bash\n", - "nat mcp serve --config_file examples/getting_started/simple_calculator/configs/config.yml --transport sse\n", + "nat mcp serve --config_file ./simple_calculator_notebook/configs/config.yml --transport sse\n", "```\n", "With this configuration, the MCP server is available at `http://localhost:9901/sse` using SSE transport.\n", "\n", @@ -581,7 +581,7 @@ "outputs": [], "source": [ "%%bash --bg\n", - "nat mcp serve --config_file ./simple_calculator/configs/config.yml \\\n", + "nat mcp serve --config_file ./simple_calculator_notebook/configs/config.yml \\\n", " --host 0.0.0.0 \\\n", " --port 9901 \\\n", " --name \"My MCP Server\"" @@ -640,7 +640,7 @@ "outputs": [], "source": [ "%%bash --bg\n", - "nat mcp serve --config_file ./simple_calculator/configs/config.yml \\\n", + "nat mcp serve --config_file ./simple_calculator_notebook/configs/config.yml \\\n", " --tool_names calculator.multiply \\\n", " --tool_names calculator.divide \\\n", " --host 0.0.0.0 \\\n", @@ -971,7 +971,7 @@ "outputs": [], "source": [ "%%bash --bg\n", - "nat mcp serve --config_file simple_calculator/configs/config.yml \\\n", + "nat mcp serve --config_file simple_calculator_notebook/configs/config.yml \\\n", " --host 0.0.0.0 \\\n", " --port 9901 \\\n", " --name \"My MCP Server\"" @@ -1092,7 +1092,7 @@ "outputs": [], "source": [ "%%bash --bg\n", - "nat mcp serve --config_file simple_calculator/configs/config.yml \\\n", + "nat mcp serve --config_file simple_calculator_notebook/configs/config.yml \\\n", " --host 0.0.0.0 \\\n", " --port 9901 \\\n", " --name \"My MCP Server\"" From e83c2c54efe552dbd0c9bfdd314dd19101e19ca9 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 11:10:00 -0800 Subject: [PATCH 08/15] Some workflows do not need to be pip installed for unit tests Signed-off-by: Bryan Bednarski --- examples/notebooks/tests/test_notebooks_e2e.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index 8c73f112d..7c4824a43 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -134,13 +134,13 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec "notebook_file_name, expected_packages, timeout_seconds", [ pytest.param("getting_started_with_nat.ipynb", ["getting_started"], 120, id="getting_started_with_nat"), - pytest.param("adding_tools_to_agents.ipynb", ["retail_sales_agent"], 300, id="adding_tools_to_agents"), - pytest.param("mcp_setup_and_integration.ipynb", ["mcp_dev_workflow", "nat_simple_calculator_notebook"], + pytest.param("adding_tools_to_agents.ipynb", [], 300, id="adding_tools_to_agents"), + pytest.param("mcp_setup_and_integration.ipynb", ["nat_simple_calculator_notebook"], 300, id="mcp_setup_and_integration"), - pytest.param("multi_agent_orchestration.ipynb", ["retail_sales_agent"], 120, + pytest.param("multi_agent_orchestration.ipynb", [], 120, id="multi_agent_orchestration"), - pytest.param("observability_evaluation_and_profiling.ipynb", ["retail_sales_agent"], + pytest.param("observability_evaluation_and_profiling.ipynb", [], 1000, id="observability_evaluation_and_profiling"), pytest.param("optimize_model_selection.ipynb", ["tmp_workflow"], 300, id="optimize_model_selection"), From 749879a71502e19bef250124b1eae2db5473eaf6 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 11:50:22 -0800 Subject: [PATCH 09/15] pre-commits Signed-off-by: Bryan Bednarski --- .../notebooks/mcp_setup_and_integration.ipynb | 34 +++++++++++-------- .../notebooks/tests/test_notebooks_e2e.py | 11 +++--- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/examples/notebooks/mcp_setup_and_integration.ipynb b/examples/notebooks/mcp_setup_and_integration.ipynb index 4b82651e8..a6539ae5d 100644 --- a/examples/notebooks/mcp_setup_and_integration.ipynb +++ b/examples/notebooks/mcp_setup_and_integration.ipynb @@ -236,11 +236,11 @@ " def rename_package_in_pyproject(pyproject_path: Path, suffix: str = \"_notebook\") -> str:\n", " \"\"\"\n", " Rename the package in pyproject.toml to avoid conflicts with existing installations.\n", - " \n", + "\n", " Args:\n", " pyproject_path: Path to the pyproject.toml file\n", " suffix: Suffix to append to the package name\n", - " \n", + "\n", " Returns:\n", " The new package name, or None if renaming failed\n", " \"\"\"\n", @@ -254,31 +254,31 @@ " except ImportError:\n", " print(\"Warning: Could not import toml library, package name will not be modified\")\n", " return None\n", - " \n", + "\n", " try:\n", " # Read the current pyproject.toml\n", " with open(pyproject_path, 'rb') as f:\n", " config = tomli.load(f)\n", - " \n", + "\n", " # Get the original package name\n", " original_name = config.get('project', {}).get('name')\n", " if not original_name:\n", " print(\"Warning: No package name found in pyproject.toml\")\n", " return None\n", - " \n", + "\n", " # Create new unique name\n", " new_name = f\"{original_name}{suffix}\"\n", - " \n", + "\n", " # Update the package name\n", " config['project']['name'] = new_name\n", - " \n", + "\n", " # Write back to pyproject.toml\n", " with open(pyproject_path, 'wb') as f:\n", " tomli_w.dump(config, f)\n", - " \n", + "\n", " print(f\"✓ Renamed package from '{original_name}' to '{new_name}' to avoid conflicts\")\n", " return new_name\n", - " \n", + "\n", " except Exception as e:\n", " print(f\"Warning: Could not modify package name: {e}\")\n", " return None\n", @@ -352,10 +352,10 @@ " if pyproject_file.exists():\n", " # Rename package to avoid conflicts\n", " new_name = rename_package_in_pyproject(pyproject_file)\n", - " \n", + "\n", " print(\"\\nInstalling example package in editable mode...\")\n", " get_ipython().system(f'pip install --no-deps -e {dest_path}')\n", - " \n", + "\n", " if new_name:\n", " print(f\"✓ Installed package as '{new_name}' from: {dest_path}\")\n", " else:\n", @@ -408,12 +408,12 @@ " if pyproject_file.exists():\n", " # Rename package to avoid conflicts\n", " new_name = rename_package_in_pyproject(pyproject_file)\n", - " \n", + "\n", " print(\"\\nInstalling example package in editable mode...\")\n", " print(f\"Installing from: {example_path}\")\n", " # get_ipython().system(f'pip install --no-deps -e {example_path}')\n", - " get_ipython().system(f'pip install --no-deps {example_path}') # remove editable mode so that nat workflow delete works\n", - " \n", + " get_ipython().system(f'pip install --no-deps {example_path}')\n", + "\n", " if new_name:\n", " print(f\"✓ Installed package as '{new_name}'\")\n", " else:\n", @@ -520,6 +520,7 @@ "source": [ "# Wait about 10 seconds before running the next cell...\n", "import time\n", + "\n", "time.sleep(10)" ] }, @@ -596,6 +597,7 @@ "source": [ "# Wait about 10 seconds before running the next cell...\n", "import time\n", + "\n", "time.sleep(10)" ] }, @@ -657,6 +659,7 @@ "source": [ "# Wait about 10 seconds before running the next cell...\n", "import time\n", + "\n", "time.sleep(10)" ] }, @@ -986,6 +989,7 @@ "source": [ "# Wait about 10 seconds before running the next cell...\n", "import time\n", + "\n", "time.sleep(10)" ] }, @@ -1107,6 +1111,7 @@ "source": [ "# Wait about 10 seconds before running the next cell...\n", "import time\n", + "\n", "time.sleep(10)" ] }, @@ -1159,6 +1164,7 @@ "source": [ "# Wait about 10 seconds before running the next cell...\n", "import time\n", + "\n", "time.sleep(10)" ] }, diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index 7c4824a43..605f28d95 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -13,9 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os import subprocess from pathlib import Path -import os import pytest @@ -134,13 +134,12 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec "notebook_file_name, expected_packages, timeout_seconds", [ pytest.param("getting_started_with_nat.ipynb", ["getting_started"], 120, id="getting_started_with_nat"), - pytest.param("adding_tools_to_agents.ipynb", [], 300, id="adding_tools_to_agents"), - pytest.param("mcp_setup_and_integration.ipynb", ["nat_simple_calculator_notebook"], + pytest.param("adding_tools_to_agents.ipynb", ["retail_sales_agent"], 300, id="adding_tools_to_agents"), + pytest.param("mcp_setup_and_integration.ipynb", ["mcp_dev_workflow", "nat_simple_calculator_notebook"], 300, id="mcp_setup_and_integration"), - pytest.param("multi_agent_orchestration.ipynb", [], 120, - id="multi_agent_orchestration"), - pytest.param("observability_evaluation_and_profiling.ipynb", [], + pytest.param("multi_agent_orchestration.ipynb", ["retail_sales_agent"], 120, id="multi_agent_orchestration"), + pytest.param("observability_evaluation_and_profiling.ipynb", ["retail_sales_agent"], 1000, id="observability_evaluation_and_profiling"), pytest.param("optimize_model_selection.ipynb", ["tmp_workflow"], 300, id="optimize_model_selection"), From 4f38faeee327df694b10ff0937cd01caf46fe52f Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 13:48:02 -0800 Subject: [PATCH 10/15] rename workflows to avoid name conflcit during integration testing Signed-off-by: Bryan Bednarski --- .../notebooks/adding_tools_to_agents.ipynb | 30 ++++++------- .../notebooks/mcp_setup_and_integration.ipynb | 7 ++- .../notebooks/multi_agent_orchestration.ipynb | 34 +++++++------- ...servability_evaluation_and_profiling.ipynb | 44 +++++++++---------- .../notebooks/tests/test_notebooks_e2e.py | 18 +++++--- 5 files changed, 70 insertions(+), 63 deletions(-) diff --git a/examples/notebooks/adding_tools_to_agents.ipynb b/examples/notebooks/adding_tools_to_agents.ipynb index 65c9a8723..7114b0ab5 100644 --- a/examples/notebooks/adding_tools_to_agents.ipynb +++ b/examples/notebooks/adding_tools_to_agents.ipynb @@ -612,7 +612,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat workflow create retail_sales_agent" + "!nat workflow create retail_sales_agent_nb3" ] }, { @@ -645,7 +645,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/total_product_sales_data_tool.py\n", + "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/total_product_sales_data_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -706,7 +706,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/sales_per_day_tool.py\n", + "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/sales_per_day_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -770,7 +770,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/detect_outliers_tool.py\n", + "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/detect_outliers_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -837,7 +837,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/src/retail_sales_agent/register.py\n", + "%%writefile -a retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n", "\n", "from . import sales_per_day_tool\n", "from . import detect_outliers_tool\n", @@ -855,7 +855,7 @@ "\n", "Below we show how to update the default configuration file for this new tool-calling retail sales agent with the new tools (python methods) that have been defined and registered properly.\n", "\n", - "Take a moment to analyze the new `retail_sales_agent/configs/config.yml` file below, where a `functions` header has been defined and each registered tool from the previous section is listed. " + "Take a moment to analyze the new `retail_sales_agent_nb3/configs/config.yml` file below, where a `functions` header has been defined and each registered tool from the previous section is listed. " ] }, { @@ -864,7 +864,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/configs/config.yml\n", + "%%writefile retail_sales_agent_nb3/configs/config.yml\n", "llms:\n", " nim_llm:\n", " _type: nim\n", @@ -915,7 +915,7 @@ "outputs": [], "source": [ "%%bash\n", - "nat workflow reinstall retail_sales_agent" + "nat workflow reinstall retail_sales_agent_nb3" ] }, { @@ -935,7 +935,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat run --config_file=retail_sales_agent/configs/config.yml --input \"How do laptop sales compare to phone sales?\"" + "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml --input \"How do laptop sales compare to phone sales?\"" ] }, { @@ -955,7 +955,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat run --config_file=retail_sales_agent/configs/config.yml --input \"What were the laptop sales on February 16th 2024?\"" + "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml --input \"What were the laptop sales on February 16th 2024?\"" ] }, { @@ -975,7 +975,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat run --config_file=retail_sales_agent/configs/config.yml --input \"What were the outliers in 'Revenue'?\"" + "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml --input \"What were the outliers in 'Revenue'?\"" ] }, { @@ -1012,7 +1012,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/retail_sales_rag_tool.py\n", + "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/retail_sales_rag_tool.py\n", "import logging\n", "import os\n", "\n", @@ -1103,7 +1103,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/src/retail_sales_agent/register.py\n", + "%%writefile -a retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n", "\n", "from . import retail_sales_rag_tool" ] @@ -1148,7 +1148,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/configs/config_rag.yml\n", + "%%writefile retail_sales_agent_nb3/configs/config_rag.yml\n", "llms:\n", " nim_llm:\n", " _type: nim\n", @@ -1216,7 +1216,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat run --config_file=retail_sales_agent/configs/config_rag.yml \\\n", + "!nat run --config_file=retail_sales_agent_nb3/configs/config_rag.yml \\\n", " --input \"What is the Ark S12 Ultra tablet and what are its specifications?\"" ] }, diff --git a/examples/notebooks/mcp_setup_and_integration.ipynb b/examples/notebooks/mcp_setup_and_integration.ipynb index a6539ae5d..9aa957d86 100644 --- a/examples/notebooks/mcp_setup_and_integration.ipynb +++ b/examples/notebooks/mcp_setup_and_integration.ipynb @@ -303,9 +303,12 @@ " print(\" - Enter a branch name (e.g., 'develop', 'main') to clone and install\")\n", " print(\"=\" * 60)\n", "\n", - " branch_name = os.getenv(\"NAT_NOTEBOOK_INSTALL_MODE\", \"\").strip()\n", - " if not branch_name:\n", + " from IPython.core.error import StdinNotImplementedError\n", + " try:\n", " branch_name = input(\"\\nEnter your choice: \").strip()\n", + " except StdinNotImplementedError:\n", + " branch_name = 'local'\n", + " print(f\"\\nNo input available. Defaulting to branch: {branch_name}\")\n", "\n", " # Default to 'main' if empty\n", " if not branch_name:\n", diff --git a/examples/notebooks/multi_agent_orchestration.ipynb b/examples/notebooks/multi_agent_orchestration.ipynb index c273b988a..df324693c 100644 --- a/examples/notebooks/multi_agent_orchestration.ipynb +++ b/examples/notebooks/multi_agent_orchestration.ipynb @@ -622,7 +622,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat workflow create retail_sales_agent" + "!nat workflow create retail_sales_agent_nb5" ] }, { @@ -648,7 +648,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/total_product_sales_data_tool.py\n", + "%%writefile retail_sales_agent_nb5/src/retail_sales_agent_nb5/total_product_sales_data_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -707,7 +707,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/sales_per_day_tool.py\n", + "%%writefile retail_sales_agent_nb5/src/retail_sales_agent_nb5/sales_per_day_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -769,7 +769,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/detect_outliers_tool.py\n", + "%%writefile retail_sales_agent_nb5/src/retail_sales_agent_nb5/detect_outliers_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -834,7 +834,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/retail_sales_rag_tool.py\n", + "%%writefile retail_sales_agent_nb5/src/retail_sales_agent_nb5/retail_sales_rag_tool.py\n", "import logging\n", "import os\n", "\n", @@ -928,7 +928,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/data_visualization_tools.py\n", + "%%writefile retail_sales_agent_nb5/src/retail_sales_agent_nb5/data_visualization_tools.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -1059,7 +1059,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/src/retail_sales_agent/register.py\n", + "%%writefile -a retail_sales_agent_nb5/src/retail_sales_agent_nb5/register.py\n", "\n", "from . import sales_per_day_tool\n", "from . import detect_outliers_tool\n", @@ -1123,7 +1123,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/configs/config_multi_agent.yml\n", + "%%writefile retail_sales_agent_nb5/configs/config_multi_agent.yml\n", "llms:\n", " nim_llm:\n", " _type: nim\n", @@ -1261,7 +1261,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat run --config_file retail_sales_agent/configs/config_multi_agent.yml \\\n", + "!nat run --config_file retail_sales_agent_nb5/configs/config_multi_agent.yml \\\n", " --input \"What is the Ark S12 Ultra tablet and what are its specifications?\" \\\n", " --input \"How do laptop sales compare to phone sales?\" \\\n", " --input \"Plot average daily revenue\"" @@ -1314,7 +1314,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/retail_hitl_approval.py\n", + "%%writefile retail_sales_agent_nb5/src/retail_sales_agent_nb5/retail_hitl_approval.py\n", "import logging\n", "\n", "from pydantic import Field\n", @@ -1370,7 +1370,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/src/retail_sales_agent/register.py\n", + "%%writefile -a retail_sales_agent_nb5/src/retail_sales_agent_nb5/register.py\n", "\n", "from . import retail_hitl_approval" ] @@ -1391,7 +1391,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/graph_summarizer_tool.py\n", + "%%writefile retail_sales_agent_nb5/src/retail_sales_agent_nb5/graph_summarizer_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -1457,7 +1457,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/src/retail_sales_agent/register.py\n", + "%%writefile -a retail_sales_agent_nb5/src/retail_sales_agent_nb5/register.py\n", "\n", "from . import graph_summarizer_tool" ] @@ -1478,7 +1478,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/data_visualization_agent.py\n", + "%%writefile retail_sales_agent_nb5/src/retail_sales_agent_nb5/data_visualization_agent.py\n", "import logging\n", "\n", "from pydantic import Field\n", @@ -1666,7 +1666,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/src/retail_sales_agent/register.py\n", + "%%writefile -a retail_sales_agent_nb5/src/retail_sales_agent_nb5/register.py\n", "\n", "from . import data_visualization_agent" ] @@ -1697,7 +1697,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/configs/config_multi_agent_hitl.yml\n", + "%%writefile retail_sales_agent_nb5/configs/config_multi_agent_hitl.yml\n", "llms:\n", " nim_llm:\n", " _type: nim\n", @@ -1864,7 +1864,7 @@ "metadata": {}, "outputs": [], "source": [ - "! echo \"yes\" | nat run --config_file retail_sales_agent/configs/config_multi_agent_hitl.yml \\\n", + "! echo \"yes\" | nat run --config_file retail_sales_agent_nb5/configs/config_multi_agent_hitl.yml \\\n", " --input \"Plot average daily revenue\"" ] }, diff --git a/examples/notebooks/observability_evaluation_and_profiling.ipynb b/examples/notebooks/observability_evaluation_and_profiling.ipynb index 868c930c9..1fed92913 100644 --- a/examples/notebooks/observability_evaluation_and_profiling.ipynb +++ b/examples/notebooks/observability_evaluation_and_profiling.ipynb @@ -616,7 +616,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat workflow create retail_sales_agent" + "!nat workflow create retail_sales_agent_nb6" ] }, { @@ -651,7 +651,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/total_product_sales_data_tool.py\n", + "%%writefile retail_sales_agent_nb6/src/retail_sales_agent_nb6/total_product_sales_data_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -710,7 +710,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/sales_per_day_tool.py\n", + "%%writefile retail_sales_agent_nb6/src/retail_sales_agent_nb6/sales_per_day_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -772,7 +772,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/detect_outliers_tool.py\n", + "%%writefile retail_sales_agent_nb6/src/retail_sales_agent_nb6/detect_outliers_tool.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -837,7 +837,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/retail_sales_rag_tool.py\n", + "%%writefile retail_sales_agent_nb6/src/retail_sales_agent_nb6/retail_sales_rag_tool.py\n", "import logging\n", "import os\n", "\n", @@ -933,7 +933,7 @@ }, "outputs": [], "source": [ - "%%writefile retail_sales_agent/src/retail_sales_agent/data_visualization_tools.py\n", + "%%writefile retail_sales_agent_nb6/src/retail_sales_agent_nb6/data_visualization_tools.py\n", "from pydantic import Field\n", "\n", "from nat.builder.builder import Builder\n", @@ -1064,7 +1064,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/src/retail_sales_agent/register.py\n", + "%%writefile -a retail_sales_agent_nb6/src/retail_sales_agent_nb6/register.py\n", "\n", "from . import sales_per_day_tool\n", "from . import detect_outliers_tool\n", @@ -1091,7 +1091,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/configs/config.yml\n", + "%%writefile retail_sales_agent_nb6/configs/config.yml\n", "llms:\n", " nim_llm:\n", " _type: nim\n", @@ -1231,7 +1231,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat run --config_file retail_sales_agent/configs/config.yml \\\n", + "!nat run --config_file retail_sales_agent_nb6/configs/config.yml \\\n", " --input \"What is the Ark S12 Ultra tablet and what are its specifications?\" \\\n", " --input \"How do laptop sales compare to phone sales?\" \\\n", " --input \"Plot average daily revenue\"" @@ -1285,7 +1285,7 @@ "metadata": {}, "outputs": [], "source": [ - "!cp retail_sales_agent/configs/config.yml retail_sales_agent/configs/phoenix_config.yml" + "!cp retail_sales_agent_nb6/configs/config.yml retail_sales_agent_nb6/configs/phoenix_config.yml" ] }, { @@ -1303,7 +1303,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/configs/phoenix_config.yml\n", + "%%writefile -a retail_sales_agent_nb6/configs/phoenix_config.yml\n", "\n", "general:\n", " telemetry:\n", @@ -1315,7 +1315,7 @@ " phoenix:\n", " _type: phoenix\n", " endpoint: http://localhost:6006/v1/traces\n", - " project: retail_sales_agent\n" + " project: retail_sales_agent_nb6\n" ] }, { @@ -1400,7 +1400,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat run --config_file retail_sales_agent/configs/phoenix_config.yml \\\n", + "!nat run --config_file retail_sales_agent_nb6/configs/phoenix_config.yml \\\n", " --input \"What is the Ark S12 Ultra tablet and what are its specifications?\" \\\n", " --input \"How do laptop sales compare to phone sales?\" \\\n", " --input \"Plot average daily revenue\"" @@ -1459,7 +1459,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile retail_sales_agent/data/eval_data.json\n", + "%%writefile retail_sales_agent_nb6/data/eval_data.json\n", "[\n", " {\n", " \"id\": \"1\",\n", @@ -1506,7 +1506,7 @@ "metadata": {}, "outputs": [], "source": [ - "!cp retail_sales_agent/configs/config.yml retail_sales_agent/configs/config_eval.yml" + "!cp retail_sales_agent_nb6/configs/config.yml retail_sales_agent_nb6/configs/config_eval.yml" ] }, { @@ -1524,7 +1524,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/configs/config_eval.yml\n", + "%%writefile -a retail_sales_agent_nb6/configs/config_eval.yml\n", "\n", "eval:\n", " general:\n", @@ -1532,7 +1532,7 @@ " verbose: true\n", " dataset:\n", " _type: json\n", - " file_path: ./retail_sales_agent/data/eval_data.json\n", + " file_path: ./retail_sales_agent_nb6/data/eval_data.json\n", "\n", " evaluators:\n", " accuracy:\n", @@ -1570,7 +1570,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat eval --config_file retail_sales_agent/configs/config_eval.yml" + "!nat eval --config_file retail_sales_agent_nb6/configs/config_eval.yml" ] }, { @@ -1645,7 +1645,7 @@ "metadata": {}, "outputs": [], "source": [ - "!cp retail_sales_agent/configs/config.yml retail_sales_agent/configs/config_profile.yml" + "!cp retail_sales_agent_nb6/configs/config.yml retail_sales_agent_nb6/configs/config_profile.yml" ] }, { @@ -1663,7 +1663,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%writefile -a retail_sales_agent/configs/config_profile.yml\n", + "%%writefile -a retail_sales_agent_nb6/configs/config_profile.yml\n", "\n", "eval:\n", " general:\n", @@ -1671,7 +1671,7 @@ " verbose: true\n", " dataset:\n", " _type: json\n", - " file_path: ./retail_sales_agent/data/eval_data.json\n", + " file_path: ./retail_sales_agent_nb6/data/eval_data.json\n", "\n", " profiler:\n", " token_uniqueness_forecast: true\n", @@ -1742,7 +1742,7 @@ "metadata": {}, "outputs": [], "source": [ - "!nat eval --config_file retail_sales_agent/configs/config_profile.yml" + "!nat eval --config_file retail_sales_agent_nb6/configs/config_profile.yml" ] }, { diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index 605f28d95..76c219ab3 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -13,9 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import subprocess from pathlib import Path +import os import pytest @@ -25,6 +25,9 @@ "second_agent_attempt", "third_agent_attempt", "retail_sales_agent", + "retail_sales_agent_nb3", + "retail_sales_agent_nb5", + "retail_sales_agent_nb6", "tmp_workflow", "mcp_dev_workflow", "simple_calculator_notebook" @@ -115,12 +118,12 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec str(notebook_path.absolute()), ] - env = os.environ.copy() - env["NAT_NOTEBOOK_INSTALL_MODE"] = "develop" + # env = os.environ.copy() + # env["NAT_NOTEBOOK_INSTALL_MODE"] = "local" # Ideally if the notebook times out we want jupyter to catch it and exit gracefully with the most informative error # possible. However in the potential situation where jupyter itself hangs, we add a 10s buffer to the timeout. - result = subprocess.run(cmd, check=False, capture_output=True, text=True, timeout=timeout_seconds + 10, env=env) + result = subprocess.run(cmd, check=False, capture_output=True, text=True, timeout=timeout_seconds + 10) assert result.returncode == 0, f"Notebook execution failed:\n{result.stderr}" for package in expected_packages: @@ -134,12 +137,13 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec "notebook_file_name, expected_packages, timeout_seconds", [ pytest.param("getting_started_with_nat.ipynb", ["getting_started"], 120, id="getting_started_with_nat"), - pytest.param("adding_tools_to_agents.ipynb", ["retail_sales_agent"], 300, id="adding_tools_to_agents"), + pytest.param("adding_tools_to_agents.ipynb", ["retail_sales_agent_nb3"], 300, id="adding_tools_to_agents"), pytest.param("mcp_setup_and_integration.ipynb", ["mcp_dev_workflow", "nat_simple_calculator_notebook"], 300, id="mcp_setup_and_integration"), - pytest.param("multi_agent_orchestration.ipynb", ["retail_sales_agent"], 120, id="multi_agent_orchestration"), - pytest.param("observability_evaluation_and_profiling.ipynb", ["retail_sales_agent"], + pytest.param("multi_agent_orchestration.ipynb", ["retail_sales_agent_nb5"], 120, + id="multi_agent_orchestration"), + pytest.param("observability_evaluation_and_profiling.ipynb", ["retail_sales_agent_nb6"], 1000, id="observability_evaluation_and_profiling"), pytest.param("optimize_model_selection.ipynb", ["tmp_workflow"], 300, id="optimize_model_selection"), From 673b40ae4771d3f4e5fba0f4a0fc896bebc7cc9d Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 14:00:38 -0800 Subject: [PATCH 11/15] precommit Signed-off-by: Bryan Bednarski --- .../notebooks/adding_tools_to_agents.ipynb | 510 ++++++++++++++++-- .../notebooks/tests/test_notebooks_e2e.py | 1 - 2 files changed, 472 insertions(+), 39 deletions(-) diff --git a/examples/notebooks/adding_tools_to_agents.ipynb b/examples/notebooks/adding_tools_to_agents.ipynb index 7114b0ab5..f2153a5ea 100644 --- a/examples/notebooks/adding_tools_to_agents.ipynb +++ b/examples/notebooks/adding_tools_to_agents.ipynb @@ -91,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -126,7 +126,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -144,11 +144,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "cellView": "form" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing data/retail_sales_data.csv\n" + ] + } + ], "source": [ "%%writefile data/retail_sales_data.csv\n", "Date,StoreID,Product,UnitsSold,Revenue,Promotion\n", @@ -465,11 +473,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "cellView": "form" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing data/rag/product_catalog.md\n" + ] + } + ], "source": [ "%%writefile data/rag/product_catalog.md\n", "# Product Catalog: Smartphones, Laptops, and Tablets\n", @@ -552,9 +568,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: uv in /Users/bbednarski/.venvs/unew_312/lib/python3.12/site-packages (0.8.18)\n" + ] + } + ], "source": [ "!pip install uv" ] @@ -574,9 +598,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "nvidia-nat[langchain,llama-index] is already installed\n" + ] + } + ], "source": [ "%%bash\n", "uv pip show -q \"nvidia-nat-langchain\"\n", @@ -608,9 +640,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing workflow 'retail_sales_agent_nb3'...\n", + "Workflow 'retail_sales_agent_nb3' installed successfully.\n", + "Workflow 'retail_sales_agent_nb3' created successfully in '/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/examples/notebooks/retail_sales_agent_nb3'.\n", + "\u001b[0m\u001b[0m" + ] + } + ], "source": [ "!nat workflow create retail_sales_agent_nb3" ] @@ -641,9 +684,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing retail_sales_agent_nb3/src/retail_sales_agent_nb3/total_product_sales_data_tool.py\n" + ] + } + ], "source": [ "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/total_product_sales_data_tool.py\n", "from pydantic import Field\n", @@ -702,9 +753,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing retail_sales_agent_nb3/src/retail_sales_agent_nb3/sales_per_day_tool.py\n" + ] + } + ], "source": [ "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/sales_per_day_tool.py\n", "from pydantic import Field\n", @@ -766,9 +825,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing retail_sales_agent_nb3/src/retail_sales_agent_nb3/detect_outliers_tool.py\n" + ] + } + ], "source": [ "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/detect_outliers_tool.py\n", "from pydantic import Field\n", @@ -833,9 +900,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Appending to retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n" + ] + } + ], "source": [ "%%writefile -a retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n", "\n", @@ -860,9 +935,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting retail_sales_agent_nb3/configs/config.yml\n" + ] + } + ], "source": [ "%%writefile retail_sales_agent_nb3/configs/config.yml\n", "llms:\n", @@ -910,9 +993,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reinstalling workflow 'retail_sales_agent_nb3'...\n", + "Workflow 'retail_sales_agent_nb3' reinstalled successfully.\n", + "\u001b[0m" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[0m" + ] + } + ], "source": [ "%%bash\n", "nat workflow reinstall retail_sales_agent_nb3" @@ -931,9 +1031,104 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-05 13:51:21 - WARNING - nat.runtime.loader:209 - Failed to import plugin 'test_workflow_debug'\n", + "Traceback (most recent call last):\n", + " File \"/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/src/nat/runtime/loader.py\", line 188, in discover_and_register_plugins\n", + " entry_point.load()\n", + " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/metadata/__init__.py\", line 205, in load\n", + " module = import_module(match.group('module'))\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"\", line 1387, in _gcd_import\n", + " File \"\", line 1360, in _find_and_load\n", + " File \"\", line 1310, in _find_and_load_unlocked\n", + " File \"\", line 488, in _call_with_frames_removed\n", + " File \"\", line 1387, in _gcd_import\n", + " File \"\", line 1360, in _find_and_load\n", + " File \"\", line 1324, in _find_and_load_unlocked\n", + "ModuleNotFoundError: No module named 'test_workflow_debug'\n", + "2025-11-05 13:51:21 - INFO - nat.cli.commands.start:192 - Starting NAT from config file: 'retail_sales_agent_nb3/configs/config.yml'\n", + "\n", + "Configuration Summary:\n", + "--------------------\n", + "Workflow Type: react_agent\n", + "Number of Functions: 3\n", + "Number of Function Groups: 0\n", + "Number of LLMs: 1\n", + "Number of Embedders: 0\n", + "Number of Memory: 0\n", + "Number of Object Stores: 0\n", + "Number of Retrievers: 0\n", + "Number of TTC Strategies: 0\n", + "Number of Authentication Providers: 0\n", + "\n", + "2025-11-05 13:51:22 - INFO - nat.agent.react_agent.agent:169 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: How do laptop sales compare to phone sales?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: To compare laptop sales to phone sales, I need to know the total sales data for both products. I can use the total_product_sales_data tool to retrieve this information.\n", + "\n", + "Action: total_product_sales_data\n", + "Action Input: {\"product_name\": \"laptop\"}\n", + "\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:22 - INFO - nat.agent.base:221 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[37mCalling tools: total_product_sales_data\n", + "\u001b[33mTool's input: {'product_name': 'laptop'}\n", + "\u001b[36mTool's response: \n", + "Revenue for laptop are 512000 and total units sold are 512\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:23 - INFO - nat.agent.react_agent.agent:193 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: How do laptop sales compare to phone sales?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: Now that I have the total sales data for laptops, I need to compare it to the total sales data for phones. I can use the total_product_sales_data tool again to retrieve the sales data for phones.\n", + "\n", + "Action: total_product_sales_data\n", + "Action Input: {\"product_name\": \"phone\"} \n", + "\n", + "\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:23 - INFO - nat.agent.base:221 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[37mCalling tools: total_product_sales_data\n", + "\u001b[33mTool's input: {'product_name': 'phone'}\n", + "\u001b[36mTool's response: \n", + "Revenue for phone are 561000 and total units sold are 1122\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:25 - INFO - nat.agent.react_agent.agent:193 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: How do laptop sales compare to phone sales?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: I now have the total sales data for both laptops and phones. I can compare the revenue and total units sold for both products to determine how laptop sales compare to phone sales.\n", + "\n", + "Thought: The revenue for laptops is $512,000 with 512 units sold, while the revenue for phones is $561,000 with 1122 units sold. This suggests that phone sales are higher than laptop sales in terms of both revenue and units sold.\n", + "\n", + "Final Answer: Phone sales are higher than laptop sales, with a revenue of $561,000 and 1122 units sold, compared to laptop sales of $512,000 and 512 units sold.\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:25 - INFO - nat.front_ends.console.console_front_end_plugin:102 - --------------------------------------------------\n", + "\u001b[32mWorkflow Result:\n", + "['Phone sales are higher than laptop sales, with a revenue of $561,000 and 1122 units sold, compared to laptop sales of $512,000 and 512 units sold.']\u001b[39m\n", + "--------------------------------------------------\n", + "\u001b[0m\u001b[0m" + ] + } + ], "source": [ "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml --input \"How do laptop sales compare to phone sales?\"" ] @@ -953,9 +1148,81 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-05 13:51:30 - WARNING - nat.runtime.loader:209 - Failed to import plugin 'test_workflow_debug'\n", + "Traceback (most recent call last):\n", + " File \"/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/src/nat/runtime/loader.py\", line 188, in discover_and_register_plugins\n", + " entry_point.load()\n", + " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/metadata/__init__.py\", line 205, in load\n", + " module = import_module(match.group('module'))\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"\", line 1387, in _gcd_import\n", + " File \"\", line 1360, in _find_and_load\n", + " File \"\", line 1310, in _find_and_load_unlocked\n", + " File \"\", line 488, in _call_with_frames_removed\n", + " File \"\", line 1387, in _gcd_import\n", + " File \"\", line 1360, in _find_and_load\n", + " File \"\", line 1324, in _find_and_load_unlocked\n", + "ModuleNotFoundError: No module named 'test_workflow_debug'\n", + "2025-11-05 13:51:31 - INFO - nat.cli.commands.start:192 - Starting NAT from config file: 'retail_sales_agent_nb3/configs/config.yml'\n", + "\n", + "Configuration Summary:\n", + "--------------------\n", + "Workflow Type: react_agent\n", + "Number of Functions: 3\n", + "Number of Function Groups: 0\n", + "Number of LLMs: 1\n", + "Number of Embedders: 0\n", + "Number of Memory: 0\n", + "Number of Object Stores: 0\n", + "Number of Retrievers: 0\n", + "Number of TTC Strategies: 0\n", + "Number of Authentication Providers: 0\n", + "\n", + "2025-11-05 13:51:32 - INFO - nat.agent.react_agent.agent:169 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: What were the laptop sales on February 16th 2024?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: To find the laptop sales on February 16th, 2024, I need to use the sales_per_day tool.\n", + "Action: sales_per_day\n", + "Action Input: {\"date\": \"2024-02-16\", \"product\": \"laptop\"}\n", + "\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:32 - INFO - nat.agent.base:221 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[37mCalling tools: sales_per_day\n", + "\u001b[33mTool's input: {'date': '2024-02-16', 'product': 'laptop'}\n", + "\u001b[36mTool's response: \n", + "Total revenue for 2024-02-16 is 13000 and total units sold is 13\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:33 - INFO - nat.agent.react_agent.agent:193 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: What were the laptop sales on February 16th 2024?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: I have received the total sales data for laptops on February 16th, 2024, which includes the total revenue and total units sold. I can now provide the final answer.\n", + "Final Answer: The laptop sales on February 16th, 2024, were 13 units with a total revenue of $13,000.\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:33 - INFO - nat.front_ends.console.console_front_end_plugin:102 - --------------------------------------------------\n", + "\u001b[32mWorkflow Result:\n", + "['The laptop sales on February 16th, 2024, were 13 units with a total revenue of $13,000.']\u001b[39m\n", + "--------------------------------------------------\n", + "\u001b[0m\u001b[0m" + ] + } + ], "source": [ - "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml --input \"What were the laptop sales on February 16th 2024?\"" + "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml \\\n", + " --input \"What were the laptop sales on February 16th 2024?\"" ] }, { @@ -971,9 +1238,80 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-05 13:51:38 - WARNING - nat.runtime.loader:209 - Failed to import plugin 'test_workflow_debug'\n", + "Traceback (most recent call last):\n", + " File \"/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/src/nat/runtime/loader.py\", line 188, in discover_and_register_plugins\n", + " entry_point.load()\n", + " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/metadata/__init__.py\", line 205, in load\n", + " module = import_module(match.group('module'))\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"\", line 1387, in _gcd_import\n", + " File \"\", line 1360, in _find_and_load\n", + " File \"\", line 1310, in _find_and_load_unlocked\n", + " File \"\", line 488, in _call_with_frames_removed\n", + " File \"\", line 1387, in _gcd_import\n", + " File \"\", line 1360, in _find_and_load\n", + " File \"\", line 1324, in _find_and_load_unlocked\n", + "ModuleNotFoundError: No module named 'test_workflow_debug'\n", + "2025-11-05 13:51:38 - INFO - nat.cli.commands.start:192 - Starting NAT from config file: 'retail_sales_agent_nb3/configs/config.yml'\n", + "\n", + "Configuration Summary:\n", + "--------------------\n", + "Workflow Type: react_agent\n", + "Number of Functions: 3\n", + "Number of Function Groups: 0\n", + "Number of LLMs: 1\n", + "Number of Embedders: 0\n", + "Number of Memory: 0\n", + "Number of Object Stores: 0\n", + "Number of Retrievers: 0\n", + "Number of TTC Strategies: 0\n", + "Number of Authentication Providers: 0\n", + "\n", + "2025-11-05 13:51:39 - INFO - nat.agent.react_agent.agent:169 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: What were the outliers in 'Revenue'?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: I need to detect outliers in the 'Revenue' metric.\n", + "Action: detect_outliers\n", + "Action Input: {\"metric\": \"Revenue\"}\n", + "\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:39 - INFO - nat.agent.base:221 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[37mCalling tools: detect_outliers\n", + "\u001b[33mTool's input: {'metric': 'Revenue'}\n", + "\u001b[36mTool's response: \n", + "Outliers in Revenue are [{'Date': '2024-01-26', 'StoreID': 'S002', 'Product': 'Phone', 'UnitsSold': 24, 'Revenue': 12000, 'Promotion': 'Yes'}, {'Date': '2024-02-15', 'StoreID': 'S001', 'Product': 'Phone', 'UnitsSold': 26, 'Revenue': 13000, 'Promotion': 'Yes'}]\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:40 - INFO - nat.agent.react_agent.agent:193 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: What were the outliers in 'Revenue'?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: I now know the final answer\n", + "Final Answer: The outliers in 'Revenue' are [{'Date': '2024-01-26', 'StoreID': 'S002', 'Product': 'Phone', 'UnitsSold': 24, 'Revenue': 12000, 'Promotion': 'Yes'}, {'Date': '2024-02-15', 'StoreID': 'S001', 'Product': 'Phone', 'UnitsSold': 26, 'Revenue': 13000, 'Promotion': 'Yes'}]\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:40 - INFO - nat.front_ends.console.console_front_end_plugin:102 - --------------------------------------------------\n", + "\u001b[32mWorkflow Result:\n", + "[\"The outliers in 'Revenue' are [{'Date': '2024-01-26', 'StoreID': 'S002', 'Product': 'Phone', 'UnitsSold': 24, 'Revenue': 12000, 'Promotion': 'Yes'}, {'Date': '2024-02-15', 'StoreID': 'S001', 'Product': 'Phone', 'UnitsSold': 26, 'Revenue': 13000, 'Promotion': 'Yes'}]\"]\u001b[39m\n", + "--------------------------------------------------\n", + "\u001b[0m\u001b[0m" + ] + } + ], "source": [ "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml --input \"What were the outliers in 'Revenue'?\"" ] @@ -1008,9 +1346,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing retail_sales_agent_nb3/src/retail_sales_agent_nb3/retail_sales_rag_tool.py\n" + ] + } + ], "source": [ "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/retail_sales_rag_tool.py\n", "import logging\n", @@ -1099,9 +1445,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Appending to retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n" + ] + } + ], "source": [ "%%writefile -a retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n", "\n", @@ -1144,9 +1498,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing retail_sales_agent_nb3/configs/config_rag.yml\n" + ] + } + ], "source": [ "%%writefile retail_sales_agent_nb3/configs/config_rag.yml\n", "llms:\n", @@ -1212,9 +1574,81 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-05 13:51:46 - WARNING - nat.runtime.loader:209 - Failed to import plugin 'test_workflow_debug'\n", + "Traceback (most recent call last):\n", + " File \"/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/src/nat/runtime/loader.py\", line 188, in discover_and_register_plugins\n", + " entry_point.load()\n", + " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/metadata/__init__.py\", line 205, in load\n", + " module = import_module(match.group('module'))\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"\", line 1387, in _gcd_import\n", + " File \"\", line 1360, in _find_and_load\n", + " File \"\", line 1310, in _find_and_load_unlocked\n", + " File \"\", line 488, in _call_with_frames_removed\n", + " File \"\", line 1387, in _gcd_import\n", + " File \"\", line 1360, in _find_and_load\n", + " File \"\", line 1324, in _find_and_load_unlocked\n", + "ModuleNotFoundError: No module named 'test_workflow_debug'\n", + "2025-11-05 13:51:46 - INFO - nat.cli.commands.start:192 - Starting NAT from config file: 'retail_sales_agent_nb3/configs/config_rag.yml'\n", + "2025-11-05 13:51:47 - INFO - retail_sales_agent_nb3.retail_sales_rag_tool:48 - Loaded 1 documents from data/rag/\n", + "\n", + "Configuration Summary:\n", + "--------------------\n", + "Workflow Type: react_agent\n", + "Number of Functions: 4\n", + "Number of Function Groups: 0\n", + "Number of LLMs: 1\n", + "Number of Embedders: 1\n", + "Number of Memory: 0\n", + "Number of Object Stores: 0\n", + "Number of Retrievers: 0\n", + "Number of TTC Strategies: 0\n", + "Number of Authentication Providers: 0\n", + "\n", + "2025-11-05 13:51:49 - INFO - nat.agent.react_agent.agent:169 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: What is the Ark S12 Ultra tablet and what are its specifications?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: The user is asking about the Ark S12 Ultra tablet, which is not one of the products I have information about. I should ask about the product catalog to see if it contains information about this tablet.\n", + "Action: product_catalog_rag\n", + "Action Input: {\"inputs\": \"Ark S12 Ultra tablet\"}\n", + "\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:52 - INFO - nat.agent.base:221 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[37mCalling tools: product_catalog_rag\n", + "\u001b[33mTool's input: {'inputs': 'Ark S12 Ultra tablet'}\n", + "\u001b[36mTool's response: \n", + "The Ark S12 Ultra tablet features a 12.9-inch OLED display with a 144Hz refresh rate, HDR10+ dynamic range, and a resolution of 2800 x 1752 pixels. It runs on NebulynOS 6.0, based on Android 14L, and supports app sandboxing, multi-user profiles, and remote device management. The device is powered by Qualcomm's Snapdragon 8 Gen 3 SoC, includes an Adreno 750 GPU and an NPU for on-device AI tasks, and comes with 16GB LPDDR5X RAM and 512GB of storage. The tablet also supports a stylus with 4096 pressure levels and tilt detection, as well as a keyboard with a trackpad and programmable shortcut keys. Additionally, it has a 13MP main sensor and a 12MP ultra-wide front camera, and supports Wi-Fi 7, Bluetooth 5.3, and optional LTE/5G with eSIM. The device is targeted at professionals who require a balance between media consumption, creativity, and light productivity.\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:54 - INFO - nat.agent.react_agent.agent:193 - \n", + "------------------------------\n", + "[AGENT]\n", + "\u001b[33mAgent input: What is the Ark S12 Ultra tablet and what are its specifications?\n", + "\u001b[36mAgent's thoughts: \n", + "Thought: I now know the final answer\n", + "Final Answer: The Ark S12 Ultra tablet features a 12.9-inch OLED display, runs on NebulynOS 6.0, and is powered by Qualcomm's Snapdragon 8 Gen 3 SoC. It comes with 16GB LPDDR5X RAM, 512GB of storage, and supports a stylus and keyboard. The device also has a 13MP main sensor, a 12MP ultra-wide front camera, and supports Wi-Fi 7, Bluetooth 5.3, and optional LTE/5G with eSIM. It is targeted at professionals who require a balance between media consumption, creativity, and light productivity.\u001b[39m\n", + "------------------------------\n", + "2025-11-05 13:51:54 - INFO - nat.front_ends.console.console_front_end_plugin:102 - --------------------------------------------------\n", + "\u001b[32mWorkflow Result:\n", + "[\"The Ark S12 Ultra tablet features a 12.9-inch OLED display, runs on NebulynOS 6.0, and is powered by Qualcomm's Snapdragon 8 Gen 3 SoC. It comes with 16GB LPDDR5X RAM, 512GB of storage, and supports a stylus and keyboard. The device also has a 13MP main sensor, a 12MP ultra-wide front camera, and supports Wi-Fi 7, Bluetooth 5.3, and optional LTE/5G with eSIM. It is targeted at professionals who require a balance between media consumption, creativity, and light productivity.\"]\u001b[39m\n", + "--------------------------------------------------\n", + "\u001b[0m\u001b[0m" + ] + } + ], "source": [ "!nat run --config_file=retail_sales_agent_nb3/configs/config_rag.yml \\\n", " --input \"What is the Ark S12 Ultra tablet and what are its specifications?\"" diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index 76c219ab3..dacf5f5e4 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -15,7 +15,6 @@ import subprocess from pathlib import Path -import os import pytest From 4812ec00185bea906e0b79947806484f19f9612b Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 14:31:12 -0800 Subject: [PATCH 12/15] remove notebook numbers from comments Signed-off-by: Bryan Bednarski --- .../notebooks/tests/test_notebooks_e2e.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index dacf5f5e4..1d499478f 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -34,20 +34,20 @@ # Other files produced by notebooks, relative to the notebooks directory, please keep this list sorted _OTHER_FILES = [ - "average_daily_revenue.png", # bar chart produced by notebooks 5 and 6 - # Descriptions of fictitious electronic devices used in RAG examples in notebooks 3, 5 and 6 + "average_daily_revenue.png", # bar chart produced by notebooks + # Descriptions of fictitious electronic devices used in RAG examples in notebooks "data/rag/product_catalog.md", - # Retail sales data for devices described in data/rag/product_catalog.md used in notebooks 3, 5 and 6 + # Retail sales data for devices described in data/rag/product_catalog.md used in notebooks "data/retail_sales_data.csv", - # The `eval_output` files are output from evaluation in 6_observability_evaluation_and_profiling + # The `eval_output` files are output from evaluation in observability_evaluation_and_profiling "eval_output/accuracy_output.json", "eval_output/groundedness_output.json", "eval_output/relevance_output.json", "eval_output/trajectory_accuracy_output.json", "eval_output/workflow_output.json", - "langchain_agent.py", # Example existing agent being incorporated into NAT in 2_bringing_your_own_agent - "nat_embedded.py", # Python script generated by 1_getting_started_with_nat, runs the workflow via the Python API - # The `profile_output` files are output from profiling in 6_observability_evaluation_and_profiling + "langchain_agent.py", # Example existing agent being incorporated into NAT in bringing_your_own_agent + "nat_embedded.py", # Python script generated by getting_started_with_nat, runs the workflow via the Python API + # The `profile_output` files are output from profiling in observability_evaluation_and_profiling "profile_output/all_requests_profiler_traces.json", "profile_output/gantt_chart.png", "profile_output/inference_optimization.json", @@ -55,10 +55,10 @@ "profile_output/workflow_output.json", "profile_output/workflow_profiling_metrics.json", "profile_output/workflow_profiling_report.txt", - "revenue_across_stores.png", # Chart produced by notebooks 5 and 6 - "sales_trend.png", # line chart produced by notebooks 5 and 6 - "search_agent.yml", # Workflow generated by 2_bringing_your_own_agent, uses Tavily to perform searches - # "simple_calculator/", # Example code directory created by 4_mcp_setup_and_integration + "revenue_across_stores.png", # Chart produced + "sales_trend.png", # line chart + "search_agent.yml", # Workflow generated by bringing_your_own_agent, uses Tavily to perform searches + # "simple_calculator/", # Example code directory created by mcp_setup_and_integration ] From e84451f1076bf9201dd45af5df0d5c89cb7636d7 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 14:32:10 -0800 Subject: [PATCH 13/15] precommit Signed-off-by: Bryan Bednarski --- examples/notebooks/tests/test_notebooks_e2e.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index 1d499478f..f0f9b0ded 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -55,8 +55,8 @@ "profile_output/workflow_output.json", "profile_output/workflow_profiling_metrics.json", "profile_output/workflow_profiling_report.txt", - "revenue_across_stores.png", # Chart produced - "sales_trend.png", # line chart + "revenue_across_stores.png", # Chart produced + "sales_trend.png", # line chart "search_agent.yml", # Workflow generated by bringing_your_own_agent, uses Tavily to perform searches # "simple_calculator/", # Example code directory created by mcp_setup_and_integration ] From 8301e9606a63181d315d677b9de411b2f54bd9eb Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 14:39:04 -0800 Subject: [PATCH 14/15] precommit 2 Signed-off-by: Bryan Bednarski --- .../notebooks/adding_tools_to_agents.ipynb | 507 ++---------------- 1 file changed, 37 insertions(+), 470 deletions(-) diff --git a/examples/notebooks/adding_tools_to_agents.ipynb b/examples/notebooks/adding_tools_to_agents.ipynb index f2153a5ea..f81a68d35 100644 --- a/examples/notebooks/adding_tools_to_agents.ipynb +++ b/examples/notebooks/adding_tools_to_agents.ipynb @@ -91,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -126,7 +126,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -144,19 +144,11 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "cellView": "form" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Writing data/retail_sales_data.csv\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile data/retail_sales_data.csv\n", "Date,StoreID,Product,UnitsSold,Revenue,Promotion\n", @@ -473,19 +465,11 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "cellView": "form" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Writing data/rag/product_catalog.md\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile data/rag/product_catalog.md\n", "# Product Catalog: Smartphones, Laptops, and Tablets\n", @@ -568,17 +552,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: uv in /Users/bbednarski/.venvs/unew_312/lib/python3.12/site-packages (0.8.18)\n" - ] - } - ], + "outputs": [], "source": [ "!pip install uv" ] @@ -598,17 +574,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "nvidia-nat[langchain,llama-index] is already installed\n" - ] - } - ], + "outputs": [], "source": [ "%%bash\n", "uv pip show -q \"nvidia-nat-langchain\"\n", @@ -640,20 +608,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Installing workflow 'retail_sales_agent_nb3'...\n", - "Workflow 'retail_sales_agent_nb3' installed successfully.\n", - "Workflow 'retail_sales_agent_nb3' created successfully in '/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/examples/notebooks/retail_sales_agent_nb3'.\n", - "\u001b[0m\u001b[0m" - ] - } - ], + "outputs": [], "source": [ "!nat workflow create retail_sales_agent_nb3" ] @@ -684,17 +641,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Writing retail_sales_agent_nb3/src/retail_sales_agent_nb3/total_product_sales_data_tool.py\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/total_product_sales_data_tool.py\n", "from pydantic import Field\n", @@ -753,17 +702,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Writing retail_sales_agent_nb3/src/retail_sales_agent_nb3/sales_per_day_tool.py\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/sales_per_day_tool.py\n", "from pydantic import Field\n", @@ -825,17 +766,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Writing retail_sales_agent_nb3/src/retail_sales_agent_nb3/detect_outliers_tool.py\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/detect_outliers_tool.py\n", "from pydantic import Field\n", @@ -900,17 +833,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Appending to retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile -a retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n", "\n", @@ -935,17 +860,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting retail_sales_agent_nb3/configs/config.yml\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile retail_sales_agent_nb3/configs/config.yml\n", "llms:\n", @@ -993,26 +910,9 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Reinstalling workflow 'retail_sales_agent_nb3'...\n", - "Workflow 'retail_sales_agent_nb3' reinstalled successfully.\n", - "\u001b[0m" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[0m" - ] - } - ], + "outputs": [], "source": [ "%%bash\n", "nat workflow reinstall retail_sales_agent_nb3" @@ -1031,104 +931,9 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-11-05 13:51:21 - WARNING - nat.runtime.loader:209 - Failed to import plugin 'test_workflow_debug'\n", - "Traceback (most recent call last):\n", - " File \"/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/src/nat/runtime/loader.py\", line 188, in discover_and_register_plugins\n", - " entry_point.load()\n", - " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/metadata/__init__.py\", line 205, in load\n", - " module = import_module(match.group('module'))\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n", - " return _bootstrap._gcd_import(name[level:], package, level)\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"\", line 1387, in _gcd_import\n", - " File \"\", line 1360, in _find_and_load\n", - " File \"\", line 1310, in _find_and_load_unlocked\n", - " File \"\", line 488, in _call_with_frames_removed\n", - " File \"\", line 1387, in _gcd_import\n", - " File \"\", line 1360, in _find_and_load\n", - " File \"\", line 1324, in _find_and_load_unlocked\n", - "ModuleNotFoundError: No module named 'test_workflow_debug'\n", - "2025-11-05 13:51:21 - INFO - nat.cli.commands.start:192 - Starting NAT from config file: 'retail_sales_agent_nb3/configs/config.yml'\n", - "\n", - "Configuration Summary:\n", - "--------------------\n", - "Workflow Type: react_agent\n", - "Number of Functions: 3\n", - "Number of Function Groups: 0\n", - "Number of LLMs: 1\n", - "Number of Embedders: 0\n", - "Number of Memory: 0\n", - "Number of Object Stores: 0\n", - "Number of Retrievers: 0\n", - "Number of TTC Strategies: 0\n", - "Number of Authentication Providers: 0\n", - "\n", - "2025-11-05 13:51:22 - INFO - nat.agent.react_agent.agent:169 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: How do laptop sales compare to phone sales?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: To compare laptop sales to phone sales, I need to know the total sales data for both products. I can use the total_product_sales_data tool to retrieve this information.\n", - "\n", - "Action: total_product_sales_data\n", - "Action Input: {\"product_name\": \"laptop\"}\n", - "\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:22 - INFO - nat.agent.base:221 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[37mCalling tools: total_product_sales_data\n", - "\u001b[33mTool's input: {'product_name': 'laptop'}\n", - "\u001b[36mTool's response: \n", - "Revenue for laptop are 512000 and total units sold are 512\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:23 - INFO - nat.agent.react_agent.agent:193 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: How do laptop sales compare to phone sales?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: Now that I have the total sales data for laptops, I need to compare it to the total sales data for phones. I can use the total_product_sales_data tool again to retrieve the sales data for phones.\n", - "\n", - "Action: total_product_sales_data\n", - "Action Input: {\"product_name\": \"phone\"} \n", - "\n", - "\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:23 - INFO - nat.agent.base:221 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[37mCalling tools: total_product_sales_data\n", - "\u001b[33mTool's input: {'product_name': 'phone'}\n", - "\u001b[36mTool's response: \n", - "Revenue for phone are 561000 and total units sold are 1122\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:25 - INFO - nat.agent.react_agent.agent:193 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: How do laptop sales compare to phone sales?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: I now have the total sales data for both laptops and phones. I can compare the revenue and total units sold for both products to determine how laptop sales compare to phone sales.\n", - "\n", - "Thought: The revenue for laptops is $512,000 with 512 units sold, while the revenue for phones is $561,000 with 1122 units sold. This suggests that phone sales are higher than laptop sales in terms of both revenue and units sold.\n", - "\n", - "Final Answer: Phone sales are higher than laptop sales, with a revenue of $561,000 and 1122 units sold, compared to laptop sales of $512,000 and 512 units sold.\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:25 - INFO - nat.front_ends.console.console_front_end_plugin:102 - --------------------------------------------------\n", - "\u001b[32mWorkflow Result:\n", - "['Phone sales are higher than laptop sales, with a revenue of $561,000 and 1122 units sold, compared to laptop sales of $512,000 and 512 units sold.']\u001b[39m\n", - "--------------------------------------------------\n", - "\u001b[0m\u001b[0m" - ] - } - ], + "outputs": [], "source": [ "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml --input \"How do laptop sales compare to phone sales?\"" ] @@ -1148,78 +953,7 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-11-05 13:51:30 - WARNING - nat.runtime.loader:209 - Failed to import plugin 'test_workflow_debug'\n", - "Traceback (most recent call last):\n", - " File \"/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/src/nat/runtime/loader.py\", line 188, in discover_and_register_plugins\n", - " entry_point.load()\n", - " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/metadata/__init__.py\", line 205, in load\n", - " module = import_module(match.group('module'))\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n", - " return _bootstrap._gcd_import(name[level:], package, level)\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"\", line 1387, in _gcd_import\n", - " File \"\", line 1360, in _find_and_load\n", - " File \"\", line 1310, in _find_and_load_unlocked\n", - " File \"\", line 488, in _call_with_frames_removed\n", - " File \"\", line 1387, in _gcd_import\n", - " File \"\", line 1360, in _find_and_load\n", - " File \"\", line 1324, in _find_and_load_unlocked\n", - "ModuleNotFoundError: No module named 'test_workflow_debug'\n", - "2025-11-05 13:51:31 - INFO - nat.cli.commands.start:192 - Starting NAT from config file: 'retail_sales_agent_nb3/configs/config.yml'\n", - "\n", - "Configuration Summary:\n", - "--------------------\n", - "Workflow Type: react_agent\n", - "Number of Functions: 3\n", - "Number of Function Groups: 0\n", - "Number of LLMs: 1\n", - "Number of Embedders: 0\n", - "Number of Memory: 0\n", - "Number of Object Stores: 0\n", - "Number of Retrievers: 0\n", - "Number of TTC Strategies: 0\n", - "Number of Authentication Providers: 0\n", - "\n", - "2025-11-05 13:51:32 - INFO - nat.agent.react_agent.agent:169 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: What were the laptop sales on February 16th 2024?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: To find the laptop sales on February 16th, 2024, I need to use the sales_per_day tool.\n", - "Action: sales_per_day\n", - "Action Input: {\"date\": \"2024-02-16\", \"product\": \"laptop\"}\n", - "\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:32 - INFO - nat.agent.base:221 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[37mCalling tools: sales_per_day\n", - "\u001b[33mTool's input: {'date': '2024-02-16', 'product': 'laptop'}\n", - "\u001b[36mTool's response: \n", - "Total revenue for 2024-02-16 is 13000 and total units sold is 13\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:33 - INFO - nat.agent.react_agent.agent:193 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: What were the laptop sales on February 16th 2024?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: I have received the total sales data for laptops on February 16th, 2024, which includes the total revenue and total units sold. I can now provide the final answer.\n", - "Final Answer: The laptop sales on February 16th, 2024, were 13 units with a total revenue of $13,000.\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:33 - INFO - nat.front_ends.console.console_front_end_plugin:102 - --------------------------------------------------\n", - "\u001b[32mWorkflow Result:\n", - "['The laptop sales on February 16th, 2024, were 13 units with a total revenue of $13,000.']\u001b[39m\n", - "--------------------------------------------------\n", - "\u001b[0m\u001b[0m" - ] - } - ], + "outputs": [], "source": [ "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml \\\n", " --input \"What were the laptop sales on February 16th 2024?\"" @@ -1238,80 +972,9 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-11-05 13:51:38 - WARNING - nat.runtime.loader:209 - Failed to import plugin 'test_workflow_debug'\n", - "Traceback (most recent call last):\n", - " File \"/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/src/nat/runtime/loader.py\", line 188, in discover_and_register_plugins\n", - " entry_point.load()\n", - " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/metadata/__init__.py\", line 205, in load\n", - " module = import_module(match.group('module'))\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n", - " return _bootstrap._gcd_import(name[level:], package, level)\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"\", line 1387, in _gcd_import\n", - " File \"\", line 1360, in _find_and_load\n", - " File \"\", line 1310, in _find_and_load_unlocked\n", - " File \"\", line 488, in _call_with_frames_removed\n", - " File \"\", line 1387, in _gcd_import\n", - " File \"\", line 1360, in _find_and_load\n", - " File \"\", line 1324, in _find_and_load_unlocked\n", - "ModuleNotFoundError: No module named 'test_workflow_debug'\n", - "2025-11-05 13:51:38 - INFO - nat.cli.commands.start:192 - Starting NAT from config file: 'retail_sales_agent_nb3/configs/config.yml'\n", - "\n", - "Configuration Summary:\n", - "--------------------\n", - "Workflow Type: react_agent\n", - "Number of Functions: 3\n", - "Number of Function Groups: 0\n", - "Number of LLMs: 1\n", - "Number of Embedders: 0\n", - "Number of Memory: 0\n", - "Number of Object Stores: 0\n", - "Number of Retrievers: 0\n", - "Number of TTC Strategies: 0\n", - "Number of Authentication Providers: 0\n", - "\n", - "2025-11-05 13:51:39 - INFO - nat.agent.react_agent.agent:169 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: What were the outliers in 'Revenue'?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: I need to detect outliers in the 'Revenue' metric.\n", - "Action: detect_outliers\n", - "Action Input: {\"metric\": \"Revenue\"}\n", - "\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:39 - INFO - nat.agent.base:221 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[37mCalling tools: detect_outliers\n", - "\u001b[33mTool's input: {'metric': 'Revenue'}\n", - "\u001b[36mTool's response: \n", - "Outliers in Revenue are [{'Date': '2024-01-26', 'StoreID': 'S002', 'Product': 'Phone', 'UnitsSold': 24, 'Revenue': 12000, 'Promotion': 'Yes'}, {'Date': '2024-02-15', 'StoreID': 'S001', 'Product': 'Phone', 'UnitsSold': 26, 'Revenue': 13000, 'Promotion': 'Yes'}]\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:40 - INFO - nat.agent.react_agent.agent:193 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: What were the outliers in 'Revenue'?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: I now know the final answer\n", - "Final Answer: The outliers in 'Revenue' are [{'Date': '2024-01-26', 'StoreID': 'S002', 'Product': 'Phone', 'UnitsSold': 24, 'Revenue': 12000, 'Promotion': 'Yes'}, {'Date': '2024-02-15', 'StoreID': 'S001', 'Product': 'Phone', 'UnitsSold': 26, 'Revenue': 13000, 'Promotion': 'Yes'}]\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:40 - INFO - nat.front_ends.console.console_front_end_plugin:102 - --------------------------------------------------\n", - "\u001b[32mWorkflow Result:\n", - "[\"The outliers in 'Revenue' are [{'Date': '2024-01-26', 'StoreID': 'S002', 'Product': 'Phone', 'UnitsSold': 24, 'Revenue': 12000, 'Promotion': 'Yes'}, {'Date': '2024-02-15', 'StoreID': 'S001', 'Product': 'Phone', 'UnitsSold': 26, 'Revenue': 13000, 'Promotion': 'Yes'}]\"]\u001b[39m\n", - "--------------------------------------------------\n", - "\u001b[0m\u001b[0m" - ] - } - ], + "outputs": [], "source": [ "!nat run --config_file=retail_sales_agent_nb3/configs/config.yml --input \"What were the outliers in 'Revenue'?\"" ] @@ -1346,17 +1009,9 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Writing retail_sales_agent_nb3/src/retail_sales_agent_nb3/retail_sales_rag_tool.py\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile retail_sales_agent_nb3/src/retail_sales_agent_nb3/retail_sales_rag_tool.py\n", "import logging\n", @@ -1445,17 +1100,9 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Appending to retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile -a retail_sales_agent_nb3/src/retail_sales_agent_nb3/register.py\n", "\n", @@ -1498,17 +1145,9 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Writing retail_sales_agent_nb3/configs/config_rag.yml\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile retail_sales_agent_nb3/configs/config_rag.yml\n", "llms:\n", @@ -1574,81 +1213,9 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-11-05 13:51:46 - WARNING - nat.runtime.loader:209 - Failed to import plugin 'test_workflow_debug'\n", - "Traceback (most recent call last):\n", - " File \"/Users/bbednarski/Projects/nat-getting-started-fork/NeMo-Agent-Toolkit/src/nat/runtime/loader.py\", line 188, in discover_and_register_plugins\n", - " entry_point.load()\n", - " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/metadata/__init__.py\", line 205, in load\n", - " module = import_module(match.group('module'))\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/opt/homebrew/Cellar/python@3.12/3.12.11_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n", - " return _bootstrap._gcd_import(name[level:], package, level)\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"\", line 1387, in _gcd_import\n", - " File \"\", line 1360, in _find_and_load\n", - " File \"\", line 1310, in _find_and_load_unlocked\n", - " File \"\", line 488, in _call_with_frames_removed\n", - " File \"\", line 1387, in _gcd_import\n", - " File \"\", line 1360, in _find_and_load\n", - " File \"\", line 1324, in _find_and_load_unlocked\n", - "ModuleNotFoundError: No module named 'test_workflow_debug'\n", - "2025-11-05 13:51:46 - INFO - nat.cli.commands.start:192 - Starting NAT from config file: 'retail_sales_agent_nb3/configs/config_rag.yml'\n", - "2025-11-05 13:51:47 - INFO - retail_sales_agent_nb3.retail_sales_rag_tool:48 - Loaded 1 documents from data/rag/\n", - "\n", - "Configuration Summary:\n", - "--------------------\n", - "Workflow Type: react_agent\n", - "Number of Functions: 4\n", - "Number of Function Groups: 0\n", - "Number of LLMs: 1\n", - "Number of Embedders: 1\n", - "Number of Memory: 0\n", - "Number of Object Stores: 0\n", - "Number of Retrievers: 0\n", - "Number of TTC Strategies: 0\n", - "Number of Authentication Providers: 0\n", - "\n", - "2025-11-05 13:51:49 - INFO - nat.agent.react_agent.agent:169 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: What is the Ark S12 Ultra tablet and what are its specifications?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: The user is asking about the Ark S12 Ultra tablet, which is not one of the products I have information about. I should ask about the product catalog to see if it contains information about this tablet.\n", - "Action: product_catalog_rag\n", - "Action Input: {\"inputs\": \"Ark S12 Ultra tablet\"}\n", - "\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:52 - INFO - nat.agent.base:221 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[37mCalling tools: product_catalog_rag\n", - "\u001b[33mTool's input: {'inputs': 'Ark S12 Ultra tablet'}\n", - "\u001b[36mTool's response: \n", - "The Ark S12 Ultra tablet features a 12.9-inch OLED display with a 144Hz refresh rate, HDR10+ dynamic range, and a resolution of 2800 x 1752 pixels. It runs on NebulynOS 6.0, based on Android 14L, and supports app sandboxing, multi-user profiles, and remote device management. The device is powered by Qualcomm's Snapdragon 8 Gen 3 SoC, includes an Adreno 750 GPU and an NPU for on-device AI tasks, and comes with 16GB LPDDR5X RAM and 512GB of storage. The tablet also supports a stylus with 4096 pressure levels and tilt detection, as well as a keyboard with a trackpad and programmable shortcut keys. Additionally, it has a 13MP main sensor and a 12MP ultra-wide front camera, and supports Wi-Fi 7, Bluetooth 5.3, and optional LTE/5G with eSIM. The device is targeted at professionals who require a balance between media consumption, creativity, and light productivity.\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:54 - INFO - nat.agent.react_agent.agent:193 - \n", - "------------------------------\n", - "[AGENT]\n", - "\u001b[33mAgent input: What is the Ark S12 Ultra tablet and what are its specifications?\n", - "\u001b[36mAgent's thoughts: \n", - "Thought: I now know the final answer\n", - "Final Answer: The Ark S12 Ultra tablet features a 12.9-inch OLED display, runs on NebulynOS 6.0, and is powered by Qualcomm's Snapdragon 8 Gen 3 SoC. It comes with 16GB LPDDR5X RAM, 512GB of storage, and supports a stylus and keyboard. The device also has a 13MP main sensor, a 12MP ultra-wide front camera, and supports Wi-Fi 7, Bluetooth 5.3, and optional LTE/5G with eSIM. It is targeted at professionals who require a balance between media consumption, creativity, and light productivity.\u001b[39m\n", - "------------------------------\n", - "2025-11-05 13:51:54 - INFO - nat.front_ends.console.console_front_end_plugin:102 - --------------------------------------------------\n", - "\u001b[32mWorkflow Result:\n", - "[\"The Ark S12 Ultra tablet features a 12.9-inch OLED display, runs on NebulynOS 6.0, and is powered by Qualcomm's Snapdragon 8 Gen 3 SoC. It comes with 16GB LPDDR5X RAM, 512GB of storage, and supports a stylus and keyboard. The device also has a 13MP main sensor, a 12MP ultra-wide front camera, and supports Wi-Fi 7, Bluetooth 5.3, and optional LTE/5G with eSIM. It is targeted at professionals who require a balance between media consumption, creativity, and light productivity.\"]\u001b[39m\n", - "--------------------------------------------------\n", - "\u001b[0m\u001b[0m" - ] - } - ], + "outputs": [], "source": [ "!nat run --config_file=retail_sales_agent_nb3/configs/config_rag.yml \\\n", " --input \"What is the Ark S12 Ultra tablet and what are its specifications?\"" From bdc953bc8d0f5af6abb9f29037c71681bc5058f7 Mon Sep 17 00:00:00 2001 From: Bryan Bednarski Date: Wed, 5 Nov 2025 14:43:46 -0800 Subject: [PATCH 15/15] remove comments Signed-off-by: Bryan Bednarski --- examples/notebooks/tests/test_notebooks_e2e.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/notebooks/tests/test_notebooks_e2e.py b/examples/notebooks/tests/test_notebooks_e2e.py index f0f9b0ded..e50ceea6c 100644 --- a/examples/notebooks/tests/test_notebooks_e2e.py +++ b/examples/notebooks/tests/test_notebooks_e2e.py @@ -117,9 +117,6 @@ def _run_notebook(notebook_path: Path, expected_packages: list[str], timeout_sec str(notebook_path.absolute()), ] - # env = os.environ.copy() - # env["NAT_NOTEBOOK_INSTALL_MODE"] = "local" - # Ideally if the notebook times out we want jupyter to catch it and exit gracefully with the most informative error # possible. However in the potential situation where jupyter itself hangs, we add a 10s buffer to the timeout. result = subprocess.run(cmd, check=False, capture_output=True, text=True, timeout=timeout_seconds + 10)