import os from qwen_agent.agents import Assistant from qwen_agent.gui import WebUI from qwen_agent.tools.base import BaseTool, register_tool import json5 import sys from datetime import datetime import pandas as pd # 获取当前脚本所在目录 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前运行代码的解释器路径 current_interpreter = sys.executable # 获取当前时间 @register_tool('get_current_datetime') class GetCurrentDateTime(BaseTool): """获取当前系统日期时间的工具,返回年、月、日、时、分、秒等信息""" description = '获取当前系统日期时间的工具,可返回完整的日期时间信息,用于辅助旅行规划中对时间的判断。' parameters = [] # 此工具不需要参数 def __init__(self, *args, **kwargs): super().__init__() pass def call(self, params: str, **kwargs) -> str: try: # 获取当前时间 now = datetime.now() # 构建响应数据 current_time_info = { 'year': now.year, 'month': now.month, 'day': now.day, 'hour': now.hour, 'minute': now.minute, 'second': now.second, 'formatted_time': now.strftime('%Y-%m-%d %H:%M:%S') # 标准格式时间字符串 } response = { 'status': 'success', 'current_datetime': current_time_info } return json5.dumps(response, ensure_ascii=False) except Exception as e: return json5.dumps({ 'status': 'error', 'message': f'获取当前时间失败: {str(e)}' }) # 获取南航航班信息 @register_tool('flight_search') class FlightSearch(BaseTool): """航班信息检索工具,根据出发地、目的地和日期查询航班信息""" description = '航班信息检索工具,根据出发地、目的地和日期查询航班信息,返回符合条件的航班列表。' parameters = [ { 'name': 'departure_city', 'type': 'string', 'description': '出发城市名称。例如:广州、北京', 'required': True }, { 'name': 'arrival_city', 'type': 'string', 'description': '到达城市名称,例如:上海、杭州', 'required': True }, { 'name': 'date', 'type': 'string', 'description': '查询日期,格式:YYYY/MM/DD,例如:2025/04/29', 'required': True } ] def __init__(self, *args, **kwargs): """初始化工具,加载航班数据""" super().__init__() self.csv_file_path = r"C:\Users\a1371\PycharmProjects\TravelAssistant\Flight.csv" self.data = self._load_data() def _load_data(self): """加载CSV数据并进行预处理""" try: df = pd.read_csv(self.csv_file_path) if '航班日期' in df.columns: # 将日期列转换为字符串格式 YYYY/MM/DD df['航班日期_str'] = pd.to_datetime(df['航班日期']).dt.strftime('%Y/%m/%d') return df except Exception as e: print(f"加载航班数据失败: {e}") return pd.DataFrame() def call(self, params: str, **kwargs) -> str: try: params = json5.loads(params) departure = params['departure_city'] arrival = params['arrival_city'] date_str = params['date'] # 保持字符串格式,如 '2025/5/30' if self.data.empty: return json5.dumps({ 'status': 'error', 'message': '航班数据未成功加载,请检查CSV文件路径' }) # 执行筛选查询(使用字符串列进行比较) filtered_df = self.data[ (self.data['出发城市'] == departure) & (self.data['终到城市'] == arrival) & (self.data['航班日期_str'] == date_str) # 关键修改点 ] results = filtered_df.to_dict('records') response = { 'status': 'success', 'query': { 'departure_city': departure, 'arrival_city': arrival, 'date': date_str # 保持原始字符串格式 }, 'total_results': len(results), 'flights': results } return json5.dumps(response, ensure_ascii=False) except Exception as e: return json5.dumps({ 'status': 'error', 'message': f'查询过程中发生错误: {str(e)}' }) def init_agent_service(): llm_cfg = { # Use the model service provided by DashScope: 'model': 'qwen3-235b-a22b', 'model_server': 'dashscope', 'api_key': "sk-1eb585dbfeea444691cd4216fd2a071d", 'generate_cfg': { 'top_p': 0.8 } } tools = [ # 查询高铁MCP server { "mcpServers": { "tongchenglvxing-mcp-server": { "command": "npx", "args": [ "-y", "@wuchubuzai/tongchenglvxing-mcp-server" ] } } }, # 查询航班 MCP server { "mcpServers": { "variflight": { "command": "npx", "args": [ "-y", "@variflight-ai/variflight-mcp" ], "env": { "X_VARIFLIGHT_KEY": "sk-6Si9JTjgDINieKYLEE2VNMyZI285AuCYF8wl3Z-n18c" } } } }, # 高德地图MCP server { "mcpServers": { "amap-maps": { "command": "npx", "args": [ "-y", "@amap/amap-maps-mcp-server" ], "env": { "AMAP_MAPS_API_KEY": "5b4f21c9dc29219b19cb7666258245c1" } } } }, # 小红书 { "mcpServers": { "xiaohongshu MCP": { "command": current_interpreter, # 配置为解释器地址 "args": [ os.path.join(BASE_DIR, "Redbook-Search-Comment-MCP2.0", "xiaohongshu_mcp.py"), "--stdio" ] } } }, # Edgeone page生成网页 { "mcpServers": { "edgeone-pages-mcp-server": { "command": "npx", "args": ["edgeone-pages-mcp"], "env": { "EDGEONE_PAGES_API_TOKEN": "VqQ91Y9EMJtfK8pvPQzS+kPIHsBi8C9bb4eYi5If9+4=", "EDGEONE_PAGES_PROJECT_NAME": os.path.join(BASE_DIR) # 配置为现有项目地址 } } } }, # 浏览器搜索 { "mcpServers": { "AISearch": { "url": "http://appbuilder.baidu.com/v2/ai_search/mcp/sse?api_key=Bearer+bce-v3/ALTAK-zHZ0uMemmKiBJD6n3o4UX/9d081c95580f5b9d37ffacb63f815f4c441e8fc3" } } }, 'flight_search', 'get_current_datetime', 'code_interpreter' ] system_message = """ 你是一个旅行规划助手,请根据用户的输入,为其规划出行。 以下是默认操作: 1) 如果需要为用户生成旅行规划,请调用amap-maps的高德地图MCP Server工具查询景点,进行旅行规划,保证规划的实际性。 2) 请一定要在回答的的尾部给出信息来源,显式给出信息是来自于你固有知识还是外部信息,如(高铁信息来源:同程旅行; 航班信息来源:Variflight;景点信息来源:高德地图)。请注意,严禁编造虚假的信息来源,如“途牛旅行”等为附加给智能体的信息源。 对于航班推荐: 3) 如果用户需要航班推荐,请优先使用flight_search工具推荐南方航空航班。 4) 如果flight_search工具获取不到相关航班,则使用variflight MCP server推荐航班,同样优先推荐南航航班。 5) 请在回答的末尾加上信息来源,如果航安信息是来自于工具flight_search则为“航班信息来源:中国南方航空公司”; 如果是来自于variflight则为“航班信息来源:Variflight航班平台”。 以下是非默认操作,仅在用户要求下进行,如果用户不要求则不进行以下操作: 1) 如果用户需要图文并茂的旅游攻略,请你通过amap-maps的amap-maps-maps_text_search工具获取图像的url,最好可以做到攻略中推荐的每个景点都跟随一张图像,多模态呈现。 """ bot = Assistant(llm=llm_cfg, function_list=tools, name='智慧出行助手', system_message=system_message) return bot def app_gui(): # Define the agent bot = init_agent_service() chatbot_config = { 'prompt.suggestions': [ '我是一名在读大学生,2025年5月31号前往北京旅游,请你为我规划三天两晚的旅行计划。', '我是用户u104,2025年5月22号想从杭州前往北京,请你为我推荐去程的高铁,并为我规划三天两晚的旅行计划。', ] } WebUI(bot, chatbot_config=chatbot_config, ).run() if __name__ == '__main__': app_gui()