通过一个简单的例子来实现,通过autogen的助手来实现工具的调用。本次实验使用qwen-plus模型 可自己去https://dashscope.aliyuncs.com申请api。代码全部为python代码。环境配置使用uv,使用uv进行运行。
注意:本次实验需要魔法。
weather.py 写了一个官方的天气获取的sever 详细代码如下(可以去看autogen教程1的文章有介绍):
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# 初始化 FastMCP server
mcp = FastMCP("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""向 NWS API 发送请求,并进行适当的错误处理。"""
headers = {
"User-Agent": USER_AGENT,
"Accept": "application/geo+json"
}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except httpx.HTTPStatusError as e:
print(f"HTTP错误: {e.response.status_code} - {e.response.text}")
return None
except httpx.RequestError as e:
print(f"请求错误: {str(e)}")
return None
except Exception as e:
print(f"未知错误: {str(e)}")
return None
def format_alert(feature: dict) -> str:
"""将警报 feature 格式化为可读的字符串。"""
props = feature["properties"]
return f"""
事件: {props.get('event', 'Unknown')}
区域: {props.get('areaDesc', 'Unknown')}
严重性: {props.get('severity', 'Unknown')}
描述: {props.get('description', 'No description available')}
指示: {props.get('instruction', 'No specific instructions provided')}
"""
@mcp.tool()
async def get_alerts(state: str) -> str:
"""获取美国州的天气警报。
Args:
state: 两个字母的美国州代码(例如 CA、NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "无法获取警报或未找到警报。"
if not data["features"]:
return "该州没有活跃的警报。"
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""获取某个位置的天气预报。
Args:
latitude: 位置的纬度
longitude: 位置的经度
"""
# 首先获取预报网格 endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取此位置的预报数据。"
# 从 points response 中获取预报 URL
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "无法获取详细预报。"
# 将 periods 格式化为可读的预报
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # 仅显示接下来的 5 个 periods
forecast = f"""
{period['name']}:
温度: {period['temperature']}°{period['temperatureUnit']}
风: {period['windSpeed']} {period['windDirection']}
预报: {period['detailedForecast']}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
if __name__ == "__main__":
# 初始化并运行 server
mcp.run(transport='stdio')
主程序代码api_key通过.env文件进行配置 api_key=xxxx。代码如下
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import StructuredMessage
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.models.openai._model_info import ModelInfo
from dotenv import load_dotenv
import os
import asyncio
from autogen_ext.tools.mcp import StdioServerParams, mcp_server_tools
from autogen_core import CancellationToken
# 加载环境变量
load_dotenv()
api_key=os.getenv("api_key")
# 创建主函数
async def main():
weather_server = StdioServerParams(
command="uv",
args=[
"run",
"../mcp/weather.py"
]
)
tools = await mcp_server_tools(weather_server)
# 调用模型
qwen_model_info = ModelInfo(
max_tokens=8192,
has_function_call_api=True,
vision=True,
function_calling=True,
json_output=True,
family="unkonwn",
structured_output=True
)
# 创建模型客户端
model_client = OpenAIChatCompletionClient(
model="qwen-plus",
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=api_key,
model_info=qwen_model_info
)
agent = AssistantAgent(
name="assistant",
model_client=model_client,
tools=tools,
reflect_on_tool_use=True,
system_message=("你是一个天气预报员,可以通过使用tools来查询天气")
)
await Console(
agent.run_stream(
task="今天加州的天气怎么样",
cancellation_token=CancellationToken()
)
)
if __name__=="__main__":
asyncio.run(main())
创建model_client 通过autogen的方式和mcp client的作用相同
进行属性配置,和其他的软件mcp文件配置类似。文件地址根据自己的文件地址进行修改
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
weather_server = StdioServerParams(
command="uv",
args=[
"run",
"../mcp/weather.py"
]
)
代码运行结果为
---------- TextMessage (user) ----------
今天加州的天气怎么样
---------- ToolCallRequestEvent (assistant) ----------
[FunctionCall(id='call_50223cf11e844810a71d80', arguments='{"state": "CA"}', name='get_alerts')]
---------- ToolCallExecutionEvent (assistant) ----------
[FunctionExecutionResult(content='[{"type": "text", "text": "\n\u4e8b\u4ef6: Wind Advisory\n\u533a\u57df: Indian Wells Valley; Mojave Desert\n\u4e25\u91cd\u6027: Moderate\n\u63cf\u8ff0: * WHAT...West winds 20 to 30 mph with gusts to 50 mph.
---------- TextMessage (assistant) ----------
今天加州的天气状况复杂多变,主要受到强风影响,部分地区还存在霜冻和空气质量问题。以下是具体的情况:
1. **强风警报(Wind Advisory 和 High Wind Warning)**:
- 多个地区发布了强风警报,包括Indian Wells Valley、Mojave Desert、Santa Barbara County沿海地区、Antelope Valley、Interstate 5 Corridor、Western Mojave Desert等。
- 风速普遍在20到40英里每小时之间,阵风可能达到50至65英里每小时。
- 这种强风可能导致物体被吹动,树枝掉落以及局部停电。对高车身车辆驾驶尤其困难,建议谨慎驾驶。
2. **霜冻警报(Frost Advisory)**:
- Northern Trinity和Southern Trinity地区可能会出现霜冻,温度低至32°F。
- 霜冻可能损害敏感植物,建议采取措施保护室外植物。
3. **红旗警告(Red Flag Warning)**:
- 北部Sacramento Valley到南部Tehama县线以下1000英尺的区域有红旗警告,表明火灾风险极高。
- 风速预计为15到25英里每小时,阵风可达35英里每小时,湿度在15%到25%之间。
- 北部Sacramento Valley到南部Tehama县线以下1000英尺的区域有红旗警告,表明火灾风险极高。
- 风速预计为15到25英里每小时,阵风可达35英里每小时,湿度在15%到25%之间。
- 风速预计为15到25英里每小时,阵风可达35英里每小时,湿度在15%到25%之间。
- 建议避免户外用火。
4. **空气质量警报(Air Quality Alert)**:
- Imperial County西南部、西部及Imperial Valley地区因风沙导致颗粒污染水平升高,空气质量较差。
- 粒子污染可能引发健康问题,特别是对敏感人群如老年人、儿童和孕妇等。
- 建议减少户外活动,并保持室内空气清洁。
总体来说,加州今天以强风为主,出行需注意安全,尤其是驾车时要特别小心。对于敏感人群,应尽量减少外出以保护健康。