legendlc's picture
Update app.py
f306a42 verified
Raw History Blame Contribute Delete
6.55 kB
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()