文章目录
多种工具组合
importosfromtypingimportDict,List,Any,TypedDictfromlangchain.agentsimportcreate_agent,AgentStatefromlangchain.toolsimporttoolfromlangchain.messagesimportHumanMessagefromlangchain_community.chat_modelsimportChatTongyifromdatetimeimportdatetimefromdotenvimportload_dotenv load_dotenv()# ============ 自定义状态定义 ============classTravelAgentState(AgentState):"""旅游助手 Agent 的自定义状态"""user_preferences:Dict[str,Any]conversation_history:List[Dict[str,str]]current_city:str# ============ 使用 @tool 装饰器定义工具 ============@tooldefweather_query(city:str)->str:"""查询城市天气信息。输入应该是城市名称,如'北京'或'上海'。 返回该城市当前天气情况、温度、湿度等信息。"""try:# 模拟天气数据weather_data={"北京":{"city":"北京","weather":"晴","temperature":"25°C","humidity":"45%","wind":"东南风3级"},"上海":{"city":"上海","weather":"多云","temperature":"28°C","humidity":"65%","wind":"东风2级"},"广州":{"city":"广州","weather":"阵雨","temperature":"30°C","humidity":"80%","wind":"南风2级"},"杭州":{"city":"杭州","weather":"晴转多云","temperature":"26°C","humidity":"60%","wind":"微风"},}ifcityinweather_data:data=weather_data[city]returnf"""{city}天气情况: - 天气:{data['weather']}- 温度:{data['temperature']}- 湿度:{data['humidity']}- 风速:{data['wind']}- 更新时间:{datetime.now().strftime('%Y-%m-%d %H:%M')}"""else:returnf"未找到{city}的天气信息,请确认城市名称是否正确。"exceptExceptionase:returnf"查询天气时出错:{str(e)}"@tooldefattraction_recommendation(query:str)->str:"""推荐旅游景点。输入应该是城市名称和可选的主题或偏好, 如'北京 历史'或'上海 美食'。 返回该城市的推荐景点、评分和简介。"""try:# 解析查询参数parts=query.split()city=parts[0]ifpartselse""preference=parts[1]iflen(parts)>1else""# 模拟景点数据attractions_db={"北京":{"历史":[{"name":"故宫","rating":4.8,"description":"明清两代的皇家宫殿","type":"历史文化"},{"name":"长城","rating":4.9,"description":"世界文化遗产,古代军事防御工程","type":"历史遗迹"},{"name":"天坛","rating":4.7,"description":"明清皇帝祭天祈谷的场所","type":"历史建筑"}],"公园":[{"name":"颐和园","rating":4.8,"description":"皇家园林,风景秀丽","type":"园林景观"},{"name":"北海公园","rating":4.6,"description":"古典皇家园林","type":"城市公园"}]},"上海":{"现代":[{"name":"外滩","rating":4.7,"description":"上海标志性景观,万国建筑博览","type":"城市景观"},{"name":"东方明珠","rating":4.6,"description":"上海地标性建筑","type":"现代建筑"}],"美食":[{"name":"城隍庙","rating":4.5,"description":"上海小吃聚集地","type":"美食文化"},{"name":"田子坊","rating":4.4,"description":"文艺小资聚集地,特色小吃","type":"文艺美食"}]},"杭州":{"自然":[{"name":"西湖","rating":4.9,"description":"人间天堂,风景如画","type":"湖泊风光"},{"name":"西溪湿地","rating":4.7,"description":"城市湿地公园","type":"自然生态"}]}}ifcityinattractions_db:recommendations=[]ifpreferenceandpreferenceinattractions_db[city]:recommendations=attractions_db[city][preference]else:# 如果没有指定偏好,返回所有景点forpref,attrsinattractions_db[city].items():recommendations.extend(attrs)ifrecommendations:result=f"{city}推荐景点:\n"fori,attrinenumerate(recommendations[:5],1):result+=f"{i}.{attr['name']}(评分:{attr['rating']})\n"result+=f" 类型:{attr['type']}\n"result+=f" 简介:{attr['description']}\n\n"returnresultelse:returnf"未找到{city}的{preference}相关景点推荐。"else:returnf"暂无{city}的景点数据。"exceptExceptionase:returnf"查询景点时出错:{str(e)}"@tooldeftrip_planner(query:str)->str:"""规划旅游行程。输入应该包含城市、天数、偏好等信息, 如'北京 3天 历史'或'上海 2天 美食购物'。 返回详细的行程安排。"""try:parts=query.split()iflen(parts)<2:return"请输入城市和天数,如'北京 3天'"city=parts[0]days=parts[1].replace("天","")preference=parts[2]iflen(parts)>2else"general"# 模拟行程数据sample_itineraries={"北京":{"1":"第一天:上午参观故宫,下午游览天安门广场和王府井","2":"第一天:上午参观故宫,下午游览天坛\n第二天:全天游览八达岭长城,晚上品尝北京烤鸭","3":"第一天:上午参观故宫,下午游览天安门广场\n第二天:全天游览八达岭长城\n第三天:上午参观颐和园,下午逛什刹海胡同,晚上体验老北京文化"},"上海":{"1":"第一天:上午游览外滩,下午参观东方明珠,晚上逛南京路步行街","2":"第一天:上午游览外滩和豫园,下午参观城隍庙\n第二天:上午参观上海博物馆,下午逛田子坊,晚上品尝本帮菜","3":"第一天:外滩、南京路步行街\n第二天:豫园、城隍庙、上海博物馆\n第三天:迪士尼乐园或朱家角古镇"}}ifcityinsample_itinerariesanddaysinsample_itineraries[city]:itinerary=sample_itineraries[city][days]returnf"{city}{days}天{preference}主题行程建议:\n{itinerary}\n\n温馨提示:请根据实际情况调整,注意景区开放时间。"else:returnf"暂无{city}{days}天的标准行程,建议结合天气和景点推荐自行规划。"exceptExceptionase:returnf"规划行程时出错:{str(e)}"# ============ 使用第三方包的工具示例 ============@tooldefcurrency_converter(amount:float,from_currency:str,to_currency:str)->str:"""货币转换工具。输入:金额, 原货币, 目标货币,如'100, USD, CNY'"""try:# 模拟汇率数据rates={"USD":{"CNY":7.2,"EUR":0.92,"JPY":150},"CNY":{"USD":0.14,"EUR":0.13,"JPY":21},"EUR":{"USD":1.09,"CNY":7.8,"JPY":163}}iffrom_currencyinratesandto_currencyinrates[from_currency]:rate=rates[from_currency][to_currency]converted=amount*ratereturnf"{amount}{from_currency}={converted:.2f}{to_currency}(汇率: 1{from_currency}={rate}{to_currency})"else:returnf"不支持{from_currency}到{to_currency}的货币转换"exceptExceptionase:returnf"货币转换失败:{str(e)}"@tooldefget_local_food(city:str)->str:"""获取当地美食推荐。输入:城市名称"""try:food_db={"北京":["北京烤鸭","炸酱面","豆汁焦圈","卤煮火烧","炒肝","爆肚"],"上海":["小笼包","生煎包","本帮红烧肉","蟹粉汤包","油爆虾","腌笃鲜"],"广州":["早茶点心","煲仔饭","烧鹅","肠粉","云吞面","白切鸡"],"成都":["火锅","串串香","麻婆豆腐","担担面","夫妻肺片","龙抄手"],"杭州":["西湖醋鱼","东坡肉","龙井虾仁","叫化鸡","片儿川","定胜糕"],}ifcityinfood_db:returnf"{city}特色美食推荐:\n"+"\n".join([f"-{food}"forfoodinfood_db[city]])else:returnf"暂无{city}的美食数据"exceptExceptionase:returnf"查询美食时出错:{str(e)}"# ============ 创建 Agent ============defcreate_travel_agent():"""创建旅游助手 Agent"""# 初始化通义千问模型llm=ChatTongyi(model="qwen-plus",temperature=0.1,max_tokens=2000)# 工具列表tools=[weather_query,attraction_recommendation,trip_planner,currency_converter,get_local_food]# 系统提示词system_prompt="""你是一个专业的旅游助手,可以帮助用户: 1. 查询城市天气信息 2. 推荐旅游景点(可按主题筛选) 3. 规划旅游行程 4. 货币汇率转换 5. 推荐当地特色美食 请根据用户的需求,选择合适的工具来提供帮助。 如果用户的问题需要多个信息,请按顺序使用相关工具。 最后给出完整、有用的回答。"""# 使用 create_agent 创建 Agent(新版API)# 使用新版的create_agent(正确的参数)agent=create_agent(model=llm,# 必需:模型实例或字符串标识tools=tools,# 必需:工具列表system_prompt=system_prompt,# 系统提示词)returnagent# ============ 测试函数 ============deftest_agent():"""测试 Agent 的不同功能"""travel_agent=create_travel_agent()test_cases=["北京今天的天气怎么样?","我想去上海旅游,有什么推荐的景点吗?","推荐一些杭州的自然风光景点","帮我规划一个北京3天的行程","我想去广州玩,先查一下天气,再推荐一些景点","100美元能换多少人民币?","成都有什么好吃的?"]print("="*60)print("开始测试旅游助手Agent")print("="*60)fori,queryinenumerate(test_cases,1):print(f"\n测试{i}:{query}")print("-"*40)try:# 初始化状态initial_state={"messages":[HumanMessage(content=query)],"user_preferences":{"language":"zh","detail_level":"normal"},"conversation_history":[],"current_city":""}# 调用 Agentresult=travel_agent.invoke(initial_state)# 提取最终回答final_message=result["messages"][-1]print(f"助手回答:\n{final_message.content}")exceptExceptionase:print(f"执行出错:{e}")# ============ 交互式对话 ============definteractive_chat():"""交互式对话模式"""travel_agent=create_travel_agent()print("="*60)print("旅游助手交互模式")print("输入 '退出' 结束对话")print("="*60)# 初始化状态state={"messages":[],"user_preferences":{"language":"zh","detail_level":"normal"},"conversation_history":[],"current_city":""}whileTrue:user_input=input("\n你:").strip()ifuser_input.lower()in['退出','quit','exit','q']:print("感谢使用,再见!")breakifnotuser_input:continue# 添加用户消息到状态state["messages"].append(HumanMessage(content=user_input))try:print("思考中...")# 调用 Agentresult=travel_agent.invoke(state)# 更新状态state=result# 提取并显示助手的最新回复formsginreversed(state["messages"]):ifhasattr(msg,'content')andmsg.contentandmsg.content!=user_input:print(f"\n助手:{msg.content}")breakexceptExceptionase:print(f"出错:{e}")# ============ 主程序 ============if__name__=="__main__":print("旅游助手 Agent 系统")print("="*40)print("1. 测试模式(运行预设测试)")print("2. 对话模式(交互式对话)")choice=input("\n请选择模式 (1/2): ").strip()ifchoice=="1":test_agent()else:interactive_chat()