[02]Agent项目:手搓Tool Calling实现具备工具调用能力的循环“对话式”AgentDemo
本文旨在通过手搓Tool Calling来帮助新手理解Tool Calling的整个循环。在项目逐渐扩大后,可以选择使用官方SDK或者Langchain框架等方式。
一、Tool和Tool Calling的区别
1.Tool
简单来说,就类似于一个函数。
def weather_tool():
2.Tool Calling
指的是Agent如何决定、调用、执行、处理Tool,这一整套流程。
(1)Tool定义
(2)LLM决定是否调用Tool
(3)Python解析Tool请求
(4)Python执行Tool
(5)结果传回LLM
二、本节初始脚本
将[01]中的脚本进行了完善,函数进行了封装。内容分别如下所示:
1..env
SiliconFlow_API_KEY=sk-faevswcryuqddrihwxescutiisvqpfztfvixhtimfomyffzc
2.config.py
#配置文件
#管理接入的LLM模型名称、API地址、API_KEY等信息
MODEL_NAME = "deepseek-ai/DeepSeek-V3.2"
BASE_URL = "https://api.siliconflow.cn/v1"
API_KEY_ENV = "SiliconFlow_API_KEY"
3.llm_client.py
#LLM客户端文件
#创建一个OpenAI client对象,后续所有的大模型请求都通过client发送
from openai import OpenAI
from dotenv import load_dotenv
import config
import os
#读取当前目录下的.env文件,会把.env中的内容加载到环境变量中
load_dotenv()
def create_client():
client = OpenAI(
#从环境变量中读取API Key
api_key=os.getenv(config.API_KEY_ENV),
#设置请求的基础URL,默认是https://api.openai.com/v1。如果使用的是SiliconFlow的API,需要修改为https://api.siliconflow.cn/v1
base_url=config.BASE_URL
)
return client
4.prompts.py
#Prompt文件
#定义系统Prompt,告诉模型的角色和身份等
SYSTEM_PROMPT = """
你是一名目标检测领域,具有前瞻目光的期刊编辑
"""
5.chat.py
#对话文件
#用户向LLM发送一次对话请求,LLM返回一次回答
import config
def chat_with_llm(client, messages):
#使用client这个客户端,在它的聊天补全功能中,创建一个新的请求
response = client.chat.completions.create(
#指定使用的模型,DeepSeek-V3.2是模型名称
model=config.MODEL_NAME,
#messages表示对话历史,传入的messages是一个列表
messages=messages
)
#返回llm的回答。response是完整返回结果;choices[0]表示第一个回答;message.content表示回答文本
return response.choices[0].message.content
6.main.py
import llm_client
import prompts
import chat
#创建一个OpenAI client对象
client = llm_client.create_client()
print("\n欢迎使用QM_AgentDemo!(输入'Q'或'q'结束对话)\n")
#保存对话历史,添加系统信息
messages = [
{
#role表示消息角色,system表示系统消息;#content表示消息内容,即给系统拟定的前提条件
"role": "system",
"content": prompts.SYSTEM_PROMPT
}
]
#向大模型开启循环对话请求
while True:
#获取用户输入
user_input = input("你:")
#程序结束条件
if user_input.lower() in['Q', 'q']:
print("对话结束")
break
#添加用户信息
messages.append({
#role表示消息角色,user表示用户输入;#content表示消息内容,即用户真正说的话
"role": "user",
"content": user_input
})
#打印LLM回复内容
agent_reply = chat.chat_with_llm(client, messages)
print(f"模型回复:{agent_reply}\n")
#将LLM回复也加入到对话历史
messages.append({
"role": "assistant",
"content": agent_reply
})
三、搭建Tool Calling最小可运行版本(Minimum Viable Product,MVP)
1.构建TOOL_PROMPT
(1)在tool_prompts.py中构建字符串TOOL_PROMPT
目前只构建一个Tool,weather_tool(city):查询天气。
TOOL_PROMPT = """
你是一个Agent。
你可以使用以下工具:
1.weather_tool(city)
功能:
查询天气。
如果用户需要查询天气:
请严格按照一下格式输出:
TOOL:weather_tool
ARGS:城市名
例如:
TOOL:weather_tool
ARGS:大连
不要输出其他内容。
如果不需要调用工具:
直接正常回答。
"""
(2)在main.py中,将TOOL_PROMPT也加入到messages[]
#保存对话历史,添加系统信息
messages = [
{
#role表示消息角色,system表示系统消息;#content表示消息内容,即给系统拟定的前提条件
"role": "system",
"content": prompts.SYSTEM_PROMPT
},
{
#role表示消息角色,system表示系统消息;#content表示消息内容,即给系统拟定的前提条件
"role": "system",
"content": tool_prompts.TOOL_PROMPT
}
]
(3)在tools.py中,构建weather_tool(city)
#测试流程
def weather_tool(city):
return f"{city}今天25度"
注:以上weather_tool(city)仅适用于流程测试,并非最终代码。
2.main.py中,获取LLM返回的结果
#获取LLM返回的结果
agent_reply = chat.chat_with_llm(client, messages)
若用户询问普通问题,则LLM正常回答;若用户询问天气相关问题,LLM回答如下所示:

