Chapter 2 — Working with Tools¶
Setup Instructions¶
To ensure you have the required dependencies to run this notebook, you'll need to have our llm-agents-from-scratch framework installed on the running Jupyter kernel. To do this, you can launch this notebook with the following command while within the project's root directory:
uv run --with jupyter jupyter lab
Alternatively, if you just want to use the published version of llm-agents-from-scratch without local development, you can install it from PyPi by uncommenting the cell below.
In [1]:
Copied!
# Uncomment the line below to install `llm-agents-from-scratch` from PyPi
# !pip install llm-agents-from-scratch
# Uncomment the line below to install `llm-agents-from-scratch` from PyPi
# !pip install llm-agents-from-scratch
Examples¶
Example 1: Creating a ToolCall object¶
In [2]:
Copied!
from llm_agents_from_scratch.data_structures.tool import ToolCall
croissant_tool_call = ToolCall(
tool_name="web-search-tool",
arguments={
"query": "Croissant bakeries in New York City and their prices.",
},
)
from llm_agents_from_scratch.data_structures.tool import ToolCall
croissant_tool_call = ToolCall(
tool_name="web-search-tool",
arguments={
"query": "Croissant bakeries in New York City and their prices.",
},
)
In [3]:
Copied!
croissant_tool_call
croissant_tool_call
Out[3]:
ToolCall(id_='77148f15-74d5-4b38-9e9f-d39620bb7031', tool_name='web-search-tool', arguments={'query': 'Croissant bakeries in New York City and their prices.'})
Example 2: Creating a ToolCallResult object¶
In [4]:
Copied!
from llm_agents_from_scratch.data_structures.tool import ToolCallResult
result = ToolCallResult(
tool_call_id=croissant_tool_call.id_,
content={
"search_results": {
"hits": [
{"data": "..."},
],
},
},
)
from llm_agents_from_scratch.data_structures.tool import ToolCallResult
result = ToolCallResult(
tool_call_id=croissant_tool_call.id_,
content={
"search_results": {
"hits": [
{"data": "..."},
],
},
},
)
In [5]:
Copied!
result
result
Out[5]:
ToolCallResult(tool_call_id='77148f15-74d5-4b38-9e9f-d39620bb7031', content={'search_results': {'hits': [{'data': '...'}]}}, error=False)
Example 3: The Hailstone Tool¶
In [6]:
Copied!
from typing import Any
from llm_agents_from_scratch.base.tool import BaseTool
from llm_agents_from_scratch.data_structures.tool import (
ToolCall,
ToolCallResult,
)
class Hailstone(BaseTool): # A
@property
def name(self) -> str:
return "hailstone"
@property
def description(self) -> str:
return "A tool that performs a Hailstone step on a given input number."
@property
def parameters_json_schema(self) -> dict[str, Any]:
"""JSON Schema for tool parameters."""
return {
"type": "object",
"properties": {
"x": {
"type": "number",
"description": "The input number.",
},
},
"required": ["x"],
}
def __call__(
self,
tool_call: ToolCall,
*args: Any,
**kwargs: Any,
) -> ToolCallResult:
"""Execute the tool call."""
x = tool_call.arguments.get("x")
if x % 2 == 0:
result = x // 2
else:
result = (x * 3) + 1
return ToolCallResult(
tool_call_id=tool_call.id_,
content=result,
error=False,
)
from typing import Any
from llm_agents_from_scratch.base.tool import BaseTool
from llm_agents_from_scratch.data_structures.tool import (
ToolCall,
ToolCallResult,
)
class Hailstone(BaseTool): # A
@property
def name(self) -> str:
return "hailstone"
@property
def description(self) -> str:
return "A tool that performs a Hailstone step on a given input number."
@property
def parameters_json_schema(self) -> dict[str, Any]:
"""JSON Schema for tool parameters."""
return {
"type": "object",
"properties": {
"x": {
"type": "number",
"description": "The input number.",
},
},
"required": ["x"],
}
def __call__(
self,
tool_call: ToolCall,
*args: Any,
**kwargs: Any,
) -> ToolCallResult:
"""Execute the tool call."""
x = tool_call.arguments.get("x")
if x % 2 == 0:
result = x // 2
else:
result = (x * 3) + 1
return ToolCallResult(
tool_call_id=tool_call.id_,
content=result,
error=False,
)
Invoking the Hailstone tool:
In [7]:
Copied!
hailstone_tool = Hailstone()
tool_call = ToolCall(
tool_name="hailstone",
arguments={"x": 3},
)
tool_call_result = hailstone_tool(tool_call)
print(tool_call_result)
hailstone_tool = Hailstone()
tool_call = ToolCall(
tool_name="hailstone",
arguments={"x": 3},
)
tool_call_result = hailstone_tool(tool_call)
print(tool_call_result)
tool_call_id='935bde41-5805-4bbe-9828-93b06625ab36' content=10 error=False
Example 4: The Hailstone step function (to be used in SimpleFunctionTool)¶
In [8]:
Copied!
def hailstone_step_func(x: int) -> int:
"""Performs a single step of the Hailstone sequence."""
if x % 2 == 0:
return x // 2
return 3 * x + 1
def hailstone_step_func(x: int) -> int:
"""Performs a single step of the Hailstone sequence."""
if x % 2 == 0:
return x // 2
return 3 * x + 1
Example 5: Hailstone step function as a SimpleFunctionTool¶
In [9]:
Copied!
from llm_agents_from_scratch.tools.simple_function import SimpleFunctionTool
# convert our Python function to a BaseTool
hailstone_tool = SimpleFunctionTool(hailstone_step_func)
print(hailstone_tool.name)
print(hailstone_tool.description)
print(hailstone_tool.parameters_json_schema)
from llm_agents_from_scratch.tools.simple_function import SimpleFunctionTool
# convert our Python function to a BaseTool
hailstone_tool = SimpleFunctionTool(hailstone_step_func)
print(hailstone_tool.name)
print(hailstone_tool.description)
print(hailstone_tool.parameters_json_schema)
hailstone_step_func
Performs a single step of the Hailstone sequence.
{'type': 'object', 'properties': {'x': {'type': 'number'}}, 'required': ['x']}
Example 6: Running the previous Hailstone tool_call with the alternative SimpleFunctionTool implementation¶
In [10]:
Copied!
from llm_agents_from_scratch.data_structures import ToolCall
tool_call = ToolCall(
tool_name="hailstone_fn",
arguments={"x": 3},
)
res = hailstone_tool(tool_call)
from llm_agents_from_scratch.data_structures import ToolCall
tool_call = ToolCall(
tool_name="hailstone_fn",
arguments={"x": 3},
)
res = hailstone_tool(tool_call)
In [11]:
Copied!
res
res
Out[11]:
ToolCallResult(tool_call_id='b37fa814-8aa4-49a3-9037-b3c73d9817a5', content='10', error=False)
Example 7: Example usage of PydanticFunctionTool¶
In [12]:
Copied!
from pydantic import BaseModel
class MyFuncParams(BaseModel):
x: int
def my_func(params: MyFuncParams) -> int:
print(params.x)
from pydantic import BaseModel
class MyFuncParams(BaseModel):
x: int
def my_func(params: MyFuncParams) -> int:
print(params.x)
In [13]:
Copied!
from llm_agents_from_scratch.tools.pydantic_function import PydanticFunctionTool
tool = PydanticFunctionTool(my_func)
from llm_agents_from_scratch.tools.pydantic_function import PydanticFunctionTool
tool = PydanticFunctionTool(my_func)
In [14]:
Copied!
tool
tool
Out[14]:
<llm_agents_from_scratch.tools.pydantic_function.PydanticFunctionTool at 0x71ba2da6c590>