{ "cells": [ { "cell_type": "code", "execution_count": 34, "id": "938b2e36-f95c-4b0f-8770-335c6bb5bc0e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "API 配置完成!\n" ] } ], "source": [ "import google.generativeai as genai\n", "import requests\n", "import json\n", "import os\n", "import re\n", "from tavily import TavilyClient\n", "from IPython.display import display, Markdown, HTML, clear_output\n", "import time\n", "\n", "# 配置 API 密钥\n", "GEMINI_API_KEY = \"AIzaSyBYXm6uWt5-wDi9wXQ1oBhHhsMTWAH8kbo\"\n", "TAVILY_API_KEY = \"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\"\n", "MODEL_NAME = \"gemini-2.5-flash\" # 如果2.5不可用,使用1.5\n", "\n", "# 配置 Gemini\n", "genai.configure(api_key=GEMINI_API_KEY)\n", "\n", "# 配置 Tavily\n", "os.environ['TAVILY_API_KEY'] = TAVILY_API_KEY\n", "\n", "print(\"API 配置完成!\")" ] }, { "cell_type": "code", "execution_count": 35, "id": "66d9d404-3c95-42f2-8975-436769b3cb87", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 工具函数定义完成!\n" ] } ], "source": [ "# 单元块 2: 定义工具函数\n", "def get_weather(city: str) -> str:\n", " \"\"\"查询城市天气\"\"\"\n", " url = f\"https://wttr.in/{city}?format=j1\"\n", " \n", " try:\n", " response = requests.get(url)\n", " response.raise_for_status()\n", " data = response.json()\n", " \n", " current_condition = data['current_condition'][0]\n", " weather_desc = current_condition['weatherDesc'][0]['value']\n", " temp_c = current_condition['temp_C']\n", " humidity = current_condition['humidity']\n", " wind_speed = current_condition['windspeedKmph']\n", " \n", " return f\"{city}当前天气:{weather_desc},气温{temp_c}°C,湿度{humidity}%,风速{wind_speed}km/h\"\n", " \n", " except Exception as e:\n", " return f\"错误:查询天气时遇到问题 - {e}\"\n", "\n", "def get_attraction(city: str, weather: str) -> str:\n", " \"\"\"查询景点推荐\"\"\"\n", " try:\n", " tavily = TavilyClient(api_key=os.environ['TAVILY_API_KEY'])\n", " query = f\"'{city}' 在'{weather}'天气下最值得去的旅游景点推荐及理由\"\n", " \n", " response = tavily.search(query=query, search_depth=\"basic\", include_answer=True)\n", " \n", " if response.get(\"answer\"):\n", " return response[\"answer\"]\n", " \n", " formatted_results = []\n", " for result in response.get(\"results\", []):\n", " formatted_results.append(f\"- {result['title']}: {result['content']}\")\n", " \n", " if not formatted_results:\n", " return \"抱歉,没有找到相关的旅游景点推荐。\"\n", "\n", " return \"根据搜索,为您找到以下信息:\\n\" + \"\\n\".join(formatted_results)\n", "\n", " except Exception as e:\n", " return f\"错误:执行搜索时出现问题 - {e}\"\n", "\n", "print(\"✅ 工具函数定义完成!\")" ] }, { "cell_type": "code", "execution_count": 36, "id": "e953fee4-9e3c-4e34-bf48-4ea002c3bb92", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 智能助手类定义完成!\n" ] } ], "source": [ "# 单元块 3: 定义智能助手类\n", "class NotebookTravelAssistant:\n", " def __init__(self, model_name=\"gemini-1.5-flash\"):\n", " # 初始化模型\n", " self.model_name = model_name\n", " try:\n", " self.model = genai.GenerativeModel(model_name)\n", " except:\n", " print(f\"⚠️ 模型 {model_name} 不可用,使用 gemini-1.5-flash 替代\")\n", " self.model = genai.GenerativeModel(\"gemini-1.5-flash\")\n", " \n", " # 定义工具\n", " self.available_tools = {\n", " \"get_weather\": get_weather,\n", " \"get_attraction\": get_attraction,\n", " }\n", " \n", " # 系统提示词\n", " self.system_prompt = \"\"\"\n", "你是一个智能旅行助手。你的任务是分析用户的请求,并使用可用工具一步步地解决问题。\n", "\n", "# 可用工具:\n", "- `get_weather(city: str)`: 查询指定城市的实时天气。\n", "- `get_attraction(city: str, weather: str)`: 根据城市和天气搜索推荐的旅游景点。\n", "\n", "# 行动格式:\n", "你的回答必须严格遵循以下格式。首先是你的思考过程,然后是你要执行的具体行动。\n", "Thought: [这里是你的思考过程和下一步计划]\n", "Action: [这里是你要调用的工具,格式为 function_name(arg_name=\"arg_value\")]\n", "\n", "# 任务完成:\n", "当你收集到足够的信息,能够回答用户的最终问题时,你必须使用 `finish(answer=\"...\")` 来输出最终答案。\n", "\n", "请开始吧!\n", "\"\"\"\n", " \n", " def generate_response(self, prompt: str) -> str:\n", " \"\"\"调用Gemini生成回应\"\"\"\n", " full_prompt = f\"{self.system_prompt}\\n\\n用户请求: {prompt}\"\n", " response = self.model.generate_content(full_prompt)\n", " return response.text\n", " \n", " def parse_action(self, text: str):\n", " \"\"\"解析行动指令\"\"\"\n", " action_match = re.search(r\"Action: (.*)\", text, re.DOTALL)\n", " if not action_match:\n", " return None, None\n", " \n", " action_str = action_match.group(1).strip()\n", " \n", " if action_str.startswith(\"finish\"):\n", " final_answer_match = re.search(r'finish\\(answer=\"(.*)\"\\)', action_str)\n", " if final_answer_match:\n", " return \"finish\", final_answer_match.group(1)\n", " return \"finish\", \"抱歉,我无法提供完整的答案。\"\n", " \n", " tool_match = re.search(r\"(\\w+)\\((.*)\\)\", action_str)\n", " if not tool_match:\n", " return None, None\n", " \n", " tool_name = tool_match.group(1)\n", " args_str = tool_match.group(2)\n", " \n", " kwargs = {}\n", " if args_str:\n", " arg_matches = re.findall(r'(\\w+)=\"([^\"]*)\"', args_str)\n", " kwargs = dict(arg_matches)\n", " \n", " return tool_name, kwargs\n", "\n", "print(\"✅ 智能助手类定义完成!\")" ] }, { "cell_type": "code", "execution_count": 37, "id": "ab5d3142-c119-46ad-a7a1-ec1aa2e79435", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 显示函数定义完成!\n" ] } ], "source": [ "# 单元块 4: 定义显示函数\n", "def display_user_input(user_input):\n", " \"\"\"显示用户输入\"\"\"\n", " display(HTML(f\"\"\"\n", "
\n", "
👤 用户:
\n", "
{user_input}
\n", "
\n", " \"\"\"))\n", "\n", "def display_cycle_header(cycle_num):\n", " \"\"\"显示循环标题\"\"\"\n", " display(HTML(f\"\"\"\n", "
\n", " 🔄 循环 {cycle_num}:\n", "
\n", " \"\"\"))\n", "\n", "def display_thought(thought_text):\n", " \"\"\"显示思考过程\"\"\"\n", " display(HTML(f\"\"\"\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: {thought_text}
\n", "
\n", " \"\"\"))\n", "\n", "def display_action(tool_name, args):\n", " \"\"\"显示行动\"\"\"\n", " display(HTML(f\"\"\"\n", "
\n", " ⚡ 执行工具: {tool_name}({', '.join([f'{k}=\"{v}\"' for k, v in args.items()])})\n", "
\n", " \"\"\"))\n", "\n", "def display_observation(observation):\n", " \"\"\"显示观察结果\"\"\"\n", " display(HTML(f\"\"\"\n", "
\n", "
👁️ 观察结果:
\n", "
{observation}
\n", "
\n", " \"\"\"))\n", "\n", "def display_final_result(result):\n", " \"\"\"显示最终结果\"\"\"\n", " display(HTML(f\"\"\"\n", "
\n", "
✅ 任务完成!
\n", "
{result}
\n", "
\n", " \"\"\"))\n", "\n", "print(\"✅ 显示函数定义完成!\")" ] }, { "cell_type": "code", "execution_count": 38, "id": "cc543309-fe16-44a9-9735-bce828b9c7ad", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 主运行函数定义完成!\n" ] } ], "source": [ "# 单元块 5: 定义主运行函数\n", "def run_assistant(user_input, max_iterations=5):\n", " \"\"\"运行智能助手\"\"\"\n", " # 创建助手实例\n", " assistant = NotebookTravelAssistant(model_name=MODEL_NAME)\n", " \n", " # 显示用户输入\n", " display_user_input(user_input)\n", " \n", " prompt_history = [f\"用户请求: {user_input}\"]\n", " \n", " for i in range(max_iterations):\n", " # 显示循环标题\n", " display_cycle_header(i+1)\n", " \n", " # 调用模型\n", " full_prompt = \"\\n\".join(prompt_history)\n", " llm_output = assistant.generate_response(full_prompt)\n", " \n", " # 提取思考过程\n", " thought_match = re.search(r\"Thought: (.*?)(?=Action:|$)\", llm_output, re.DOTALL)\n", " thought_text = thought_match.group(1).strip() if thought_match else \"思考过程未明确显示\"\n", " \n", " # 显示思考过程\n", " display_thought(thought_text)\n", " \n", " # 解析并执行行动\n", " tool_name, args = assistant.parse_action(llm_output)\n", " \n", " if tool_name == \"finish\":\n", " # 显示最终结果\n", " display_final_result(args)\n", " return args\n", " \n", " elif tool_name in assistant.available_tools:\n", " # 显示行动\n", " display_action(tool_name, args)\n", " \n", " # 执行工具\n", " observation = assistant.available_tools[tool_name](**args)\n", " \n", " # 显示观察结果\n", " display_observation(observation)\n", " \n", " # 更新历史\n", " prompt_history.append(llm_output)\n", " prompt_history.append(f\"Observation: {observation}\")\n", " \n", " # 添加短暂延迟,使输出更易读\n", " time.sleep(1)\n", " else:\n", " display(HTML(f\"
❌ 无法解析行动: {tool_name}
\"))\n", " break\n", " \n", " return \"抱歉,我无法完成这个请求。请尝试更具体的查询。\"\n", "\n", "print(\"✅ 主运行函数定义完成!\")" ] }, { "cell_type": "code", "execution_count": 39, "id": "3f6e44eb-ff3d-4060-b4c2-ea3e139bf307", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
👤 用户:
\n", "
你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 1:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 用户首先要求查询北京的天气,然后根据天气推荐旅游景点。我需要先调用 `get_weather` 工具来获取北京的天气信息。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " ⚡ 执行工具: get_weather(city=\"北京\")\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
👁️ 观察结果:
\n", "
北京当前天气:Mist,气温8°C,湿度100%,风速8km/h
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 2:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 我已经获取了北京的天气信息是 \"Mist\"。现在我需要根据这个天气信息来推荐一个合适的旅游景点。我将使用 `get_attraction` 工具,将城市设置为 \"北京\",天气设置为 \"Mist\"。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " ⚡ 执行工具: get_attraction(city=\"北京\", weather=\"Mist\")\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
👁️ 观察结果:
\n", "
In mist weather, Beijing's Forbidden City, Temple of Heaven, and Summer Palace are best for sightseeing. These sites offer indoor attractions and clear views despite weather.
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 3:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 我已经获取了北京的天气信息是 \"Mist\",并且根据这个天气推荐了景点:故宫、天坛和颐和园。现在我拥有了回答用户请求的所有信息。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
✅ 任务完成!
\n", "
您好!今天北京的天气是:有薄雾(Mist),气温8°C。根据薄雾天气,推荐您去故宫、天坛和颐和园游览,这些景点即使在薄雾天气下也能提供室内景点或清晰的视野。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# 单元块 6: 运行示例\n", "user_input = \"你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点\"\n", "result = run_assistant(user_input)" ] }, { "cell_type": "code", "execution_count": 40, "id": "68c735c1-eb3e-40e7-8b70-2be941798187", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 交互式对话功能已加载!\n", "运行 'interactive_travel_assistant()' 开始对话\n" ] } ], "source": [ "# 单元块 7: 实现交互式对话功能\n", "def interactive_travel_assistant():\n", " \"\"\"交互式旅行助手\"\"\"\n", " print(\"🌍 欢迎使用智能旅行助手!\")\n", " print(\"=\" * 50)\n", " print(\"我可以帮您查询任何城市的天气,并根据天气推荐合适的旅游景点。\")\n", " print(\"您只需输入城市名称,我将为您提供完整的旅行建议。\")\n", " print(\"输入 '退出'、'quit' 或 'exit' 可以结束对话。\")\n", " print(\"=\" * 50)\n", " \n", " conversation_count = 0\n", " \n", " while True:\n", " # 获取用户输入\n", " user_input = input(f\"\\n🏙️ 请输入城市名称 (对话 {conversation_count + 1}): \").strip()\n", " \n", " # 检查退出条件\n", " if user_input.lower() in ['退出', 'quit', 'exit']:\n", " print(\"\\n\" + \"=\" * 50)\n", " print(\"👋 感谢使用智能旅行助手,期待下次为您服务!\")\n", " print(\"=\" * 50)\n", " break\n", " \n", " # 检查空输入\n", " if not user_input:\n", " print(\"⚠️ 请输入有效的城市名称。\")\n", " continue\n", " \n", " # 构建查询\n", " query = f\"请帮我查询{user_input}的天气,然后根据天气推荐合适的旅游景点\"\n", " \n", " print(f\"\\n📡 处理您的请求: {query}\")\n", " print(\"-\" * 50)\n", " \n", " # 运行助手\n", " result = run_assistant(query)\n", " \n", " # 增加对话计数\n", " conversation_count += 1\n", " \n", " print(\"\\n\" + \"=\" * 50)\n", " print(f\"💫 已完成 {conversation_count} 次对话\")\n", " print(\"=\" * 50)\n", "\n", "# 启动交互式助手\n", "print(\"✅ 交互式对话功能已加载!\")\n", "print(\"运行 'interactive_travel_assistant()' 开始对话\")" ] }, { "cell_type": "code", "execution_count": 41, "id": "bc58c911-8502-4cf5-aa3f-a9f57a94b679", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "🌍 欢迎使用智能旅行助手!\n", "==================================================\n", "我可以帮您查询任何城市的天气,并根据天气推荐合适的旅游景点。\n", "您只需输入城市名称,我将为您提供完整的旅行建议。\n", "输入 '退出'、'quit' 或 'exit' 可以结束对话。\n", "==================================================\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "\n", "🏙️ 请输入城市名称 (对话 1): 伦敦\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "📡 处理您的请求: 请帮我查询伦敦的天气,然后根据天气推荐合适的旅游景点\n", "--------------------------------------------------\n" ] }, { "data": { "text/html": [ "\n", "
\n", "
👤 用户:
\n", "
请帮我查询伦敦的天气,然后根据天气推荐合适的旅游景点
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 1:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 用户请求查询伦敦的天气,并根据天气推荐景点。第一步是获取伦敦的天气。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " ⚡ 执行工具: get_weather(city=\"伦敦\")\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
👁️ 观察结果:
\n", "
伦敦当前天气:Clear,气温9°C,湿度93%,风速12km/h
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 2:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 我已经查询到伦敦的天气是\"Clear\"。现在我需要根据这个天气信息来推荐伦敦的旅游景点。我可以使用 `get_attraction` 工具,将城市设置为\"伦敦\",天气设置为\"Clear\"。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " ⚡ 执行工具: get_attraction(city=\"伦敦\", weather=\"Clear\")\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
👁️ 观察结果:
\n", "
在伦敦天气晴朗时,乘船游览泰晤士河是最佳选择,欣赏国会大厦和伦敦眼。白天参观西敏寺和大本钟。格林威治天文台也是不错的景点。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 3:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 我已经查询到伦敦的天气信息,并且根据晴朗的天气推荐了合适的旅游景点。现在我拥有了所有必要的信息来回答用户的请求。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
✅ 任务完成!
\n", "
伦敦目前天气晴朗,气温9°C。在伦敦天气晴朗时,乘船游览泰晤士河是最佳选择,可以欣赏国会大厦和伦敦眼。白天还可以参观西敏寺、大本钟和格林威治天文台。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "==================================================\n", "💫 已完成 1 次对话\n", "==================================================\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "\n", "🏙️ 请输入城市名称 (对话 2): 郑州\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "📡 处理您的请求: 请帮我查询郑州的天气,然后根据天气推荐合适的旅游景点\n", "--------------------------------------------------\n" ] }, { "data": { "text/html": [ "\n", "
\n", "
👤 用户:
\n", "
请帮我查询郑州的天气,然后根据天气推荐合适的旅游景点
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 1:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 用户请求包含两个步骤:首先查询郑州的天气,然后根据天气推荐景点。我需要先调用 `get_weather` 工具获取郑州的天气信息。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " ⚡ 执行工具: get_weather(city=\"郑州\")\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
👁️ 观察结果:
\n", "
郑州当前天气:Mist,气温10°C,湿度94%,风速4km/h
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 2:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 我已经查询到了郑州的天气是 \"Mist\"。现在我需要根据这个天气信息,调用 `get_attraction` 工具来推荐旅游景点。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " ⚡ 执行工具: get_attraction(city=\"郑州\", weather=\"Mist\")\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
👁️ 观察结果:
\n", "
在雾霾天气下,郑州的二七纪念塔和新稀伏羲山景区是最值得去的旅游景点。这些地方空气质量较好,景色优美。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 3:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 我已经获取了郑州的天气信息和根据该天气推荐的旅游景点。现在我可以将这些信息整合起来,回答用户的请求。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
✅ 任务完成!
\n", "
郑州当前天气:Mist,气温10°C,湿度94%,风速4km/h。根据当前雾蒙蒙的天气,推荐您前往二七纪念塔和新稀伏羲山景区,这些地方空气质量较好,景色优美。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "==================================================\n", "💫 已完成 2 次对话\n", "==================================================\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "\n", "🏙️ 请输入城市名称 (对话 3): 莆田\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "📡 处理您的请求: 请帮我查询莆田的天气,然后根据天气推荐合适的旅游景点\n", "--------------------------------------------------\n" ] }, { "data": { "text/html": [ "\n", "
\n", "
👤 用户:
\n", "
请帮我查询莆田的天气,然后根据天气推荐合适的旅游景点
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 1:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 用户请求包含两个步骤:首先查询莆田的天气,然后根据天气推荐景点。我需要先使用 `get_weather` 工具获取莆田的天气信息。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " ⚡ 执行工具: get_weather(city=\"莆田\")\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
👁️ 观察结果:
\n", "
莆田当前天气:Partly cloudy,气温19°C,湿度77%,风速10km/h
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 2:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 我已经获取了莆田的天气信息是 \"Partly cloudy\"。现在我需要根据这个天气信息,使用 `get_attraction` 工具来推荐合适的旅游景点。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " ⚡ 执行工具: get_attraction(city=\"莆田\", weather=\"Partly cloudy\")\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
👁️ 观察结果:
\n", "
莆田在多云天气下,莆田市博物馆和莆田古城是最值得去的景点。这些地方风景宜人,适合观光。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " 🔄 循环 3:\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
🧠 智能体响应:
\n", "
Thought: 我已经获取了莆田的天气信息和根据天气推荐的旅游景点。现在我可以将这些信息整合成最终答案。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
✅ 任务完成!
\n", "
莆田当前天气:Partly cloudy,气温19°C,湿度77%,风速10km/h。在多云天气下,莆田市博物馆和莆田古城是最值得去的景点,这些地方风景宜人,适合观光。
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "==================================================\n", "💫 已完成 3 次对话\n", "==================================================\n" ] }, { "ename": "KeyboardInterrupt", "evalue": "Interrupted by user", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mKeyboardInterrupt\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[41]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;66;03m# 启动交互式对话\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m \u001b[43minteractive_travel_assistant\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[40]\u001b[39m\u001b[32m, line 15\u001b[39m, in \u001b[36minteractive_travel_assistant\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m 11\u001b[39m conversation_count = \u001b[32m0\u001b[39m\n\u001b[32m 13\u001b[39m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[32m 14\u001b[39m \u001b[38;5;66;03m# 获取用户输入\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m15\u001b[39m user_input = \u001b[38;5;28;43minput\u001b[39;49m\u001b[43m(\u001b[49m\u001b[33;43mf\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[33;43m🏙️ 请输入城市名称 (对话 \u001b[39;49m\u001b[38;5;132;43;01m{\u001b[39;49;00m\u001b[43mconversation_count\u001b[49m\u001b[38;5;250;43m \u001b[39;49m\u001b[43m+\u001b[49m\u001b[38;5;250;43m \u001b[39;49m\u001b[32;43m1\u001b[39;49m\u001b[38;5;132;43;01m}\u001b[39;49;00m\u001b[33;43m): \u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m.strip()\n\u001b[32m 17\u001b[39m \u001b[38;5;66;03m# 检查退出条件\u001b[39;00m\n\u001b[32m 18\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m user_input.lower() \u001b[38;5;129;01min\u001b[39;00m [\u001b[33m'\u001b[39m\u001b[33m退出\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mquit\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mexit\u001b[39m\u001b[33m'\u001b[39m]:\n", "\u001b[36mFile \u001b[39m\u001b[32mD:\\Anaconda\\envs\\hello_agents\\Lib\\site-packages\\ipykernel\\kernelbase.py:1275\u001b[39m, in \u001b[36mKernel.raw_input\u001b[39m\u001b[34m(self, prompt)\u001b[39m\n\u001b[32m 1273\u001b[39m msg = \u001b[33m\"\u001b[39m\u001b[33mraw_input was called, but this frontend does not support input requests.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 1274\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m StdinNotImplementedError(msg)\n\u001b[32m-> \u001b[39m\u001b[32m1275\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_input_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 1276\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mprompt\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1277\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_parent_ident\u001b[49m\u001b[43m[\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mshell\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1278\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mget_parent\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mshell\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1279\u001b[39m \u001b[43m \u001b[49m\u001b[43mpassword\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[32m 1280\u001b[39m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", "\u001b[36mFile \u001b[39m\u001b[32mD:\\Anaconda\\envs\\hello_agents\\Lib\\site-packages\\ipykernel\\kernelbase.py:1320\u001b[39m, in \u001b[36mKernel._input_request\u001b[39m\u001b[34m(self, prompt, ident, parent, password)\u001b[39m\n\u001b[32m 1317\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m:\n\u001b[32m 1318\u001b[39m \u001b[38;5;66;03m# re-raise KeyboardInterrupt, to truncate traceback\u001b[39;00m\n\u001b[32m 1319\u001b[39m msg = \u001b[33m\"\u001b[39m\u001b[33mInterrupted by user\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m-> \u001b[39m\u001b[32m1320\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m(msg) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m 1321\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n\u001b[32m 1322\u001b[39m \u001b[38;5;28mself\u001b[39m.log.warning(\u001b[33m\"\u001b[39m\u001b[33mInvalid Message:\u001b[39m\u001b[33m\"\u001b[39m, exc_info=\u001b[38;5;28;01mTrue\u001b[39;00m)\n", "\u001b[31mKeyboardInterrupt\u001b[39m: Interrupted by user" ] } ], "source": [ "# 启动交互式对话\n", "interactive_travel_assistant()" ] }, { "cell_type": "code", "execution_count": null, "id": "b84ad2cf-d240-4322-9e91-5da2af51f53f", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3.11 (hello_agents Environment)", "language": "python", "name": "hello_agents" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.14" } }, "nbformat": 4, "nbformat_minor": 5 }