legendlc's picture
Update app.py
f306a42 verified
import os
from typing import Any, Dict, Optional
import csv
import httpx
import logging
from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
import datetime
import requests
import pytz
import yaml
from tools.final_answer import FinalAnswerTool
from Gradio_UI import GradioUI
AMAP_API_BASE = "https://restapi.amap.com/v3/weather/weatherInfo"
AMAP_API_KEY = os.environ.get("AMAP_API_KEY", "")
USER_AGENT = "amap-weather-mcp-server/1.0"
city_to_adcode = {}
def load_city_adcode_map():
"""加载城市名称到adcode的映射"""
try:
current_dir = os.path.dirname(os.path.abspath(__file__))
csv_file_path = os.path.join(current_dir, "AMap_adcode_citycode.csv")
with open(csv_file_path, 'r', encoding='utf-8') as file:
reader = csv.reader(file)
next(reader) # 跳过表头
for row in reader:
if len(row) >= 2:
city_name = row[0].strip()
adcode = row[1].strip()
city_to_adcode[city_name] = adcode
return True
except Exception as e:
print(f"加载城市编码文件失败: {e}")
return False
# 初始加载城市编码数据
load_city_adcode_map()
def get_adcode_by_city(city_name: str) -> Optional[str]:
"""根据城市名称查找对应的adcode
Args:
city_name: 城市名称,如"北京市"、"上海市"等
Returns:
城市对应的adcode,如果未找到则返回None
"""
# 先尝试直接匹配
if city_name in city_to_adcode:
return city_to_adcode[city_name]
# 如果未找到,尝试添加"市"或"省"后缀再查找
if not city_name.endswith("市") and not city_name.endswith("省"):
city_with_suffix = city_name + "市"
if city_with_suffix in city_to_adcode:
return city_to_adcode[city_with_suffix]
city_with_suffix = city_name + "省"
if city_with_suffix in city_to_adcode:
return city_to_adcode[city_with_suffix]
# 对于区级城市,尝试判断是否为区名
for full_name, code in city_to_adcode.items():
if city_name in full_name and (full_name.endswith("区") or "区" in full_name):
return code
return None
def make_amap_request(params: Dict[str, str]) -> Dict[str, Any]:
"""向高德地图API发送请求并获取天气数据
Args:
params: API请求参数
Returns:
API返回的JSON数据,如果请求失败则返回None
"""
# 添加公共参数
params["key"] = AMAP_API_KEY
headers = {
"User-Agent": USER_AGENT
}
with httpx.Client() as client:
try:
response = client.get(AMAP_API_BASE, params=params, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception as e:
print(f"API请求失败: {e}")
return None
def format_current_weather(weather_data: Dict[str, Any]) -> str:
"""格式化实时天气信息
Args:
weather_data: 高德地图API返回的天气数据
Returns:
格式化后的天气信息字符串
"""
if not weather_data or "lives" not in weather_data or not weather_data["lives"]:
return "无法获取天气信息或数据格式错误"
live = weather_data["lives"][0]
return f"""
城市: {live.get('city', '未知')}
天气: {live.get('weather', '未知')}
温度: {live.get('temperature', '未知')}°C
风向: {live.get('winddirection', '未知')}
风力: {live.get('windpower', '未知')}
湿度: {live.get('humidity', '未知')}%
发布时间: {live.get('reporttime', '未知')}
"""
@tool
def get_current_weather(city: str) -> str:
"""获取指定城市的实时天气
Args:
city: 中国城市名称,如"北京市"、"上海市"、"广州市"等
"""
adcode = get_adcode_by_city(city)
if not adcode:
return f"无法找到城市'{city}'的编码,请检查城市名称是否正确"
params = {
"city": adcode,
"extensions": "base" # 获取实时天气
}
data = make_amap_request(params)
if not data:
return f"获取{city}的天气信息失败"
if data.get("status") != "1":
return f"API返回错误: {data.get('info', '未知错误')}"
return format_current_weather(data)
@tool
def get_current_time_in_timezone(timezone: str) -> str:
"""A tool that fetches the current local time in a specified timezone.
Args:
timezone: A string representing a valid timezone (e.g., 'America/New_York').
"""
try:
# Create timezone object
tz = pytz.timezone(timezone)
# Get current time in that timezone
local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
return f"The current local time in {timezone} is: {local_time}"
except Exception as e:
return f"Error fetching time for timezone '{timezone}': {str(e)}"
@tool
def who_is(name: str) -> str:
"""一个回来回答”XXX是谁“的工具,无论返回的结果有多不靠谱,都作为最终答案,不需要进一步搜索
Args:
name: 人名
"""
if "林晨" in name:
return f"{name}是世界上最帅的男人"
elif "胜阳" in name:
return f"{name}是世界上最丑的男人"
else:
return "不认识"
final_answer = FinalAnswerTool()
# If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
# model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
model = HfApiModel(
max_tokens=2096,
temperature=0.5,
model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded
custom_role_conversions=None,
)
# Import tool from Hub
image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
with open("prompts.yaml", 'r') as stream:
prompt_templates = yaml.safe_load(stream)
agent = CodeAgent(
model=model,
tools=[final_answer, get_current_weather, get_current_time_in_timezone, who_is], ## add your tools here (don't remove final answer)
max_steps=6,
verbosity_level=1,
grammar=None,
planning_interval=None,
name=None,
description=None,
prompt_templates=prompt_templates
)
GradioUI(agent).launch()