llama-stack-mirror/docs/zero_to_hero_guide/03_Tool_Calling101.ipynb
2024-11-06 18:07:01 -08:00

457 lines
27 KiB
Text

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tool Calling\n",
"\n",
"Before you begin, please ensure Llama Stack is installed and set up by following the [Getting Started Guide](https://llama-stack.readthedocs.io/en/latest/getting_started/index.html)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this section, we'll explore how to enhance your applications with tool calling capabilities. We'll cover:\n",
"1. Setting up and using the Brave Search API\n",
"2. Creating custom tools\n",
"3. Configuring tool prompts and safety settings"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Set up your connection parameters:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"HOST = \"localhost\" # Replace with your host\n",
"PORT = 5000 # Replace with your port"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: llama_stack_client in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (0.0.41)\n",
"Collecting llama_stack_client\n",
" Downloading llama_stack_client-0.0.49-py3-none-any.whl.metadata (13 kB)\n",
"Requirement already satisfied: anyio<5,>=3.5.0 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from llama_stack_client) (4.6.2)\n",
"Requirement already satisfied: distro<2,>=1.7.0 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from llama_stack_client) (1.9.0)\n",
"Requirement already satisfied: httpx<1,>=0.23.0 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from llama_stack_client) (0.27.0)\n",
"Requirement already satisfied: pydantic<3,>=1.9.0 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from llama_stack_client) (2.9.2)\n",
"Requirement already satisfied: sniffio in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from llama_stack_client) (1.3.0)\n",
"Requirement already satisfied: tabulate>=0.9.0 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from llama_stack_client) (0.9.0)\n",
"Requirement already satisfied: typing-extensions<5,>=4.7 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from llama_stack_client) (4.11.0)\n",
"Requirement already satisfied: idna>=2.8 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from anyio<5,>=3.5.0->llama_stack_client) (3.10)\n",
"Requirement already satisfied: exceptiongroup>=1.0.2 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from anyio<5,>=3.5.0->llama_stack_client) (1.2.0)\n",
"Requirement already satisfied: certifi in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from httpx<1,>=0.23.0->llama_stack_client) (2024.8.30)\n",
"Requirement already satisfied: httpcore==1.* in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from httpx<1,>=0.23.0->llama_stack_client) (1.0.2)\n",
"Requirement already satisfied: h11<0.15,>=0.13 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->llama_stack_client) (0.14.0)\n",
"Requirement already satisfied: annotated-types>=0.6.0 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from pydantic<3,>=1.9.0->llama_stack_client) (0.7.0)\n",
"Requirement already satisfied: pydantic-core==2.23.4 in /home/justinai/.conda/envs/agentstore/lib/python3.10/site-packages (from pydantic<3,>=1.9.0->llama_stack_client) (2.23.4)\n",
"Downloading llama_stack_client-0.0.49-py3-none-any.whl (280 kB)\n",
"Installing collected packages: llama_stack_client\n",
" Attempting uninstall: llama_stack_client\n",
" Found existing installation: llama_stack_client 0.0.41\n",
" Uninstalling llama_stack_client-0.0.41:\n",
" Successfully uninstalled llama_stack_client-0.0.41\n",
"Successfully installed llama_stack_client-0.0.49\n"
]
}
],
"source": [
"!pip install --upgrade llama_stack_client"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import asyncio\n",
"import os\n",
"from typing import Dict, List, Optional\n",
"from dotenv import load_dotenv\n",
"\n",
"from llama_stack_client import LlamaStackClient\n",
"from llama_stack_client.lib.agents.agent import Agent\n",
"from llama_stack_client.lib.agents.event_logger import EventLogger\n",
"from llama_stack_client.types.agent_create_params import (\n",
" AgentConfig,\n",
" AgentConfigToolSearchToolDefinition,\n",
")\n",
"\n",
"# Load environment variables\n",
"load_dotenv()\n",
"\n",
"# Helper function to create an agent with tools\n",
"async def create_tool_agent(\n",
" client: LlamaStackClient,\n",
" tools: List[Dict],\n",
" instructions: str = \"You are a helpful assistant\",\n",
" model: str = \"Llama3.2-11B-Vision-Instruct\",\n",
") -> Agent:\n",
" \"\"\"Create an agent with specified tools.\"\"\"\n",
" print(\"Using the following model: \", model)\n",
" agent_config = AgentConfig(\n",
" model=model,\n",
" instructions=instructions,\n",
" sampling_params={\n",
" \"strategy\": \"greedy\",\n",
" \"temperature\": 1.0,\n",
" \"top_p\": 0.9,\n",
" },\n",
" tools=tools,\n",
" tool_choice=\"auto\",\n",
" tool_prompt_format=\"json\",\n",
" enable_session_persistence=True,\n",
" )\n",
"\n",
" return Agent(client, agent_config)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, create a `.env` file in your notebook directory with your Brave Search API key:\n",
"\n",
"```\n",
"BRAVE_SEARCH_API_KEY=your_key_here\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Using the following model: Llama3.2-11B-Vision-Instruct\n",
"\n",
"Query: What are the latest developments in quantum computing?\n",
"--------------------------------------------------\n",
"\u001b[30m\u001b[0m\u001b[33minference> \u001b[0m\u001b[33mF\u001b[0m\u001b[33mIND\u001b[0m\u001b[33mINGS\u001b[0m\u001b[33m:\n",
"\u001b[0m\u001b[33mQuant\u001b[0m\u001b[33mum\u001b[0m\u001b[33m computing\u001b[0m\u001b[33m has\u001b[0m\u001b[33m made\u001b[0m\u001b[33m significant\u001b[0m\u001b[33m progress\u001b[0m\u001b[33m in\u001b[0m\u001b[33m recent\u001b[0m\u001b[33m years\u001b[0m\u001b[33m,\u001b[0m\u001b[33m with\u001b[0m\u001b[33m several\u001b[0m\u001b[33m companies\u001b[0m\u001b[33m and\u001b[0m\u001b[33m research\u001b[0m\u001b[33m institutions\u001b[0m\u001b[33m making\u001b[0m\u001b[33m breakthrough\u001b[0m\u001b[33ms\u001b[0m\u001b[33m in\u001b[0m\u001b[33m the\u001b[0m\u001b[33m field\u001b[0m\u001b[33m.\u001b[0m\u001b[33m Some\u001b[0m\u001b[33m of\u001b[0m\u001b[33m the\u001b[0m\u001b[33m latest\u001b[0m\u001b[33m developments\u001b[0m\u001b[33m include\u001b[0m\u001b[33m:\n",
"\n",
"\u001b[0m\u001b[33m*\u001b[0m\u001b[33m Google\u001b[0m\u001b[33m's\u001b[0m\u001b[33m S\u001b[0m\u001b[33myc\u001b[0m\u001b[33mam\u001b[0m\u001b[33more\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m processor\u001b[0m\u001b[33m,\u001b[0m\u001b[33m which\u001b[0m\u001b[33m achieved\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m supremacy\u001b[0m\u001b[33m in\u001b[0m\u001b[33m \u001b[0m\u001b[33m201\u001b[0m\u001b[33m9\u001b[0m\u001b[33m by\u001b[0m\u001b[33m performing\u001b[0m\u001b[33m a\u001b[0m\u001b[33m complex\u001b[0m\u001b[33m calculation\u001b[0m\u001b[33m that\u001b[0m\u001b[33m was\u001b[0m\u001b[33m beyond\u001b[0m\u001b[33m the\u001b[0m\u001b[33m capabilities\u001b[0m\u001b[33m of\u001b[0m\u001b[33m classical\u001b[0m\u001b[33m computers\u001b[0m\u001b[33m (\u001b[0m\u001b[33mSource\u001b[0m\u001b[33m:\u001b[0m\u001b[33m \"\u001b[0m\u001b[33mQuant\u001b[0m\u001b[33mum\u001b[0m\u001b[33m Sup\u001b[0m\u001b[33mrem\u001b[0m\u001b[33macy\u001b[0m\u001b[33m Using\u001b[0m\u001b[33m a\u001b[0m\u001b[33m \u001b[0m\u001b[33m53\u001b[0m\u001b[33m-Q\u001b[0m\u001b[33mubit\u001b[0m\u001b[33m Quantum\u001b[0m\u001b[33m Computer\u001b[0m\u001b[33m\"\u001b[0m\u001b[33m by\u001b[0m\u001b[33m Google\u001b[0m\u001b[33m Researchers\u001b[0m\u001b[33m,\u001b[0m\u001b[33m ar\u001b[0m\u001b[33mX\u001b[0m\u001b[33miv\u001b[0m\u001b[33m:\u001b[0m\u001b[33m191\u001b[0m\u001b[33m0\u001b[0m\u001b[33m.\u001b[0m\u001b[33m113\u001b[0m\u001b[33m33\u001b[0m\u001b[33m).\n",
"\u001b[0m\u001b[33m*\u001b[0m\u001b[33m IBM\u001b[0m\u001b[33m's\u001b[0m\u001b[33m Quantum\u001b[0m\u001b[33m Experience\u001b[0m\u001b[33m,\u001b[0m\u001b[33m a\u001b[0m\u001b[33m cloud\u001b[0m\u001b[33m-based\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m computer\u001b[0m\u001b[33m that\u001b[0m\u001b[33m allows\u001b[0m\u001b[33m users\u001b[0m\u001b[33m to\u001b[0m\u001b[33m run\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m algorithms\u001b[0m\u001b[33m and\u001b[0m\u001b[33m experiments\u001b[0m\u001b[33m (\u001b[0m\u001b[33mSource\u001b[0m\u001b[33m:\u001b[0m\u001b[33m IBM\u001b[0m\u001b[33m Quantum\u001b[0m\u001b[33m Experience\u001b[0m\u001b[33m,\u001b[0m\u001b[33m IBM\u001b[0m\u001b[33m Research\u001b[0m\u001b[33m).\n",
"\u001b[0m\u001b[33m*\u001b[0m\u001b[33m Rig\u001b[0m\u001b[33metti\u001b[0m\u001b[33m Computing\u001b[0m\u001b[33m's\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m cloud\u001b[0m\u001b[33m platform\u001b[0m\u001b[33m,\u001b[0m\u001b[33m which\u001b[0m\u001b[33m provides\u001b[0m\u001b[33m access\u001b[0m\u001b[33m to\u001b[0m\u001b[33m a\u001b[0m\u001b[33m \u001b[0m\u001b[33m128\u001b[0m\u001b[33m-q\u001b[0m\u001b[33mubit\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m processor\u001b[0m\u001b[33m (\u001b[0m\u001b[33mSource\u001b[0m\u001b[33m:\u001b[0m\u001b[33m Rig\u001b[0m\u001b[33metti\u001b[0m\u001b[33m Computing\u001b[0m\u001b[33m,\u001b[0m\u001b[33m Rig\u001b[0m\u001b[33metti\u001b[0m\u001b[33m.com\u001b[0m\u001b[33m).\n",
"\u001b[0m\u001b[33m*\u001b[0m\u001b[33m Microsoft\u001b[0m\u001b[33m's\u001b[0m\u001b[33m Quantum\u001b[0m\u001b[33m Development\u001b[0m\u001b[33m Kit\u001b[0m\u001b[33m,\u001b[0m\u001b[33m a\u001b[0m\u001b[33m set\u001b[0m\u001b[33m of\u001b[0m\u001b[33m tools\u001b[0m\u001b[33m and\u001b[0m\u001b[33m software\u001b[0m\u001b[33m for\u001b[0m\u001b[33m developing\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m algorithms\u001b[0m\u001b[33m and\u001b[0m\u001b[33m applications\u001b[0m\u001b[33m (\u001b[0m\u001b[33mSource\u001b[0m\u001b[33m:\u001b[0m\u001b[33m Microsoft\u001b[0m\u001b[33m Quantum\u001b[0m\u001b[33m Development\u001b[0m\u001b[33m Kit\u001b[0m\u001b[33m,\u001b[0m\u001b[33m Microsoft\u001b[0m\u001b[33m.com\u001b[0m\u001b[33m).\n",
"\u001b[0m\u001b[33m*\u001b[0m\u001b[33m The\u001b[0m\u001b[33m development\u001b[0m\u001b[33m of\u001b[0m\u001b[33m new\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m error\u001b[0m\u001b[33m correction\u001b[0m\u001b[33m techniques\u001b[0m\u001b[33m,\u001b[0m\u001b[33m such\u001b[0m\u001b[33m as\u001b[0m\u001b[33m surface\u001b[0m\u001b[33m codes\u001b[0m\u001b[33m and\u001b[0m\u001b[33m top\u001b[0m\u001b[33mological\u001b[0m\u001b[33m codes\u001b[0m\u001b[33m,\u001b[0m\u001b[33m which\u001b[0m\u001b[33m are\u001b[0m\u001b[33m essential\u001b[0m\u001b[33m for\u001b[0m\u001b[33m large\u001b[0m\u001b[33m-scale\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m computing\u001b[0m\u001b[33m (\u001b[0m\u001b[33mSource\u001b[0m\u001b[33m:\u001b[0m\u001b[33m \"\u001b[0m\u001b[33mQuant\u001b[0m\u001b[33mum\u001b[0m\u001b[33m Error\u001b[0m\u001b[33m Correction\u001b[0m\u001b[33m with\u001b[0m\u001b[33m Surface\u001b[0m\u001b[33m Codes\u001b[0m\u001b[33m\"\u001b[0m\u001b[33m by\u001b[0m\u001b[33m Stephanie\u001b[0m\u001b[33m We\u001b[0m\u001b[33mh\u001b[0m\u001b[33mner\u001b[0m\u001b[33m et\u001b[0m\u001b[33m al\u001b[0m\u001b[33m.,\u001b[0m\u001b[33m ar\u001b[0m\u001b[33mX\u001b[0m\u001b[33miv\u001b[0m\u001b[33m:\u001b[0m\u001b[33m140\u001b[0m\u001b[33m1\u001b[0m\u001b[33m.\u001b[0m\u001b[33m408\u001b[0m\u001b[33m1\u001b[0m\u001b[33m).\n",
"\n",
"\u001b[0m\u001b[33mS\u001b[0m\u001b[33mOURCES\u001b[0m\u001b[33m:\n",
"\u001b[0m\u001b[33m-\u001b[0m\u001b[33m \"\u001b[0m\u001b[33mQuant\u001b[0m\u001b[33mum\u001b[0m\u001b[33m Sup\u001b[0m\u001b[33mrem\u001b[0m\u001b[33macy\u001b[0m\u001b[33m Using\u001b[0m\u001b[33m a\u001b[0m\u001b[33m \u001b[0m\u001b[33m53\u001b[0m\u001b[33m-Q\u001b[0m\u001b[33mubit\u001b[0m\u001b[33m Quantum\u001b[0m\u001b[33m Computer\u001b[0m\u001b[33m\"\u001b[0m\u001b[33m by\u001b[0m\u001b[33m Google\u001b[0m\u001b[33m Researchers\u001b[0m\u001b[33m,\u001b[0m\u001b[33m ar\u001b[0m\u001b[33mX\u001b[0m\u001b[33miv\u001b[0m\u001b[33m:\u001b[0m\u001b[33m191\u001b[0m\u001b[33m0\u001b[0m\u001b[33m.\u001b[0m\u001b[33m113\u001b[0m\u001b[33m33\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33m-\u001b[0m\u001b[33m IBM\u001b[0m\u001b[33m Quantum\u001b[0m\u001b[33m Experience\u001b[0m\u001b[33m,\u001b[0m\u001b[33m IBM\u001b[0m\u001b[33m Research\u001b[0m\u001b[33m (\u001b[0m\u001b[33mhttps\u001b[0m\u001b[33m://\u001b[0m\u001b[33mwww\u001b[0m\u001b[33m.ibm\u001b[0m\u001b[33m.com\u001b[0m\u001b[33m/\u001b[0m\u001b[33mquant\u001b[0m\u001b[33mum\u001b[0m\u001b[33m-ex\u001b[0m\u001b[33mperience\u001b[0m\u001b[33m/)\n",
"\u001b[0m\u001b[33m-\u001b[0m\u001b[33m Rig\u001b[0m\u001b[33metti\u001b[0m\u001b[33m Computing\u001b[0m\u001b[33m,\u001b[0m\u001b[33m Rig\u001b[0m\u001b[33metti\u001b[0m\u001b[33m.com\u001b[0m\u001b[33m (\u001b[0m\u001b[33mhttps\u001b[0m\u001b[33m://\u001b[0m\u001b[33mwww\u001b[0m\u001b[33m.r\u001b[0m\u001b[33mig\u001b[0m\u001b[33metti\u001b[0m\u001b[33m.com\u001b[0m\u001b[33m/)\n",
"\u001b[0m\u001b[33m-\u001b[0m\u001b[33m Microsoft\u001b[0m\u001b[33m Quantum\u001b[0m\u001b[33m Development\u001b[0m\u001b[33m Kit\u001b[0m\u001b[33m,\u001b[0m\u001b[33m Microsoft\u001b[0m\u001b[33m.com\u001b[0m\u001b[33m (\u001b[0m\u001b[33mhttps\u001b[0m\u001b[33m://\u001b[0m\u001b[33mwww\u001b[0m\u001b[33m.microsoft\u001b[0m\u001b[33m.com\u001b[0m\u001b[33m/en\u001b[0m\u001b[33m-us\u001b[0m\u001b[33m quantum\u001b[0m\u001b[33m/)\n",
"\u001b[0m\u001b[33m-\u001b[0m\u001b[33m \"\u001b[0m\u001b[33mQuant\u001b[0m\u001b[33mum\u001b[0m\u001b[33m Error\u001b[0m\u001b[33m Correction\u001b[0m\u001b[33m with\u001b[0m\u001b[33m Surface\u001b[0m\u001b[33m Codes\u001b[0m\u001b[33m\"\u001b[0m\u001b[33m by\u001b[0m\u001b[33m Stephanie\u001b[0m\u001b[33m We\u001b[0m\u001b[33mh\u001b[0m\u001b[33mner\u001b[0m\u001b[33m et\u001b[0m\u001b[33m al\u001b[0m\u001b[33m.,\u001b[0m\u001b[33m ar\u001b[0m\u001b[33mX\u001b[0m\u001b[33miv\u001b[0m\u001b[33m:\u001b[0m\u001b[33m140\u001b[0m\u001b[33m1\u001b[0m\u001b[33m.\u001b[0m\u001b[33m408\u001b[0m\u001b[33m1\u001b[0m\u001b[97m\u001b[0m\n",
"\u001b[30m\u001b[0m"
]
}
],
"source": [
"async def create_search_agent(client: LlamaStackClient) -> Agent:\n",
" \"\"\"Create an agent with Brave Search capability.\"\"\"\n",
" search_tool = AgentConfigToolSearchToolDefinition(\n",
" type=\"brave_search\",\n",
" engine=\"brave\",\n",
" api_key=\"dummy_value\"#os.getenv(\"BRAVE_SEARCH_API_KEY\"),\n",
" )\n",
" \n",
" models_response = client.models.list()\n",
" for model in models_response:\n",
" if model.identifier.endswith(\"Instruct\"):\n",
" model_name = model.llama_model\n",
" \n",
"\n",
" return await create_tool_agent(\n",
" client=client,\n",
" tools=[search_tool],\n",
" model = model_name,\n",
" instructions=\"\"\"\n",
" You are a research assistant that can search the web.\n",
" Always cite your sources with URLs when providing information.\n",
" Format your responses as:\n",
"\n",
" FINDINGS:\n",
" [Your summary here]\n",
"\n",
" SOURCES:\n",
" - [Source title](URL)\n",
" \"\"\"\n",
" )\n",
"\n",
"# Example usage\n",
"async def search_example():\n",
" client = LlamaStackClient(base_url=f\"http://{HOST}:{PORT}\")\n",
" agent = await create_search_agent(client)\n",
"\n",
" # Create a session\n",
" session_id = agent.create_session(\"search-session\")\n",
"\n",
" # Example queries\n",
" queries = [\n",
" \"What are the latest developments in quantum computing?\",\n",
" #\"Who won the most recent Super Bowl?\",\n",
" ]\n",
"\n",
" for query in queries:\n",
" print(f\"\\nQuery: {query}\")\n",
" print(\"-\" * 50)\n",
"\n",
" response = agent.create_turn(\n",
" messages=[{\"role\": \"user\", \"content\": query}],\n",
" session_id=session_id,\n",
" )\n",
"\n",
" async for log in EventLogger().log(response):\n",
" log.print()\n",
"\n",
"# Run the example (in Jupyter, use asyncio.run())\n",
"await search_example()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Custom Tool Creation\n",
"\n",
"Let's create a custom weather tool:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Query: What's the weather like in San Francisco?\n",
"--------------------------------------------------\n",
"\u001b[30m\u001b[0m\u001b[33minference> \u001b[0m\u001b[33m{\n",
"\u001b[0m\u001b[33m \u001b[0m\u001b[33m \"\u001b[0m\u001b[33mtype\u001b[0m\u001b[33m\":\u001b[0m\u001b[33m \"\u001b[0m\u001b[33mfunction\u001b[0m\u001b[33m\",\n",
"\u001b[0m\u001b[33m \u001b[0m\u001b[33m \"\u001b[0m\u001b[33mname\u001b[0m\u001b[33m\":\u001b[0m\u001b[33m \"\u001b[0m\u001b[33mget\u001b[0m\u001b[33m_weather\u001b[0m\u001b[33m\",\n",
"\u001b[0m\u001b[33m \u001b[0m\u001b[33m \"\u001b[0m\u001b[33mparameters\u001b[0m\u001b[33m\":\u001b[0m\u001b[33m {\n",
"\u001b[0m\u001b[33m \u001b[0m\u001b[33m \"\u001b[0m\u001b[33mlocation\u001b[0m\u001b[33m\":\u001b[0m\u001b[33m \"\u001b[0m\u001b[33mSan\u001b[0m\u001b[33m Francisco\u001b[0m\u001b[33m\"\n",
"\u001b[0m\u001b[33m \u001b[0m\u001b[33m }\n",
"\u001b[0m\u001b[33m}\u001b[0m\u001b[97m\u001b[0m\n",
"tool_calls starting: ToolCall(arguments={'location': 'San Francisco'}, call_id='f558e862-0465-48c5-9f65-f9160a59003b', tool_name='get_weather')\n",
"Using Location: San Francisco\n",
" {\n",
" \"temperature\": 72.5,\n",
" \"conditions\": \"partly cloudy\",\n",
" \"humidity\": 65.0\n",
" }\n",
"\n",
"Query: Tell me the weather in Tokyo tomorrow\n",
"--------------------------------------------------\n",
"\u001b[30m\u001b[0m\u001b[33minference> \u001b[0m\u001b[36m\u001b[0m\u001b[36m{\"\u001b[0m\u001b[36mtype\u001b[0m\u001b[36m\":\u001b[0m\u001b[36m \"\u001b[0m\u001b[36mfunction\u001b[0m\u001b[36m\",\u001b[0m\u001b[36m \"\u001b[0m\u001b[36mname\u001b[0m\u001b[36m\":\u001b[0m\u001b[36m \"\u001b[0m\u001b[36mget\u001b[0m\u001b[36m_weather\u001b[0m\u001b[36m\",\u001b[0m\u001b[36m \"\u001b[0m\u001b[36mparameters\u001b[0m\u001b[36m\":\u001b[0m\u001b[36m {\"\u001b[0m\u001b[36mlocation\u001b[0m\u001b[36m\":\u001b[0m\u001b[36m \"\u001b[0m\u001b[36mTok\u001b[0m\u001b[36myo\u001b[0m\u001b[36m\",\u001b[0m\u001b[36m \"\u001b[0m\u001b[36mdate\u001b[0m\u001b[36m\":\u001b[0m\u001b[36m \"\u001b[0m\u001b[36mtom\u001b[0m\u001b[36morrow\u001b[0m\u001b[36m\"}}\u001b[0m\u001b[97m\u001b[0m\n",
"tool_calls starting: ToolCall(arguments={'location': 'Tokyo', 'date': 'tomorrow'}, call_id='d2ee9a99-ee8f-4fcd-9cda-a1bfb52bcc72', tool_name='get_weather')\n",
"Using Location: Tokyo\n",
"Using date: tomorrow\n",
" {\n",
" \"temperature\": 72.5,\n",
" \"conditions\": \"partly cloudy\",\n",
" \"humidity\": 65.0\n",
" }\n"
]
}
],
"source": [
"from typing import TypedDict, Optional, Dict, Any\n",
"from datetime import datetime\n",
"\n",
"from llama_stack_client.types.tool_param_definition_param import ToolParamDefinitionParam\n",
"from llama_stack_client.types import CompletionMessage\n",
"class WeatherTool:\n",
" \"\"\"Example custom tool for weather information.\"\"\"\n",
"\n",
" def get_name(self) -> str:\n",
" return \"get_weather\"\n",
"\n",
" def get_description(self) -> str:\n",
" return \"Get weather information for a location\"\n",
"\n",
" def get_params_definition(self) -> Dict[str, ToolParamDefinitionParam]:\n",
" return {\n",
" \"location\": ToolParamDefinitionParam(\n",
" param_type=\"str\",\n",
" description=\"City or location name\",\n",
" required=True\n",
" ),\n",
" \"date\": ToolParamDefinitionParam(\n",
" param_type=\"str\",\n",
" description=\"Optional date (YYYY-MM-DD)\",\n",
" required=False\n",
" )\n",
" }\n",
" async def run(self,messages):\n",
" for message in messages:\n",
" print(\"tool_calls starting: \", message.tool_calls[0])\n",
" return_dict = message.tool_calls[0].arguments\n",
" location = return_dict.get(\"location\",None)\n",
" date = return_dict.get(\"date\",None)\n",
" print(\"Using Location:\",location)\n",
" if date:\n",
" print(\"Using date:\",date)\n",
" return await self.run_impl(location,date)\n",
" \n",
" async def run_impl(self, location: str, date: Optional[str] = None) -> Dict[str, Any]:\n",
" \"\"\"Simulate getting weather data (replace with actual API call).\"\"\"\n",
" # Mock implementation\n",
" print(\"\"\" {\n",
" \"temperature\": 72.5,\n",
" \"conditions\": \"partly cloudy\",\n",
" \"humidity\": 65.0\n",
" }\"\"\")\n",
" return [CompletionMessage(\n",
" content=\"\"\"{\n",
" \"temperature\": 72.5,\n",
" \"conditions\": \"partly cloudy\",\n",
" \"humidity\": 65.0\n",
" }\"\"\",\n",
" role='assistant',\n",
" stop_reason='end_of_message',\n",
" tool_calls=[],\n",
" )],\n",
" \n",
"\n",
"async def create_weather_agent(client: LlamaStackClient) -> Agent:\n",
" \"\"\"Create an agent with weather tool capability.\"\"\"\n",
" models_response = client.models.list()\n",
" for model in models_response:\n",
" if model.identifier.endswith(\"Instruct\"):\n",
" model_name = model.llama_model\n",
" agent_config = AgentConfig(\n",
" model=model_name,\n",
" instructions=\"\"\"\n",
" You are a weather assistant that can provide weather information.\n",
" Always specify the location clearly in your responses.\n",
" Include both temperature and conditions in your summaries.\n",
" \"\"\",\n",
" sampling_params={\n",
" \"strategy\": \"greedy\",\n",
" \"temperature\": 1.0,\n",
" \"top_p\": 0.9,\n",
" },\n",
" tools=[\n",
" {\n",
" \"function_name\": \"get_weather\",\n",
" \"description\": \"Get weather information for a location\",\n",
" \"parameters\": {\n",
" \"location\": {\n",
" \"param_type\": \"str\",\n",
" \"description\": \"City or location name\",\n",
" \"required\": True,\n",
" },\n",
" \"date\": {\n",
" \"param_type\": \"str\",\n",
" \"description\": \"Optional date (YYYY-MM-DD)\",\n",
" \"required\": False,\n",
" },\n",
" },\n",
" \"type\": \"function_call\",\n",
" }\n",
" ],\n",
" tool_choice=\"auto\",\n",
" tool_prompt_format=\"json\",\n",
" input_shields=[],\n",
" output_shields=[],\n",
" enable_session_persistence=True\n",
" )\n",
"\n",
" # Create the agent with the tool\n",
" weather_tool = WeatherTool()\n",
" agent = Agent(\n",
" client=client,\n",
" agent_config=agent_config,\n",
" custom_tools=[weather_tool]\n",
" )\n",
"\n",
" return agent\n",
"\n",
"# Example usage\n",
"async def weather_example():\n",
" client = LlamaStackClient(base_url=f\"http://{HOST}:{PORT}\")\n",
" agent = await create_weather_agent(client)\n",
" session_id = agent.create_session(\"weather-session\")\n",
"\n",
" queries = [\n",
" \"What's the weather like in San Francisco?\",\n",
" \"Tell me the weather in Tokyo tomorrow\",\n",
" ]\n",
"\n",
" for query in queries:\n",
" print(f\"\\nQuery: {query}\")\n",
" print(\"-\" * 50)\n",
"\n",
" response = agent.create_turn(\n",
" messages=[{\"role\": \"user\", \"content\": query}],\n",
" session_id=session_id,\n",
" )\n",
" \n",
" async for log in EventLogger().log(response):\n",
" log.print()\n",
"\n",
"# For Jupyter notebooks\n",
"import nest_asyncio\n",
"nest_asyncio.apply()\n",
"\n",
"# Run the example\n",
"await weather_example()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Thanks for checking out this tutorial, hopefully you can now automate everything with Llama! :D\n",
"\n",
"Next up, we learn another hot topic of LLMs: Memory and Rag. Continue learning [here](./04_Memory101.ipynb)!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.15"
}
},
"nbformat": 4,
"nbformat_minor": 4
}