A thorough understanding of the agent's tool call based on ReAct

In-depth exploration of how AI agents can use ReAct to implement tool calls and improve autonomy and task execution efficiency.
Core content:
1. The definition of AI agents and their technical composition
2. The application of function calling in agents and its limitations
3. The basics of ReAct and its role and implementation steps in tool calls
Preface
AI agents are software or hardware entities that have a certain degree of autonomy, can perceive the environment, and perform specific tasks through intelligent decision-making. It combines artificial intelligence technologies (such as machine learning, natural language processing, computer vision, etc.) and can achieve goals independently or collaboratively.
Function Calling based on the Large Language Model (LLM) enables intelligent agents to use tools effectively and interact with external APIs. Models that support Function Calling (such as gpt-4, qwen-plus, etc.) can detect when a function needs to be called and output the function name and required parameters of the called function in JSON format.
However, not all LLM models support Function Calling (such as deepseel-v3) . For models that do not support Function Calling, ReAct's relatively complex prompt word engineering can be used to require the model to return a response in a specific format in order to distinguish different stages (thinking, action, observation).
Tool calls have two main purposes:
Get data:
For example, retrieving content from a knowledge base based on keywords and obtaining business data through a specific API interface Execution Action:
For example, modify business status data and execute scheduled business operations through API interfaces
This article contains the following content:
ReAct Basics Detailed introduction to the ReAct-based tool calling process and the interactive messages involved Hand-rolled Agent code to implement ReAct-based tool calls
ReAct Basics
ReAct is derived from a classic paper: REACT: SYNERGIZING REASONING AND ACTING IN LANGUAGE MODELS
(Link: https://arxiv.org/pdf/2210.03629 )
In order to solve the problem, the ReAct-based agent needs to go through several stages.
Thought: Thinking and Reasoning Action: Take action and decide which tools and parameters to call Observation: The result of the action (tool output)
The above three stages may be iterated multiple times until the problem is solved or the upper limit of the iteration number is reached.
ReAct-based tool calls rely on complex prompt word engineering. The system prompt words refer to the langchain template:
Answer the following questions as best you can. You have access to the following tools:
{tool_strings}
The way you use the tools is by specifying a json blob.
Specifically, this json should have a `action` key (with the name of the tool to use ) and a `action_input` key (with the input to the tool going here).
The only values that should be in the "action" field are: {tool_names}
The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB:
```
{{{{
"action": $TOOL_NAME,
"action_input": $INPUT
}}}}
` ``
ALWAYS use the following format :
Question: the input question you must answer
Thought: you should always think about what to do
Action:
```
$JSON_BLOB
` ``
Observation: the result of the action
... (this Thought/Action/Observation can repeat N times )
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin! Reminder to always use the exact characters `Final Answer` when responding.
Tool calling process and interactive messages based on ReAct
Let’s take the weather query in Beijing and Guangzhou as an example. LLM uses Alibaba Cloud’sDeepSeek-v3
The process of querying weather is as follows:
1. Initiate a query request
When inquiring LLM, there are 2 messages in the messages list:
The first role is system
, defines system prompt words (including tool definitions)The second role is user
, contains the following:Question: What is the weather like in Beijing and Guangzhou?
We use curl to initiate a POST request. The JSON structure of the body can be found at https://platform.openai.com/docs/api-reference/chat/create .
In the request
stop
The field needs to be set toObservation:
Otherwise, LLM will directly output the entire Thought/Action/Observation process and give a fictitious final answer. We only need LLM to output Thought/Action.
# !/ bin / bash
export OPENAI_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
export OPENAI_API_KEY = "sk-xxx" # Replace with your key
curl ${ OPENAI_BASE_URL } /chat/ completions \
-H "Content-Type: application/json " \
- H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model" : "deepseek-v3" ,
"messages" : [
{
"role" : "system" ,
"content" : " \n Answer the following questions as best you can. You have access to the following tools: \n { \" name \" : \" get_weather \" , \" description \" : \" Get weather \" , \" parameters \" : { \" type \" : \" object \" , \" properties \" : { \" location \" : { \" type \" : \" string \" , \" description \" : \" the name of the location \" }}, \" required \" : [ \" location \" ]}} \n\n\n The way you use the tools is by specifying a json blob. \n Specifically, this json should have a `action` key (with the name of the tool to use) and a `action_input` key (with the input to the tool going here). \n\n The only values that should be in the \" action \" field are: get_weather \n\n The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB: \n\n `` \n {{ \n\" action \" : $TOOL_NAME, \n\" action_input \" : $INPUT \n }} \n `` \n\n ALWAYS use the following format: \n\n Question: the input question you must answer \n Thought: you should always think about what to do \n Action: \n ``` \n $JSON_BLOB \n ``` \n Observation: the result of the action \n ... (this Thought/Action/Observation can repeat N times) \n Thought: I now know the final answer \n Final Answer: the final answer to the original input question \n\n\n Begin! Reminder to always use the exact characters `Final Answer` when responding. \n "
},
{
"role" : "user" ,
"content" : "Question: What's the weather like in Beijing and Guangzhou \n\n "
}
],
"stop" : "Observation:"
}'
2. LLM returns to Action to obtain Beijing weather
After reasoning, LLM found that it was necessary to call a function to obtain Beijing's weather first.
Thought: I need to get weather information for Beijing and Guangzhou. First, I will get the weather in Beijing. Action:```{ "action": "get_weather", "action_input": { "location": "Beijing" }}```
The complete JSON response is as follows:
{ "choices": [ { "message": { "content": "Thought: I need to get weather information for Beijing and Guangzhou. First, I will get the weather in Beijing.\n\nAction:\n```\n{\n \"action\": \"get_weather\",\n \"action_input\": {\n \"location\": \"北京\"\n }\n}\n```", "role": "assistant" }, "finish_reason": "stop", "index": 0, "logprobs": null } ], "object": "chat.completion", "usage": { "prompt_tokens": 305, "completion_tokens": 49, "total_tokens": 354 }, "created": 1745651748, "system_fingerprint": null, "model": "deepseek-v3", "id": "chatcmpl-697b0627-4fca-975b-954c-7304386ac224"}
3. Processing function call to obtain Beijing weather
Parse and process the LLM Action to obtain the function name and parameter list, and call the corresponding API interface to obtain the result.
For example: throughhttp://weather.cma.cn/api/now/54511
Weather conditions in Beijing are available.
The complete JSON response is as follows:
{ "msg": "success", "code": 0, "data": { "location": { "id": "54511", "name": "北京", "path": "北京, China, 北京" }, "now": { "precipitation": 0.0, "temperature": 23.4, "pressure": 1005.0, "humidity": 43.0, "windDirection": "Southwest", "windDirectionDegree": 216.0, "windSpeed": 2.7, "windScale": "Breeze", "feelst": 23.1 }, "alarm": [], "jieQi": "", "lastUpdate": "2025/04/26 15:00" }}
4. Send context information and function call results to LLM
The message list sent to LLM contains 2 messages:
The first role is system
, defines system prompt words (including tool definitions)The second role is user
, contains the following:Question: What is the weather like in Beijing and Guangzhou? Thought: I need to get weather information for Beijing and Guangzhou. First, I will get the weather in Beijing Action: {"action":"get_weather","action_input":{"location":"Beijing"}} Observation: Tool call get_weather('Beijing')
Results
# !/ bin / bash
export OPENAI_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
export OPENAI_API_KEY = "sk-xxx" # Replace with your key
curl ${ OPENAI_BASE_URL } /chat/ completions \
-H "Content-Type: application/json " \
- H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model" : "deepseek-v3" ,
"messages" : [
{
"role" : "system" ,
"content" : " \n Answer the following questions as best you can. You have access to the following tools: \n { \" name \" : \" get_weather \" , \" description \" : \" Get weather \" , \" parameters \" : { \" type \" : \" object \" , \" properties \" : { \" location \" : { \" type \" : \" string \" , \" description \" : \" the name of the location \" }}, \" required \" : [ \" location \" ]}} \n\n\n The way you use the tools is by specifying a json blob. \n Specifically, this json should have a `action` key (with the name of the tool to use) and a `action_input` key (with the input to the tool going here). \n\n The only values that should be in the \" action \" field are: get_weather \n\n The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB: \n\n `` \n {{ \n\" action \" : $TOOL_NAME, \n\" action_input \" : $INPUT \n }} \n `` \n\n ALWAYS use the following format: \n\n Question: the input question you must answer \n Thought: you should always think about what to do \n Action: \n ``` \n $JSON_BLOB \n ``` \n Observation: the result of the action \n ... (this Thought/Action/Observation can repeat N times) \n Thought: I now know the final answer \n Final Answer: the final answer to the original input question \n\n\n Begin! Reminder to always use the exact characters `Final Answer` when responding. \n "
},
{
"role" : "user" ,
} , \" now \" : { \" precipitation \" :0, \" temperature \" :23.4, \ " current hour \" :10.75, \" precipitation \" :0.1, \" temperature \" :23.6, \" current hour \" :10.6, \" precipitation \" :0.0, \" temperature \" :23.9 , \ " current hour \ " : 10.6 , \ " precipitation \ " :0.1 , \" temperature \" : 23.8, \" current hour \ " :10.6 , \" precipitation \" :0.0, \" temperature \" :23.7, \" current hour \" :10.6 , \ " precipitation \" : 0.0 , \" temperature \" : 23.9 , \" current hour \ " : 10.75 , \" precipitation \" :0.0, \ " temperature \" : 23.8 , \ " current hour \ " : 10.6, \" precipitation \ " : 0.0 , \" temperature \" : 23.9, \" current hour \" : 10.6 , \" precipitation \" :0.0 , \ " temperature \" : 23.8 , \" current hour \" : 10.6, \" precipitation \" :0.0 , \" temperature \" :23.8, \" current hour \" : 10.6, \" precipitation \" :0.0, \" temperature \" :23.9, \ " \" pressure \" :1005.0, \" humidity \" :43.0, \" windDirection \" : \" southwest wind \" , \" windDirectionDegree \" :216.0, \" windSpeed \" :2.7, \" windScale \" : \" breeze \" , \" feelst \" :23.1}, \" alarm \" :[], \" jieQi \" : \"\" , \" lastUpdate \" : \" 2025/04/26 15:00 \" }} \n "
}
],
"stop" : "Observation:"
}'
5. LLM returns to Action to obtain Guangzhou weather
After reasoning, LLM found that it was necessary to call a function to obtain the weather in Guangzhou.
Thought: I have already obtained the weather information for Beijing. Next, I will obtain the weather information for Guangzhou. Action:```{ "action": "get_weather", "action_input": { "location": "Guangzhou" }}```
The complete JSON response is as follows:
{ "choices": [ { "message": { "content": "Thought: I have already obtained the weather information for Beijing. Next, I will obtain the weather information for Guangzhou.\n\nAction:\n```\n{\n\"action\": \"get_weather\",\n\"action_input\": {\n\"location\": \"Guangzhou\"\n}\n}\n```\nObservation", "role": "assistant" }, "finish_reason": "stop", "index": 0, "logprobs": null } ], "object": "chat.completion", "usage": { "prompt_tokens": 472, "completion_tokens": 46, "total_tokens": 518 }, "created": 1745651861, "system_fingerprint": null, "model": "deepseek-v3", "id": "chatcmpl-a822b8d7-9105-9dc2-8e98-4327afb50b3a"}
6. Processing function call to obtain Guangzhou weather
Parse and process the LLM Action to obtain the function name and parameter list, and call the corresponding API interface to obtain the result.
For example: throughhttp://weather.cma.cn/api/now/59287
Weather conditions in Guangzhou are available.
The complete JSON response is as follows:
{ "msg": "success", "code": 0, "data": { "location": { "id": "59287", "name": "Guangzhou", "path": "China, Guangdong, Guangzhou" }, "now": { "precipitation": 0.0, "temperature": 24.2, "pressure": 1005.0, "humidity": 79.0, "windDirection": "Northeast Wind", "windDirectionDegree": 31.0, "windSpeed": 1.3, "windScale": "Breeze", "feelst": 27.1 }, "alarm": [], "jieQi": "", "lastUpdate": "2025/04/26 15:00" }}
7. Send context information and function call results to LLM
The message list sent to LLM contains 2 messages:
The first role is system
, defines system prompt words (including tool definitions)The second role is user
, contains the following:Question: What is the weather like in Beijing and Guangzhou? Thought: I need to get weather information for Beijing and Guangzhou. First, I will get the weather in Beijing Action: {"action":"get_weather","action_input":{"location":"Beijing"}} Observation: Tool call get_weather('Beijing')
ResultsThought: Now that I have obtained the weather information for Beijing, I will obtain the weather information for Guangzhou next. Action: {"action":"get_weather","action_input":{"location":"Guangzhou"}} Observation: Tool call get_weather('Guangzhou')
Results
# !/ bin / bash
export OPENAI_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
export OPENAI_API_KEY = "sk-xxx" # Replace with your key
curl ${ OPENAI_BASE_URL } /chat/ completions \
-H "Content-Type: application/json " \
- H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model" : "deepseek-v3" ,
"messages" : [
{
"role" : "system" ,
"content" : " \n Answer the following questions as best you can. You have access to the following tools: \n { \" name \" : \" get_weather \" , \" description \" : \" Get weather \" , \" parameters \" : { \" type \" : \" object \" , \" properties \" : { \" location \" : { \" type \" : \" string \" , \" description \" : \" the name of the location \" }}, \" required \" : [ \" location \" ]}} \n\n\n The way you use the tools is by specifying a json blob. \n Specifically, this json should have a `action` key (with the name of the tool to use) and a `action_input` key (with the input to the tool going here). \n\n The only values that should be in the \" action \" field are: get_weather \n\n The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB: \n\n `` \n {{ \n\" action \" : $TOOL_NAME, \n\" action_input \" : $INPUT \n }} \n `` \n\n ALWAYS use the following format: \n\n Question: the input question you must answer \n Thought: you should always think about what to do \n Action: \n ``` \n $JSON_BLOB \n ``` \n Observation: the result of the action \n ... (this Thought/Action/Observation can repeat N times) \n Thought: I now know the final answer \n Final Answer: the final answer to the original input question \n\n\n Begin! Reminder to always use the exact characters `Final Answer` when responding. \n "
},
{
"role" : "user" ,
} , \" now \" : { \" precipitation \" :0, \" temperature \" :23.4, \ " current hour \" :10.75, \" precipitation \" :0.1, \" temperature \" :23.6, \" current hour \" :10.6, \" precipitation \" :0.0, \" temperature \" :23.9 , \ " current hour \ " : 10.6 , \ " precipitation \ " :0.1 , \" temperature \" : 23.8, \" current hour \ " :10.6 , \" precipitation \" :0.0, \" temperature \" :23.7, \" current hour \" :10.6 , \ " precipitation \" : 0.0 , \" temperature \" : 23.9 , \" current hour \ " : 10.75 , \" precipitation \" :0.0, \ " temperature \" : 23.8 , \ " current hour \ " : 10.6, \" precipitation \ " : 0.0 , \" temperature \" : 23.9, \" current hour \" : 10.6 , \" precipitation \" :0.0 , \ " temperature \" : 23.8 , \" current hour \" : 10.6, \" precipitation \" :0.0 , \" temperature \" :23.8, \" current hour \" : 10.6, \" precipitation \" :0.0, \" temperature \" :23.9, \ " \" pressure \" :1005.0, \" humidity \" :43.0, \" windDirection \" : \" Southwest wind \" , \" windDirectionDegree \" :216.0, \" windSpeed \" :2.7, \" windScale \" : \" Breeze \" , \" feelst \" :23.1}, \" alarm \" :[], \" jieQi \" : \"\" , \" lastUpdate \" : \" 2025/04/26 15:00 \" }} \n Thought: Now that I have obtained the weather information of Beijing, I will get the weather information of Guangzhou next. \n\n Action: \n ``` \n { \n\" action \" : \" get_weather \" , \n\" action_input \" : { \n\" location \" : \" Guangzhou \"\n } \n} \n ``` \n Observation \n Observation: { \" msg \" : \" success \" , \" code \" :0, \" data \" :{ \" location \" :{ \" id \" : \" 59287 \" , \" name \" : \" Guangzhou \" , \" path \" : \" China, Guangdong, Guangzhou \" }, \" now \" :{ \" precipitation \" :0.0, \" temperature \" :24.2, \" pressure \" :1005.0, \" humidity \" :79.0, \" windDirection \" : \" Northeast wind \" , \" windDirectionDegree \" :31.0, \" windSpeed \" :1.3, \" windScale \" : \" Breeze \" , \" feelst \" :27.1}, \" alarm \" :[], \" jieQi \" : \"\" , \" lastUpdate \" : \" 2025/04/26 15:00 \" }} \n "
}
],
"stop" : "Observation:"
}'
8. LLM generates final response
LLM generates the final response:
Thought : I have obtained the weather information for Beijing and Guangzhou, and now I can answer users' questions.
Final Answer: The temperature in Beijing is 23.4 ° C , the humidity is 43 %, the wind direction is southwesterly, and the wind speed is 2.7 m /s . The temperature in Guangzhou is 24.2 ° C , the humidity is 79 %, the wind direction is northeasterly, and the wind speed is 1.3 m /s.
The complete JSON response is as follows:
{ "choices": [ { "message": { "content": "Thought: I have obtained the weather information of Beijing and Guangzhou. Now I can answer the user's question.\n\nFinal Answer: The weather temperature in Beijing is 23.4°C, the humidity is 43%, the wind direction is southwest, and the wind speed is 2.7m/s. The weather temperature in Guangzhou is 24.2°C, the humidity is 79%, the wind direction is northeast, and the wind speed is 1.3m/s.", "role": "assistant" }, "finish_reason": "stop", "index": 0, "logprobs": null } ], "object": "chat.completion", "usage": { "prompt_tokens": 641, "completion_tokens": 79, "total_tokens": 720 }, "created": 1745652025, "system_fingerprint": null, "model": "deepseek-v3", "id": "chatcmpl-d9b85f31-589e-9c6f-8694-cf813344e464"}
Hand-rolled Agent code to implement ReAct-based tool calls
1. Create a Python environment
uv init agent
cd agent
uv venv
.venv \ Scripts \ activate
uv add openai requests python-dotenv
2. Set up your API Key
Create .env, the content of .env is as follows (note to change OPENAI_API_KEY to your key)
OPENAI_API_KEY=your_api_key_here
OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
Add .env to .gitignore
3. Implement Agent code
The pseudo code logic of implementing ReAct agent based on OpenAI SDK is as follows:
maxIter = 5 # maximum number of iterations agent_scratchpad = "" # agent thinking process (Thought/Action/Observation) for iterSeq in range(1, maxIter+1): Construct chat completion request There are 2 messages The first one is the system prompt message (including tool definition) The second one is the user message: Question + agent thinking process (Thought/Action/Observation) Set the stop parameter to "Observation:" Get the chat completion result If the chat completion result contains "Final Answer:" Return the final answer If the chat completion result contains Action Parse and call the corresponding function Update the agent thinking process: add the output of this LLM (Though/Action) and the tool call result (Observation) to agent_scratchpad Continue iterating
The complete main.py code is as follows:
import json
import re
import requests
import urllib.parse
from typing import Iterable
from openai import OpenAI
from openai.types.chat.chat_completion_message_param import ChatCompletionMessageParam
from openai.types.chat.chat_completion_user_message_param import (
ChatCompletionUserMessageParam,
)
from openai.types.chat.chat_completion_system_message_param import (
ChatCompletionSystemMessageParam,
)
# Load environment variables
from dotenv import load_dotenv
load_dotenv()
client = OpenAI()
model = "deepseek-v3"
# Tool definition
tools = [
{
"type" : "function" ,
"function" : {
"name" : "get_weather" ,
"description" : "Get weather" ,
"parameters" : {
"type" : "object" ,
"properties" : {
"location" : { "type" : "string" , "description" : "location" }
},
"required" : [ "location" ],
},
},
}
]
# System prompt words
def get_system_prompt ():
tool_strings = "\n" .join([json.dumps(tool[ "function" ]) for tool in tools])
tool_names = ", " .join([tool[ "function" ][ "name" ] for tool in tools])
systemPromptFormat = """
Answer the following questions as best you can. You have access to the following tools:
{tool_strings}
The way you use the tools is by specifying a json blob.
Specifically, this json should have a `action` key (with the name of the tool to use) and a `action_input` key (with the input to the tool going here).
The only values that should be in the "action" field are: {tool_names}
The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB:
```
{{{{
"action": $TOOL_NAME,
"action_input": $INPUT
}}}}
```
ALWAYS use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action:
```
$JSON_BLOB
```
Observation: the result of the action
... (this Thought/Action/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin! Reminder to always use the exact characters `Final Answer` when responding.
"""
return systemPromptFormat. format (tool_strings=tool_strings, tool_names=tool_names)
# Get the weather
def get_weather ( location: str ) -> str :
url = "http://weather.cma.cn/api/autocomplete?q=" + urllib.parse.quote(location)
response = requests.get(url)
data = response.json()
if data[ "code" ] != 0 :
return "No information found for this location"
location_code = ""
for item in data[ "data" ]:
str_array = item.split( "|" )
if (
str_array[ 1 ] == location
or str_array[ 1 ] + "city" == location
or str_array[ 2 ] == location
):
location_code = str_array[ 0 ]
break
if location_code == "" :
return "No information found for this location"
url = f"http://weather.cma.cn/api/now/ {location_code} "
return requests.get(url).text
# Implement tool calls
def invoke_tool ( toolName: str , toolParamaters ) -> str :
result = ""
if toolName == "get_weather" :
result = get_weather(toolParamaters[ "location" ])
else :
result = f"Function {toolName} is not defined"
return result
def main ():
query = "What's the weather like in Beijing and Guangzhou?"
systemMsg = ChatCompletionSystemMessageParam(
role= "system" , content=get_system_prompt()
)
maxIter = 5 # Maximum number of iterations
agent_scratchpad = "" # agent thinking process
action_pattern = re. compile ( r"\nAction:\n`{3}(?:json)?\n(.*?)`{3}.*?$" , re.DOTALL)
for iterSeq in range ( 1 , maxIter + 1 ):
messages: Iterable[ChatCompletionMessageParam] = list ()
messages.append(systemMsg)
messages.append(
ChatCompletionUserMessageParam(
role= "user" , content= f"Question: {query} \n\n {agent_scratchpad} "
)
)
print ( f">> iterSeq: {iterSeq} " )
print ( f">>> messages: {json.dumps(messages)} " )
# Initiate a request to LLM. Note that the stop parameter needs to be set.
chat_completion = client.chat.completions.create(
messages=messages,
model=model,
stop= "Observation:" ,
)
content = chat_completion.choices[ 0 ].message.content
print ( f">>> content:\n {content} " )
final_answer_match = re.search( r"\nFinal Answer:\s*(.*)" , content)
if final_answer_match:
final_answer = final_answer_match.group( 1 )
print ( f">>> Final answer: {final_answer} " )
return
action_match = action_pattern.search(content)
if action_match:
obj = json.loads(action_match.group( 1 ))
toolName = obj[ "action" ]
toolParameters = obj[ "action_input" ]
print ( f">>> tool name: {toolName} " )
print ( f">>> tool parameters: {toolParameters} " )
result = invoke_tool(toolName, toolParameters)
print ( f">>> tool result: {result} " )
# Add the output of this LLM (Though/Action) and the tool call result (Observation) to agent_scratchpad
agent_scratchpad += content + f"\nObservation: {result} \n"
else :
print ( ">>> ERROR: detect invalid response" )
return
print ( ">>> The number of iterations has reached the upper limit and I cannot get the final answer" )
main()
Run the code:uv run .\main.py
>> iterSeq: 1
>>> messages: [{ "role" : "system" , "content" : " \n Answer the following questions as best you can. You have access to the following tools: \n { \" name \" : \" get_weather \" , \" description \" : \" Get weather \" , \" parameters \" : { \" type \" : \" object \" , \" properties \" : { \" location \" : { \" type \" : \" string \" , \" description \" : \" the name of the location \" }}, \" required \" : [ \" location \" ]}} \n\n\n The way you use the tools is by specifying a json blob. \n Specifically, this json should have a `action` key (with the name of the tool to use) and a `action_input` key (with the input to the tool going here). \n\n The only values that should be in the \" action \" field are: get_weather \n\n The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB: \n\n ``` \n {{ \n\" action \" : $TOOL_NAME, \n\" action_input \" : $INPUT \n }} \n ``` \n\n ALWAYS use the following format: \n\n Question: the input question you must answer \n Thought: you should always think about what to do \n Action: \n ``` \n $JSON_BLOB \n ``` \n Observation: the result of the action \n ... (this Thought/Action/Observation can repeat N times) \n Thought: I now know the final answer \n Final: the final answer to the original input question \n\n\n Begin! Reminder to always use the exact characters `Final Answer` when responding. \n " }, {"role" : "user" , "content" : "Question: \u5317\u4eac\u548c\u5e7f\u5dde\u5929\u6c14\u600e\u4e48\u6837 \n\n " }]
>>> content:
Thought : I need to get the weather information of Beijing and Guangzhou . First, I will get the weather of Beijing .
Action :
```
{
"action" : "get_weather" ,
"action_input" : {
"location" : "Beijing"
}
}
```
>>> tool name:get_weather
>>> tool parameters:{'location': 'Beijing'}
>>> tool result: { "msg" : "success" , "code" : 0 , "data" :{ "location" :{ "id" : "54511" , "name" : "北京" , "path" : "中国, 北京, 北京" }, "now" :{ "precipitation" : 0.0 , "temperature" : 23.4 , "pressure" : 1005.0 , "humidity" : 43.0 , "windDirection" : "Southwest Wind" , "windDirectionDegree" : 216.0 , "windSpeed" : 2.7 , "windScale" : "Breeze" , "feelst" : 23.1 }, "alarm" :[], "jieQi" : "" , "lastUpdate" : "2025/04/26 15:00" }}
>> iterSeq: 2
>>> messages: [{ "role" : "system" , "content" : " \n Answer the following questions as best you can. You have access to the following tools: \n { \" name \" : \" get_weather \" , \" description \" : \" Get weather \" , \" parameters \" : { \" type \" : \" object \" , \" properties \" : { \" location \" : { \" type \" : \" string \" , \" description \" : \" the name of the location \" }}, \" required \" : [ \" location \" ]}} \n\n\n The way you use the tools is by specifying a json blob. \n Specifically, this json should have a `action` key (with the name of the tool to use) and a `action_input` key (with the input to the tool going here). \n\n The only values that should be in the \" action \" field are: get_weather \n\n The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB: \n\n ``` \n {{ \n\" action \" : $TOOL_NAME, \n\" action_input \" : $INPUT \n }} \n ``` \n\n ALWAYS use the following format: \n\n Question: the input question you must answer \n Thought: you should always think about what to do \n Action: \n ``` \n $JSON_BLOB \n ``` \n Observation: the result of the action \n ... (this Thought/Action/Observation can repeat N times) \n Thought: I now know the final answer \n Final: the final answer to the original input question \n\n\n Begin! Reminder to always use the exact characters `Final Answer` when responding. \n " }, {"role" : "user" , "content" : "Question: \u5317\u4eac\u548c\u5e7f\u5dde\u5929\u6c14\u600e\u4e48\u6837 \n\n Thought: \u6211\u9700\u8981\u83b7\u53d6\u5317\u4eac\u548c\u5e7f\u5dde\u7684\u5929\u6c14\u4fe1\u6 06f\u3002\u9996\u5148\uff0c\u6211\u5c06\u83b7\u53d6\u5317\u4eac\u7684\u5929\u6c14\u3002 \n\n Action: \n ``` \n { \n\" action \" : \" get_weather \" , \n\" action_input \" : { \n\" location \" : \" \u5317\u4eac \"\n } \n } \n ``` \n Observation: { \" msg \" : \" success \" , \" code \" :0, \" data \" :{ \" location \" :{ \" id \" : \" 54511 \" , \" name \" : \" \u5317\u4eac \" , \" path \" : \" \u4e2d\u56fd, \u5317\u4eac, \u5317\u4eac \" }, \" now \" :{ \" precipitation \" :0.0, \" temperature \" :23.4, \" pressure \" :1005.0, \" humidity \" :43.0, \" windDirection \" : \" \u897f\u5357\u98ce \" , \" windDirectionDegree \" :216.0, \" windSpeed \" :2.7, \" windScale \" : \" \u5fae\u98ce \" , \" feelst \" :23.1}, \" alarm \" :[], \" jieQi \" : \"\" , \" lastUpdate \" :\" 2025/04/26 15:00 \" }} \n " }]
>>> content:
Thought : Now that I have obtained the weather information for Beijing, I will obtain the weather information for Guangzhou next .
Action :
```
{
"action" : "get_weather" ,
"action_input" : {
"location" : "Guangzhou"
}
}
```
Observation
>>> tool name:get_weather
>>> tool parameters:{'location': 'Guangzhou'}
>>> tool result: { "msg" : "success" , "code" : 0 , "data" :{ "location" :{ "id" : "59287" , "name" : "Guangzhou" , "path" : "China, Guangdong, Guangzhou" }, "now" :{ "precipitation" : 0.0 , "temperature" : 24.2 , "pressure" : 1005.0 , "humidity" : 79.0 , "windDirection" : "Northeast Wind" , "windDirectionDegree" : 31.0 , "windSpeed" : 1.3 , "windScale" : "Breeze" , "feelst" : 27.1 }, "alarm" :[], "jieQi" : "" , "lastUpdate" : "2025/04/26 15:00" }}
>> iterSeq: 3
>>> messages: [{ "role" : "system" , "content" : " \n Answer the following questions as best you can. You have access to the following tools: \n { \" name \" : \" get_weather \" , \" description \" : \" Get weather \" , \" parameters \" : { \" type \" : \" object \" , \" properties \" : { \" location \" : { \" type \" : \" string \" , \" description \" : \" the name of the location \" }}, \" required \" : [ \" location \" ]}} \n\n\n The way you use the tools is by specifying a json blob. \n Specifically, this json should have a `action` key (with the name of the tool to use) and a `action_input` key (with the input to the tool going here). \n\n The only values that should be in the \" action \" field are: get_weather \n\n The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB: \n\n ``` \n {{ \n\" action \" : $TOOL_NAME, \n\" action_input \" : $INPUT \n }} \n ``` \n\n ALWAYS use the following format: \n\n Question: the input question you must answer \n Thought: you should always think about what to do \n Action: \n ``` \n $JSON_BLOB \n ``` \n Observation: the result of the action \n ... (this Thought/Action/Observation can repeat N times) \n Thought: I now know the final answer \n Final: the final answer to the original input question \n\n\n Begin! Reminder to always use the exact characters `Final Answer` when responding. \n " }, {"role" : "user" , "content" : "Question: \u5317\u4eac\u548c\u5e7f\u5dde\u5929\u6c14\u600e\u4e48\u6837 \n\n Thought: \u6211\u9700\u8981\u83b7\u53d6\u5317\u4eac\u548c\u5e7f\u5dde\u7684\u5929\u6c14\u4fe1\u6 06f\u3002\u9996\u5148\uff0c\u6211\u5c06\u83b7\u53d6\u5317\u4eac\u7684\u5929\u6c14\u3002 \n\n Action: \n ``` \n { \n\" action \" : \" get_weather \" , \n\" action_input \" : { \n\" location \" : \" \u5317\u4eac \"\n } \n } \n ``` \n Observation: { \" msg \" : \" success \" , \" code \" :0, \" data \" :{ \" location \" :{ \" id \" : \" 54511 \" , \" name \" : \" \u5317\u4eac \" , \" path \" : \" \u4e2d\u56fd, \u5317\u4eac, \u5317\u4eac \" }, \" now \" :{ \" precipitation \" :0.0, \" temperature \" :23.4, \" pressure \" :1005.0, \" humidity \" :43.0, \" windDirection \" : \" \u897f\u5357\u98ce \" , \" windDirectionDegree \" :216.0, \" windSpeed \" :2.7, \" windScale \" : \" \u5fae\u98ce \" , \" feelst \" :23.1}, \" alarm \" :[], \" jieQi \" : \"\" , \" lastUpdate \" :\" 2025/04/26 15:00 \" }} \nThought: \u73b0\u5728\u6211\u5df2\u7ecf\u83b7\u53d6\u4e86\u5317\u4eac\u7684\u5929\u6c14\u4fe1\u606f\uf f0c\u63a5\u4e0b\u6765\u6211\u5c06\u83b7\u53d6\u5e7f\u5dde\u7684\u5929\u6c14\u4fe1\u606f\u3002 \n\n Action: \n ``` \n { \n\" action \" : \" get_weather \" , \n\" action_input \" : { \n\" location \" : \" \u5e7f\u5dde \"\n } \n } \n ``` \n Observation \n Observation: { \" msg \" : \" success \" , \" code \" :0, \" data \" :{ \" location \" :{ \" id \" : \" 59287 \" , \" name \" : \" \u5e7f\u5dde \" , \" path \" : \" \u4e2d\u56fd, \u5e7f\u4e1c, \u5e7f\u5dde \" }, \" now \" :{ \" precipitation \" :0.0, \" temperature \" :24.2, \" pressure \" :1005.0, \" humidity \" :79.0, \" windDirection \" : \" \u4e1c\u5317\u98ce \" , \" windDirectionDegree \" :31.0, \" windSpeed \" :1.3, \" windScale \" : \" \u5fae\u98ce \" , \" feelst \" :27.1}, \" alarm \" :[], \" jieQi \" : \"\" , \" lastUpdate \" : \" 2025/04/26 15:00 \" }} \n " }]
>>> content:
Thought : I have obtained the weather information for Beijing and Guangzhou, and now I can answer users' questions .
Final Answer : The weather conditions in Beijing are: temperature 23.4 ° C, humidity 43 % , southwest wind, wind speed 2.7 m /s, light breeze. The weather conditions in Guangzhou are: temperature 24.2°C, humidity 79%, northeast wind, wind speed 1.3 m/ s, light breeze .
>>> Final answer: The weather conditions in Beijing are: temperature 23.4 ° C, humidity 43 % , southwest wind, wind speed 2.7 m /s, light breeze. The weather conditions in Guangzhou are: temperature 24.2°C, humidity 79%, northeast wind, wind speed 1.3 m/ s, light breeze .
Summarize
Function Calling-based and ReAct-based tool calls have their own advantages and disadvantages:
1. Function Calling
No need to set system prompt words, LLM can trigger tool calls according to tools definition, and token consumption is low The model parameters are relatively large. The model training data must contain content related to Function Calling to ensure that the model can understand and generate structured outputs, and structured outputs are more stable. The output is easier to process The reasoning process is hidden and lacks explainability
2. ReAct
It is necessary to set complex system prompts, which consumes more tokens. Lower requirements on model parameters Output result processing is more complicated than Function Calling The reasoning process is visible and more explainable