目录
3.1 新建agents_sdk_tool_serial.py文件
0 环境准备
- ollama已部署推理模型qwen:7b
- 已安装miniconda环境
- 具备科学上网条件
1 开发环境准备
1.1 创建项目python环境
通过conda命令创建项目的python开发环境
conda create -n mcp_demo python=3.10
1.2 在pycharm创建项目
- 解释器类型:选择自定义环境
- 环境:选择现有
- 类型:选择conda
- 环境:选择上一步创建的环境
1.3 安装项目依赖
安装openai、openai-agents openai相关依赖
安装python-dotenv python读取环境配置文件依赖
pip install openai python-dotenv openai-agents httpx
2 资源准备
本项目中需要调用天气接口获取城市的天气信息,因此需要注册天气API网站,并且获取调用key。
具体流程请参考以下链接的第二章节:MCP实战-基于Ollama+qwen2.5以sse方式实现MCP协议工具调用_mcp sse-CSDN博客
3 程序逻辑实现
3.1 新建agents_sdk_tool_serial.py文件
3.2 导入相关依赖
import json
import os
import httpx
from agents import function_tool, set_default_openai_client, Runner, OpenAIChatCompletionsModel, Agent
from dotenv import load_dotenv
from openai import AsyncOpenAI
3.3 加载配置文件
load_dotenv()
openweather_api_key = os.getenv('OPENWEATHER_API_KEY')
openweather_base_url = os.getenv('OPENWEATHER_BASE_URL')
user_agent = os.getenv('USER_AGENT')
3.4 定义请求天气接口方法
async def get_weather(city):
"""
从OpenWeather API 获取天气信息
:param city: 城市名称(需要试用英文,如 beijing)
:return: 天气数据字典;若发生错误,返回包含error信息的字典
"""
params = {
"q": city,
"appid": openweather_api_key,
"units": "metric",
"lang": "zh_cn",
}
headers = {"User-Agent": user_agent}
async with httpx.AsyncClient() as client:
try:
response = await client.get(openweather_base_url, params=params, headers=headers, timeout=30)
response.raise_for_status()
return response.json()
except httpx.HTTPStatusError as e:
return {"error": f"HTTP请求错误:{e}"}
except Exception as e:
return {"error": f"发生错误:{e}"}
3.5 定义格式化天气接口返回内容
def format_weather_data(data):
"""
格式化天气数据
:param data: 天气数据字典
:return: 格式化后的字符串;若发生错误,返回包含error信息的字符串
"""
# 如果传入的是字符串,则先转换成字典
if isinstance(data, str):
data = json.loads(data)
if "error" in data:
return data["error"]
weather = data["weather"][0]["description"]
temperature = data["main"]["temp"]
city = data["name"]
country = data["sys"]["country"]
humidity = data["main"]["humidity"]
wind = data["wind"]["speed"]
return f"城市:{city}, {country}\n天气:{weather}\n温度:{temperature}°C\n湿度:{humidity}%\n风速:{wind}m/s"
3.6 定义获取天气agent sdk方法
@function_tool
async def get_weather_tool(city: str):
"""
查询即时天气函数
:param city: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则city参数需要输入'Beijing';
:return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
"""
weather_data = await get_weather(city)
return format_weather_data(weather_data)
需要注意的是,在进行外部函数调用的时候,Agents SDK自动生成的tools参数列表,就相当于是Function calling的json schema对象,只不过是从我们定义的外部函数的函数说明中自动读取的,因此函数说明要准确。
3.7 定义将内容写入本地文件方法
@function_tool
def write_file(content):
"""
将指定内容写入本地文件。
:param content: 必要参数,字符串类型,用于表示需要写入文档的具体内容。
:return:是否成功写入
"""
with open("weather.txt", "w", encoding="utf-8") as file:
file.write(content)
3.8 定义获取openai client方法
def get_openai_client():
api_key = os.getenv('OPENAI_API_KEY')
base_url = os.getenv('BASE_URL')
return AsyncOpenAI(
api_key=api_key,
base_url=base_url
)
3.9 定义获取chat模型方法
def get_chat_model(external_client):
model_name = os.getenv('MODEL')
return OpenAIChatCompletionsModel(
model=model_name,
openai_client=external_client
)
3.10 定义获取agent方法
def get_agent(model):
return Agent(
name = "助手",
instructions = "你是一名助人为乐的助手",
tools = [get_weather_tool, write_file],
model = model
)
需要绑定定义的两个工具方法get_weather_tool和write_file。
3.11 定义整个agent调用方法
async def run_request():
external_client = get_openai_client()
set_default_openai_client(external_client)
agent = get_agent(get_chat_model(external_client))
result = await Runner.run(
agent,
"查询武汉天气,待获取完整的天气信息后并将其写入本地文件"
)
return result.final_output
3.12 定义main入口方法
if __name__ == "__main__":
import asyncio
print(asyncio.run(run_request()))
4 完整代码
import json
import os
import httpx
from agents import function_tool, set_default_openai_client, Runner, OpenAIChatCompletionsModel, Agent
from dotenv import load_dotenv
from openai import AsyncOpenAI
load_dotenv()
openweather_api_key = os.getenv('OPENWEATHER_API_KEY')
openweather_base_url = os.getenv('OPENWEATHER_BASE_URL')
user_agent = os.getenv('USER_AGENT')
async def get_weather(city):
"""
从OpenWeather API 获取天气信息
:param city: 城市名称(需要试用英文,如 beijing)
:return: 天气数据字典;若发生错误,返回包含error信息的字典
"""
params = {
"q": city,
"appid": openweather_api_key,
"units": "metric",
"lang": "zh_cn",
}
headers = {"User-Agent": user_agent}
async with httpx.AsyncClient() as client:
try:
response = await client.get(openweather_base_url, params=params, headers=headers, timeout=30)
response.raise_for_status()
return response.json()
except httpx.HTTPStatusError as e:
return {"error": f"HTTP请求错误:{e}"}
except Exception as e:
return {"error": f"发生错误:{e}"}
def format_weather_data(data):
"""
格式化天气数据
:param data: 天气数据字典
:return: 格式化后的字符串;若发生错误,返回包含error信息的字符串
"""
# 如果传入的是字符串,则先转换成字典
if isinstance(data, str):
data = json.loads(data)
if "error" in data:
return data["error"]
weather = data["weather"][0]["description"]
temperature = data["main"]["temp"]
city = data["name"]
country = data["sys"]["country"]
humidity = data["main"]["humidity"]
wind = data["wind"]["speed"]
return f"城市:{city}, {country}\n天气:{weather}\n温度:{temperature}°C\n湿度:{humidity}%\n风速:{wind}m/s"
@function_tool
async def get_weather_tool(city: str):
"""
查询即时天气函数
:param city: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则city参数需要输入'Beijing';
:return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
"""
weather_data = await get_weather(city)
return format_weather_data(weather_data)
@function_tool
def write_file(content):
"""
将指定内容写入本地文件。
:param content: 必要参数,字符串类型,用于表示需要写入文档的具体内容。
:return:是否成功写入
"""
with open("weather.txt", "w", encoding="utf-8") as file:
file.write(content)
def get_openai_client():
api_key = os.getenv('OPENAI_API_KEY')
base_url = os.getenv('BASE_URL')
return AsyncOpenAI(
api_key=api_key,
base_url=base_url
)
def get_chat_model(external_client):
model_name = os.getenv('MODEL')
return OpenAIChatCompletionsModel(
model=model_name,
openai_client=external_client
)
def get_agent(model):
return Agent(
name = "助手",
instructions = "你是一名助人为乐的助手",
tools = [get_weather_tool, write_file],
model = model
)
async def run_request():
external_client = get_openai_client()
set_default_openai_client(external_client)
agent = get_agent(get_chat_model(external_client))
result = await Runner.run(
agent,
"查询武汉天气,待获取完整的天气信息后并将其写入本地文件"
)
return result.final_output
if __name__ == "__main__":
import asyncio
print(asyncio.run(run_request()))
5 运行结果
- 查看调用过程,result.new_items对象存储了大模型调用agent的步骤。
- 查看执行结果
运行成功后控制台会输出两个工作的执行结果,在项目目录中会生成weather.txt文件,并且获取天气tool的内容会被写入此文件中,这是一条典型的串行工作调用场景。