Tool calling in artificial intelligence (AI) is a concept that refers to the ability of language models to interact with external tools to perform specific actions. This functionality allows models to go beyond simple text generation, allowing them to integrate, execute and automate tasks using a variety of tools and services. In this article, we will explore how to implement and use tools with LangChain.
If you haven’t already done so and are new to this framework, I suggest you read the previous help articles on LangChain.
Implement a tool with LangChain
In this tutorial we will create a tool that allows the AI to read and summarize the blog articles. The first thing to do is therefore to define a Python function that allows you to make an HTTP call and retrieve the content of the web page:
from langchain_core.tools import tool
import urllib.request
from bs4 import BeautifulSoup
@tool
def get_article(url:str) -> str:
"""Retrieve an article from the web starting from the URL"""
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html, features="html.parser")
text = soup.get_text()
return text
As you can see, it is a very simple function that retrieves the content of a URL and extracts the content in text format. The only differences are the following:
- The function has been marked with the
@tool
decorator which indicates that theget_article
function is a tool that can be used by the AI model. - On the first line we have added a description of the function according to the standard already seen in the previous article on how to use structured data with LangChain. This description is essential to allow the model to invoke the function at the right time.
Use the tools
To test function calling we will use OpenA’s GPT-4o model:
...
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, ToolMessage
...
def invoke_with_tools(prompt:str):
tools = [get_article]
messages = [HumanMessage(prompt)]
llm = ChatOpenAI(model="gpt-4o")
llm_with_tools = llm.bind_tools(tools)
ai_msg = llm_with_tools.invoke(prompt)
messages.append(ai_msg)
for tool_call in ai_msg.tool_calls:
selected_tool = {"get_article": get_article}[tool_call["name"]]
tool_output = selected_tool.invoke(tool_call["args"])
messages.append(ToolMessage(tool_output, tool_call_id=tool_call["id"]))
messages.append(llm_with_tools.invoke(messages))
return messages
def main():
response = invoke_with_tools("You can summarize in a single row the article http://www.devturtleblog.com/langchain-structured-json/ ?")
print(response)
if __name__ == "__main__":
main()
By providing the model with the URL of an article and asking it to summarize the content, the AI will be able to understand that it should use the tool to retrieve the content of the page. To better understand this mechanism, before commenting further on the code, we must look at the messages that are generated by the program:
HumanMessage(
content='You can summarize in a single row the article http://www.devturtleblog.com/langchain-structured-json/ ?'
),
AIMessage(
content='',
additional_kwargs={
'tool_calls': [{
'id': 'call_kOFu8D2fKgctD0I2TuiFb5Nj',
'function': {
'arguments': '{"url":"http://www.devturtleblog.com/langchain-structured-json/"}',
'name': 'get_article'
},
'type': 'function'
}]
},
response_metadata={
...
},
id='run-cc9ea039-066b-4f7b-a0d9-f1ab090bbb35-0',
tool_calls=[{
'name': 'get_article',
'args': {'url': 'http://www.devturtleblog.com/langchain-structured-json/'},
'id': 'call_kOFu8D2fKgctD0I2TuiFb5Nj'
}],
usage_metadata={
...
}
),
ToolMessage(
content='\n\nWe have already seen how to use LangChain for creating LLM-based applications ...',
tool_call_id='call_kOFu8D2fKgctD0I2TuiFb5Nj'
),
AIMessage(
content='The article from Dev Turtle Blog discusses using LangChain to generate structured JSON responses, highlighting the benefits of JSON for readability, compatibility, flexibility, and integration. It explains how to define models in Python using Pydantic for strong typing, data validation, and serialization. The article provides an example of creating a social media post model and demonstrates how to use it with LangChain to produce structured outputs, facilitating easier integration of language models into modern applications.',
response_metadata={
...
},
id='run-afef2163-d8b7-42bd-a209-6a8c950f6354-0',
usage_metadata={'input_tokens': 1003, 'output_tokens': 90, 'total_tokens': 1093}
)]
As you can see, following the input prompt, the AI generates an AIMessage
in which it informs us that it is necessary to invoke the tool. The details of the message also indicate the values to be passed as input to the tool to obtain the desired response.
The actual call to the tool is not performed directly by the model but we had to implement a loop which, for each tool to be invoked, makes the call and adds a response message of type ToolMessage
:
...
for tool_call in ai_msg.tool_calls:
selected_tool = {"get_article": get_article}[tool_call["name"]]
tool_output = selected_tool.invoke(tool_call["args"])
messages.append(ToolMessage(tool_output, tool_call_id=tool_call["id"]))
...
This code snippet is the basis of the tool calling mechanism and can be reused in any future application. The operation is very simple and does nothing more than recover the name of the tool and the parameters to be passed as input from the output generated by the model.
If there are multiple tools, the first statement of the cycle must be modified as follows:
selected_tool = {"tool_a": tool_a, "tool_b": tool_b}[tool_call["name"]]
Each function is thus associated with a name which allows us to identify which tool to select.
At the end of the executions, the LLM is invoked again which uses the previous messages to formulate the final response containing the summary of the article.
The potential of tool calling
As you can easily imagine, tool calling has a wide range of practical applications as it allows you to integrate AI models with deterministic logic, obtaining the benefits of both approaches. For example, it is possible to invoke APIs, retrieve information from external databases or provide the model with calculation algorithms to process the information received as input via natural language.
It is therefore a real innovation that allows the creation of intelligent agents capable of orchestrating parts of software implemented in a traditional way.