File size: 6,550 Bytes
143d0b6
20ff786
d826fcd
20ff786
 
9b5b26a
 
 
 
c19d193
6aae614
8fe992b
9b5b26a
 
06688af
 
db0498c
06688af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cc41d30
06688af
 
 
 
 
 
 
 
 
 
 
 
 
 
cc41d30
 
06688af
cc41d30
06688af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b5b26a
06688af
 
 
9b5b26a
06688af
9b5b26a
06688af
 
 
 
 
 
 
 
 
cc41d30
06688af
 
 
 
 
 
 
 
 
9b5b26a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c01ffb
 
db2e414
 
f306a42
db2e414
 
 
 
 
 
 
 
 
 
 
6aae614
ae7a494
 
 
 
e121372
bf6d34c
 
29ec968
fe328e0
13d500a
8c01ffb
 
9b5b26a
 
8c01ffb
861422e
 
9b5b26a
8c01ffb
8fe992b
db2e414
8c01ffb
 
 
 
 
 
861422e
8fe992b
 
9b5b26a
8c01ffb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
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()