Tools#
Tools allows LLM to interact with the environment. Tooling is probably is the most important feature of the framework.
from langchain_core.tools import tool
from langchain_ollama import ChatOllama
model = ChatOllama(model="llama3.1")
Defining#
Tools implement how LLMs can interact with external systems. In Lang Chain, tools can take various forms, which are described in the Tool interface section.
Check full guide in Tools.
The most common way to define the tools is to use the @tool decorator. According to Lang Chain, the tool wrapped object gets all properties of the “tool interaface”.
The following cell defines the tool.
@tool
def my_tool(a: int, b: str) -> float:
"""This is my tool"""
return 4.20
The important attributes for Langchain’s internal processes are presented below.
my_tool.name
'my_tool'
my_tool.description
'This is my tool'
my_tool.args
{'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'string'}}
Formats#
Consider how the tools modify the the model’s behaviour. The tools are converted into a special JSON schema that describes the output format from that unambiguosly describes the output format, enabling you to understand which tool is begin called and what arguments are passed to it.
The following cell binds two simple tools to the model.
@tool
def convert_data(a: list[str]) -> bool:
"""
Converts data to the special format.
"""
return True
@tool
def get_data(page: int) -> str:
"""
Get the data. From given page.
"""
return "hello"
with_tools = ChatOllama(model="llama3.1").bind_tools([convert_data, get_data])
The output format that model will expose to the llm provider you can get from the kwargs["tools"].
with_tools.kwargs["tools"]
[{'type': 'function',
'function': {'name': 'convert_data',
'description': 'Converts data to the special format.',
'parameters': {'properties': {'a': {'items': {'type': 'string'},
'type': 'array'}},
'required': ['a'],
'type': 'object'}}},
{'type': 'function',
'function': {'name': 'get_data',
'description': 'Get the data. From given page.',
'parameters': {'properties': {'page': {'type': 'integer'}},
'required': ['page'],
'type': 'object'}}}]
Therefore, the model’s output corresponds to the schemas provided to Ollamaw:.
ans = with_tools.invoke(
"I need the data from page 20"
)
ans.tool_calls
[{'name': 'get_data',
'args': {'page': 20},
'id': '85e3e97c-55cd-486e-8f58-ac7aaf5555b3',
'type': 'tool_call'}]
Params description#
The instrument paradigm provides a method for specifying instrument parameter descriptions. In LangChain, you can use the following methods to leverage this approach:
Annotated(Recommended)
Use standard Python typing.
def func(arg: Annotated[str, "Description here"]): ...
Pydantic
Field(Robust)
Best for adding validation (min/max/regex) alongside descriptions.
def func(arg: Annotated[str, Field(description="...", min_length=1)]): ...
Google-Style Docstrings (Legacy)
Implicitly parsed from the function’s docstring.
def func(arg):
"""
Args:
arg: Description here
"""
args_schema(Explicit)
Define a separate Pydantic model and link it when creating the tool manually (e.g., via StructuredTool).
class Input(BaseModel):
arg: str = Field(description="...")
tool = StructuredTool.from_function(..., args_schema=Input)
The following cell uses Python typing to define the description of the parameter.
from typing import Annotated
@tool
def my_tool(
val: Annotated[int, "Description of the parameter"]
) -> int:
"""
Description of the tool.
"""
return 10
tooled_model = model.bind_tools([my_tool])
So in the “tools” attribute of the tooled model you can find how the parameter is configured.
tooled_model.kwargs["tools"]
[{'type': 'function',
'function': {'name': 'my_tool',
'description': 'Description of the tool.',
'parameters': {'properties': {'val': {'description': 'Description of the parameter',
'type': 'integer'}},
'required': ['val'],
'type': 'object'}}}]
Binding tools#
Tools are usually provided to the model via a special attribute in the body. The provider allocates the tools them according to the rules the model was trained to. Langchain certainly hides the details of API interaction under unified interface. You must call the model’s bind_tools method and provide the necessary tool information there.
The following cell provides the information about the tools to the model, using different approaches:
Passing the function decorated with the
tool.And raw declaration of the tool using corresponding format.
@tool
def from_function():
"Dummy tool"
return None
tooled_model = model.bind_tools([
from_function,
{
"type": "function",
"function": {
"name": "from_json",
"description": "Another dummy",
"parameters": {"properties": {}, "type": "object"},
}
}
])
As a result, both tools will presented in the OpenAI’s API format.
tooled_model.kwargs["tools"]
[{'type': 'function',
'function': {'name': 'from_function',
'description': 'Dummy tool',
'parameters': {'properties': {}, 'type': 'object'}}},
{'type': 'function',
'function': {'name': 'from_json',
'description': 'Another dummy',
'parameters': {'properties': {}, 'type': 'object'}}}]
The following cell triggers the model to call both tools to demonstrate their validity from the model’s perspecitive.
ans = tooled_model.invoke("Call all the tools available to you")
ans.tool_calls
[{'name': 'from_function',
'args': {},
'id': 'a9aa29d8-dd37-424b-9d50-82471b8b2ec3',
'type': 'tool_call'},
{'name': 'from_json',
'args': {},
'id': 'cfc235b6-0bc5-4b1d-821e-c0a8bab758e0',
'type': 'tool_call'}]