3.Python解析Tool调用
#判断是否调用工具
if "TOOL:" in agent_reply:
#提取参数
lines = agent_reply.split("\n")
tool_name = lines[0].replace("TOOL:", "").strip()
args = lines[1].replace("ARGS:", "").strip()
if tool_name == "weather_tool":
#这里的tool_replay是Python执行Tool后返回的结果,不是LLM返回的结果
tool_replay = tools.weather_tool(args)
print(f"天气情况:{tool_replay}\n")
else:
#这里的agent_reply才是LLM返回的结果
print(f"模型回复:{agent_reply}\n")
若调用Tool,则执行tools.weather_tool(city),获取Tool的返回值;若不调用Tool,则正常返回模型回复。
4.当前完整main.py
import llm_client
import system_prompts
import tool_prompts
import chat
import tools
#创建一个OpenAI client对象
client = llm_client.create_client()
print("\n欢迎使用QM_AgentDemo!(输入'Q'或'q'结束对话)\n")
#保存对话历史,添加系统信息
messages = [
{
#role表示消息角色,system表示系统消息;#content表示消息内容,即给系统拟定的前提条件
"role": "system",
"content": system_prompts.SYSTEM_PROMPT
},
{
#role表示消息角色,system表示系统消息;#content表示消息内容,即给系统拟定的前提条件
"role": "system",
"content": tool_prompts.TOOL_PROMPT
}
]
#向大模型开启循环对话请求
while True:
#获取用户输入
user_input = input("你:")
#程序结束条件
if user_input.lower() in['Q', 'q']:
print("对话结束")
break
#添加用户信息
messages.append({
#role表示消息角色,user表示用户输入;#content表示消息内容,即用户真正说的话
"role": "user",
"content": user_input
})
#获取LLM返回的结果
agent_reply = chat.chat_with_llm(client, messages)
#判断是否调用工具
if "TOOL:" in agent_reply:
#提取参数
lines = agent_reply.split("\n")
tool_name = lines[0].replace("TOOL:", "").strip()
args = lines[1].replace("ARGS:", "").strip()
if tool_name == "weather_tool":
#这里的tool_replay是Python执行Tool后返回的结果,不是LLM返回的结果
tool_replay = tools.weather_tool(args)
print(f"天气情况:{tool_replay}\n")
else:
#这里的agent_reply才是LLM返回的结果
print(f"模型回复:{agent_reply}\n")
#将LLM回复也加入到对话历史
messages.append({
"role": "assistant",
"content": agent_reply
})
当前运行结果:

至此,已经将一个固定返回结果的天气Tool加入了AgentDemo中。但我们接收到的天气情况只是Python执行函数返回的固定结果,并非LLM总结结果过后输出的内容。因此,还需继续完善以下内容:
(1)将Python执行Tool后的结果传回LLM,LLM继续思考,将最终回答返回给用户。实现Observation Loop。
(2)拓展Tool,并完善Tool的执行机制。
(3)实现真正的Tool。
四、下期规划——完善脚本
1.实现Observation Loop
2.Tool Registry(工具注册表)
3.实现真正的Tool
更多推荐


所有评论(0)