{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "938b2e36-f95c-4b0f-8770-335c6bb5bc0e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import json\n",
    "import os\n",
    "import re\n",
    "from openai import OpenAI\n",
    "from tavily import TavilyClient\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# 加载环境变量\n",
    "load_dotenv()\n",
    "\n",
    "# 配置API密钥\n",
    "API_KEY = os.getenv(\"API_KEY\")\n",
    "BASE_URL = os.getenv(\"BASE_URL\")\n",
    "MODEL_ID = os.getenv(\"MODEL_ID\")\n",
    "TAVILY_API_KEY = os.getenv(\"TAVILY_API_KEY\")\n",
    "\n",
    "os.environ['TAVILY_API_KEY'] = TAVILY_API_KEY\n",
    "\n",
    "# 系统提示词\n",
    "AGENT_SYSTEM_PROMPT = \"\"\"\n",
    "你是一个智能旅行助手。你的任务是分析用户的请求，并使用可用工具一步步地解决问题。\n",
    "\n",
    "# 可用工具:\n",
    "- `get_weather(city: str)`: 查询指定城市的实时天气。\n",
    "- `get_attraction(city: str, weather: str)`: 根据城市和天气搜索推荐的旅游景点。\n",
    "\n",
    "# 行动格式:\n",
    "你的回答必须严格遵循以下格式。首先是你的思考过程，然后是你要执行的具体行动，每次回复只输出一对Thought-Action：\n",
    "Thought: [这里是你的思考过程和下一步计划]\n",
    "Action: [这里是你要调用的工具，格式为 function_name(arg_name=\"arg_value\")]\n",
    "\n",
    "# 任务完成:\n",
    "当你收集到足够的信息，能够回答用户的最终问题时，你必须在`Action:`字段后使用 `finish(answer=\"...\")` 来输出最终答案。\n",
    "\n",
    "请开始吧！\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "66d9d404-3c95-42f2-8975-436769b3cb87",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ 工具函数定义完成!\n"
     ]
    }
   ],
   "source": [
    "def get_weather(city: str) -> str:\n",
    "    \"\"\"\n",
    "    通过调用 wttr.in API 查询真实的天气信息。\n",
    "    \"\"\"\n",
    "    # API端点，我们请求JSON格式的数据\n",
    "    url = f\"https://wttr.in/{city}?format=j1\"\n",
    "    \n",
    "    try:\n",
    "        # 发起网络请求\n",
    "        response = requests.get(url)\n",
    "        # 检查响应状态码是否为200 (成功)\n",
    "        response.raise_for_status() \n",
    "        # 解析返回的JSON数据\n",
    "        data = response.json()\n",
    "        \n",
    "        # 提取当前天气状况\n",
    "        current_condition = data['current_condition'][0]\n",
    "        weather_desc = current_condition['weatherDesc'][0]['value']\n",
    "        temp_c = current_condition['temp_C']\n",
    "        \n",
    "        # 格式化成自然语言返回\n",
    "        return f\"{city}当前天气：{weather_desc}，气温{temp_c}摄氏度\"\n",
    "        \n",
    "    except requests.exceptions.RequestException as e:\n",
    "        # 处理网络错误\n",
    "        return f\"错误：查询天气时遇到网络问题 - {e}\"\n",
    "    except (KeyError, IndexError) as e:\n",
    "        # 处理数据解析错误\n",
    "        return f\"错误：解析天气数据失败，可能是城市名称无效 - {e}\"\n",
    "\n",
    "def get_attraction(city: str, weather: str) -> str:\n",
    "    \"\"\"\n",
    "    根据城市和天气，使用Tavily Search API搜索并返回优化后的景点推荐。\n",
    "    \"\"\"\n",
    "    api_key = os.environ.get(\"TAVILY_API_KEY\")\n",
    "\n",
    "    if not api_key:\n",
    "        return \"错误：未配置TAVILY_API_KEY。\"\n",
    "\n",
    "    # 初始化Tavily客户端\n",
    "    tavily = TavilyClient(api_key=api_key)\n",
    "    \n",
    "    # 构造一个精确的查询\n",
    "    query = f\"'{city}' 在'{weather}'天气下最值得去的旅游景点推荐及理由\"\n",
    "    \n",
    "    try:\n",
    "        # 调用API，include_answer=True会返回一个综合性的回答\n",
    "        response = tavily.search(query=query, search_depth=\"basic\", include_answer=True)\n",
    "        \n",
    "        # Tavily返回的结果已经非常干净，可以直接使用\n",
    "        if response.get(\"answer\"):\n",
    "            return response[\"answer\"]\n",
    "        \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\"错误：执行Tavily搜索时出现问题 - {e}\"\n",
    "\n",
    "# 将所有工具函数放入一个字典，方便后续调用\n",
    "available_tools = {\n",
    "    \"get_weather\": get_weather,\n",
    "    \"get_attraction\": get_attraction,\n",
    "}\n",
    "print(\"✅ 工具函数定义完成!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e953fee4-9e3c-4e34-bf48-4ea002c3bb92",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ 智能助手类定义完成!\n"
     ]
    }
   ],
   "source": [
    "class OpenAICompatibleClient:\n",
    "    \"\"\"\n",
    "    一个用于调用任何兼容OpenAI接口的LLM服务的客户端。\n",
    "    \"\"\"\n",
    "    def __init__(self, model: str, api_key: str, base_url: str):\n",
    "        self.model = model\n",
    "        self.client = OpenAI(api_key=api_key, base_url=base_url)\n",
    "\n",
    "    def generate(self, prompt: str, system_prompt: str) -> str:\n",
    "        \"\"\"调用LLM API来生成回应。\"\"\"\n",
    "        print(\"正在调用大语言模型...\")\n",
    "        try:\n",
    "            messages = [\n",
    "                {'role': 'system', 'content': system_prompt},\n",
    "                {'role': 'user', 'content': prompt}\n",
    "            ]\n",
    "            response = self.client.chat.completions.create(\n",
    "                model=self.model,\n",
    "                messages=messages,\n",
    "                stream=False\n",
    "            )\n",
    "            answer = response.choices[0].message.content\n",
    "            print(\"大语言模型响应成功。\")\n",
    "            return answer\n",
    "        except Exception as e:\n",
    "            print(f\"调用LLM API时发生错误: {e}\")\n",
    "            return \"错误：调用语言模型服务时出错。\"\n",
    "\n",
    "class TravelAssistant:\n",
    "    \"\"\"\n",
    "    智能旅行助手类\n",
    "    \"\"\"\n",
    "    def __init__(self):\n",
    "        self.llm = OpenAICompatibleClient(\n",
    "            model=MODEL_ID,\n",
    "            api_key=API_KEY,\n",
    "            base_url=BASE_URL\n",
    "        )\n",
    "        self.prompt_history = []\n",
    "    \n",
    "    def reset(self):\n",
    "        \"\"\"重置对话历史\"\"\"\n",
    "        self.prompt_history = []\n",
    "    \n",
    "    def add_user_message(self, message: str):\n",
    "        \"\"\"添加用户消息到历史\"\"\"\n",
    "        self.prompt_history.append(f\"用户请求: {message}\")\n",
    "    \n",
    "    def add_assistant_message(self, message: str):\n",
    "        \"\"\"添加助手消息到历史\"\"\"\n",
    "        self.prompt_history.append(message)\n",
    "    \n",
    "    def add_observation(self, observation: str):\n",
    "        \"\"\"添加观察结果到历史\"\"\"\n",
    "        self.prompt_history.append(f\"Observation: {observation}\")\n",
    "print(\"✅ 智能助手类定义完成!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "ab5d3142-c119-46ad-a7a1-ec1aa2e79435",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ 显示函数定义完成!\n"
     ]
    }
   ],
   "source": [
    "def display_conversation(history):\n",
    "    \"\"\"美观地显示对话历史\"\"\"\n",
    "    print(\"\\n\" + \"=\"*60)\n",
    "    print(\"📝 对话历史\")\n",
    "    print(\"=\"*60)\n",
    "    \n",
    "    for i, message in enumerate(history, 1):\n",
    "        if message.startswith(\"用户请求:\"):\n",
    "            print(f\"\\n👤 用户 [{i}]: {message[5:]}\")\n",
    "        elif message.startswith(\"Thought:\"):\n",
    "            print(f\"\\n🤔 思考 [{i}]: {message[8:].strip()}\")\n",
    "        elif message.startswith(\"Action:\"):\n",
    "            print(f\"🛠️  行动 [{i}]: {message[7:].strip()}\")\n",
    "        elif message.startswith(\"Observation:\"):\n",
    "            print(f\"📊 观察 [{i}]: {message[12:].strip()}\")\n",
    "        else:\n",
    "            print(f\"💬 消息 [{i}]: {message}\")\n",
    "    \n",
    "    print(\"=\"*60 + \"\\n\")\n",
    "\n",
    "def parse_action(action_str):\n",
    "    \"\"\"解析行动字符串\"\"\"\n",
    "    if action_str.startswith(\"finish\"):\n",
    "        match = re.search(r'finish\\(answer=\"(.*)\"\\)', action_str)\n",
    "        if match:\n",
    "            return \"finish\", {\"answer\": match.group(1)}\n",
    "        return \"finish\", {\"answer\": \"任务完成\"}\n",
    "    \n",
    "    tool_name_match = re.search(r\"(\\w+)\\(\", action_str)\n",
    "    if not tool_name_match:\n",
    "        return None, {}\n",
    "    \n",
    "    tool_name = tool_name_match.group(1)\n",
    "    args_match = re.search(r\"\\((.*)\\)\", action_str)\n",
    "    if args_match:\n",
    "        args_str = args_match.group(1)\n",
    "        kwargs = dict(re.findall(r'(\\w+)=\"([^\"]*)\"', args_str))\n",
    "    else:\n",
    "        kwargs = {}\n",
    "    \n",
    "    return tool_name, kwargs\n",
    "print(\"✅ 显示函数定义完成!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc543309-fe16-44a9-9735-bce828b9c7ad",
   "metadata": {},
   "outputs": [],
   "source": [
    "def run_assistant(user_input, max_iterations=5, display=True):\n",
    "    \"\"\"\n",
    "    运行旅行助手的主函数\n",
    "    \n",
    "    Args:\n",
    "        user_input: 用户输入的问题\n",
    "        max_iterations: 最大循环次数\n",
    "        display: 是否显示对话历史\n",
    "    \n",
    "    Returns:\n",
    "        tuple: (最终答案, 完整的对话历史)\n",
    "    \"\"\"\n",
    "    assistant = TravelAssistant()\n",
    "    assistant.add_user_message(user_input)\n",
    "    \n",
    "    if display:\n",
    "        print(f\"👤 用户输入: {user_input}\")\n",
    "        print(\"=\"*50)\n",
    "    \n",
    "    for i in range(max_iterations):\n",
    "        if display:\n",
    "            print(f\"\\n🔄 循环 {i+1}/{max_iterations}\")\n",
    "        \n",
    "        # 构建完整prompt并调用LLM\n",
    "        full_prompt = \"\\n\".join(assistant.prompt_history)\n",
    "        llm_output = assistant.llm.generate(full_prompt, AGENT_SYSTEM_PROMPT)\n",
    "        # 模型可能会输出多余的Thought-Action，需要截断\n",
    "        match = re.search(r'(Thought:.*?Action:.*?)(?=\\n\\s*(?:Thought:|Action:|Observation:)|\\Z)', llm_output, re.DOTALL)\n",
    "        if match:\n",
    "            truncated = match.group(1).strip()\n",
    "            if truncated != llm_output.strip():\n",
    "                llm_output = truncated\n",
    "                print(\"⚠️ 已截断多余的 Thought-Action 对\")\n",
    "        \n",
    "        assistant.add_assistant_message(llm_output)\n",
    "        \n",
    "        if display:\n",
    "            print(f\"🤖 模型输出:\\n{llm_output}\")\n",
    "        \n",
    "        # 解析行动\n",
    "        action_match = re.search(r\"Action: (.*)\", llm_output, re.DOTALL)\n",
    "        if not action_match:\n",
    "            print(\"❌ 解析错误：模型输出中未找到 Action。\")\n",
    "            break\n",
    "            \n",
    "        action_str = action_match.group(1).strip()\n",
    "        tool_name, kwargs = parse_action(action_str)\n",
    "        \n",
    "        # 处理完成行动\n",
    "        if tool_name == \"finish\":\n",
    "            final_answer = kwargs.get(\"answer\", \"任务完成\")\n",
    "            if display:\n",
    "                print(f\"🎉 任务完成!\")\n",
    "                print(f\"📋 最终答案: {final_answer}\")\n",
    "            return final_answer, assistant.prompt_history\n",
    "        \n",
    "        # 处理工具调用\n",
    "        if tool_name in available_tools:\n",
    "            if display:\n",
    "                print(f\"🛠️  调用工具: {tool_name}({kwargs})\")\n",
    "            observation = available_tools[tool_name](**kwargs)\n",
    "        else:\n",
    "            observation = f\"错误：未定义的工具 '{tool_name}'\"\n",
    "        \n",
    "        # 记录观察结果\n",
    "        if display:\n",
    "            print(f\"📊 观察结果: {observation}\")\n",
    "            print(\"=\"*50)\n",
    "        \n",
    "        assistant.add_observation(observation)\n",
    "    \n",
    "    # 如果达到最大循环次数仍未完成\n",
    "    timeout_answer = \"抱歉，经过多次尝试仍未完成您的请求。请尝试简化您的问题或稍后重试。\"\n",
    "    if display:\n",
    "        print(f\"⏰ 达到最大循环次数: {timeout_answer}\")\n",
    "    \n",
    "    return timeout_answer, assistant.prompt_history"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3f6e44eb-ff3d-4060-b4c2-ea3e139bf307",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🚀 开始测试北京天气+景点推荐示例\n",
      "👤 用户输入: 你好，请帮我查询一下今天北京的天气，然后根据天气推荐一个合适的旅游景点。\n",
      "==================================================\n",
      "\n",
      "🔄 循环 1/5\n",
      "正在调用大语言模型...\n",
      "大语言模型响应成功。\n",
      "🤖 模型输出:\n",
      "Thought: 用户希望查询今天北京的天气情况，然后基于该天气推荐一个合适的旅游景点。我的第一步是获取北京的实时天气信息，以便了解当前的天气状况。执行查询天气的操作。\n",
      "\n",
      "Action: get_weather(city=\"北京\")\n",
      "🛠️  调用工具: get_weather({'city': '北京'})\n",
      "📊 观察结果: 北京当前天气：Clear，气温9摄氏度\n",
      "==================================================\n",
      "\n",
      "🔄 循环 2/5\n",
      "正在调用大语言模型...\n",
      "大语言模型响应成功。\n",
      "🤖 模型输出:\n",
      "Thought: 我已经获得了北京当前的天气信息：晴天，气温9摄氏度。接下来的步骤是根据这个天气条件推荐一个合适的旅游景点。晴天通常适合户外活动，这将影响我的选择。接下来，我将调用工具获取推荐的旅游景点。 \n",
      "\n",
      "Action: get_attraction(city=\"北京\", weather=\"Clear\")\n",
      "🛠️  调用工具: get_attraction({'city': '北京', 'weather': 'Clear'})\n",
      "📊 观察结果: 在晴天，北京的长城（如八达岭）和故宫是最值得去的景点。晴天下，这些地方的景色最美，游览最舒适。\n",
      "==================================================\n",
      "\n",
      "🔄 循环 3/5\n",
      "正在调用大语言模型...\n",
      "大语言模型响应成功。\n",
      "🤖 模型输出:\n",
      "Thought: 我已经获得了关于北京当前天气的信息，并找到了两个适合在晴天游览的旅游景点。长城和故宫都是著名的地标性景点，特别在晴天时更是吸引游客。接下来，我准备输出最终的推荐答案。\n",
      "\n",
      "Action: finish(answer=\"今天北京的天气晴，气温9摄氏度。推荐您去长城（如八达岭）或故宫游览，这两个景点在这样的天气下非常适合。\")\n",
      "🎉 任务完成!\n",
      "📋 最终答案: 今天北京的天气晴，气温9摄氏度。推荐您去长城（如八达岭）或故宫游览，这两个景点在这样的天气下非常适合。\n",
      "\n",
      "============================================================\n",
      "📊 测试完成!\n",
      "============================================================\n",
      "最终答案: 今天北京的天气晴，气温9摄氏度。推荐您去长城（如八达岭）或故宫游览，这两个景点在这样的天气下非常适合。\n",
      "\n",
      "============================================================\n",
      "📝 对话历史\n",
      "============================================================\n",
      "\n",
      "👤 用户 [1]:  你好，请帮我查询一下今天北京的天气，然后根据天气推荐一个合适的旅游景点。\n",
      "\n",
      "🤔 思考 [2]: 用户希望查询今天北京的天气情况，然后基于该天气推荐一个合适的旅游景点。我的第一步是获取北京的实时天气信息，以便了解当前的天气状况。执行查询天气的操作。\n",
      "\n",
      "Action: get_weather(city=\"北京\")\n",
      "📊 观察 [3]: 北京当前天气：Clear，气温9摄氏度\n",
      "\n",
      "🤔 思考 [4]: 我已经获得了北京当前的天气信息：晴天，气温9摄氏度。接下来的步骤是根据这个天气条件推荐一个合适的旅游景点。晴天通常适合户外活动，这将影响我的选择。接下来，我将调用工具获取推荐的旅游景点。 \n",
      "\n",
      "Action: get_attraction(city=\"北京\", weather=\"Clear\")\n",
      "📊 观察 [5]: 在晴天，北京的长城（如八达岭）和故宫是最值得去的景点。晴天下，这些地方的景色最美，游览最舒适。\n",
      "\n",
      "🤔 思考 [6]: 我已经获得了关于北京当前天气的信息，并找到了两个适合在晴天游览的旅游景点。长城和故宫都是著名的地标性景点，特别在晴天时更是吸引游客。接下来，我准备输出最终的推荐答案。\n",
      "\n",
      "Action: finish(answer=\"今天北京的天气晴，气温9摄氏度。推荐您去长城（如八达岭）或故宫游览，这两个景点在这样的天气下非常适合。\")\n",
      "============================================================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 测试示例\n",
    "def test_basic_example():\n",
    "    \"\"\"测试北京天气+景点推荐的示例\"\"\"\n",
    "    print(\"🚀 开始测试北京天气+景点推荐示例\")\n",
    "    user_input = \"你好，请帮我查询一下今天北京的天气，然后根据天气推荐一个合适的旅游景点。\"\n",
    "    \n",
    "    final_answer, history = run_assistant(user_input, display=True)\n",
    "    \n",
    "    print(\"\\n\" + \"=\"*60)\n",
    "    print(\"📊 测试完成!\")\n",
    "    print(\"=\"*60)\n",
    "    print(f\"最终答案: {final_answer}\")\n",
    "    \n",
    "    # 显示完整对话历史\n",
    "    display_conversation(history)\n",
    "    \n",
    "    return final_answer, history\n",
    "\n",
    "# 运行测试示例\n",
    "final_answer, history = test_basic_example()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "68c735c1-eb3e-40e7-8b70-2be941798187",
   "metadata": {},
   "outputs": [],
   "source": [
    "def interactive_travel_assistant():\n",
    "    \"\"\"\n",
    "    交互式旅行助手\n",
    "    \"\"\"\n",
    "    print(\"🌍 欢迎使用智能旅行助手!\")\n",
    "    print(\"💡 您可以询问任何城市的天气和旅游景点推荐\")\n",
    "    print(\"❌ 输入 'quit' 或 '退出' 来结束对话\\n\")\n",
    "    \n",
    "    while True:\n",
    "        user_input = input(\"👤 请输入您的问题: \").strip()\n",
    "        \n",
    "        if user_input.lower() in ['quit', '退出', 'exit']:\n",
    "            print(\"👋 感谢使用智能旅行助手，再见!\")\n",
    "            break\n",
    "        \n",
    "        if not user_input:\n",
    "            print(\"⚠️  请输入有效的问题\")\n",
    "            continue\n",
    "        \n",
    "        print(\"\\n\" + \"=\"*50)\n",
    "        print(\"🔄 正在处理您的请求...\")\n",
    "        \n",
    "        final_answer, history = run_assistant(user_input, display=True)\n",
    "        \n",
    "        print(\"\\n🎯 最终回答:\")\n",
    "        print(\"=\"*30)\n",
    "        print(final_answer)\n",
    "        print(\"=\"*30)\n",
    "        \n",
    "        # 询问是否显示完整对话历史\n",
    "        show_history = input(\"\\n📖 是否显示完整对话历史? (y/n): \").strip().lower()\n",
    "        if show_history in ['y', 'yes', '是']:\n",
    "            display_conversation(history)\n",
    "        \n",
    "        print(\"\\n\" + \"=\"*60)\n",
    "        print(\"🔄 准备接受下一个问题...\\n\")\n",
    "\n",
    "# 快速测试函数\n",
    "def quick_test(city=\"上海\"):\n",
    "    \"\"\"快速测试指定城市的天气和景点\"\"\"\n",
    "    user_input = f\"请帮我查询{city}的天气，并推荐适合的旅游景点\"\n",
    "    print(f\"🚀 快速测试: {user_input}\")\n",
    "    final_answer, _ = run_assistant(user_input, display=True)\n",
    "    return final_answer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bc58c911-8502-4cf5-aa3f-a9f57a94b679",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "选择运行模式:\n",
      "1. 运行测试示例 (北京)\n",
      "2. 交互模式\n",
      "3. 快速测试其他城市\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "请输入选择 (1/2/3):  3\n",
      "请输入要测试的城市:  伦敦\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🚀 快速测试: 请帮我查询伦敦的天气，并推荐适合的旅游景点\n",
      "👤 用户输入: 请帮我查询伦敦的天气，并推荐适合的旅游景点\n",
      "==================================================\n",
      "\n",
      "🔄 循环 1/5\n",
      "正在调用大语言模型...\n",
      "大语言模型响应成功。\n",
      "🤖 模型输出:\n",
      "Thought: 我需要先查询伦敦的实时天气，这样才能根据天气情况推荐合适的旅游景点。接下来，我将调用天气查询工具获取伦敦的天气信息。 \n",
      "Action: get_weather(city=\"伦敦\")\n",
      "🛠️  调用工具: get_weather({'city': '伦敦'})\n",
      "📊 观察结果: 伦敦当前天气：Partly cloudy，气温16摄氏度\n",
      "==================================================\n",
      "\n",
      "🔄 循环 2/5\n",
      "正在调用大语言模型...\n",
      "大语言模型响应成功。\n",
      "🤖 模型输出:\n",
      "Thought: 现在我已经查询到了伦敦的实时天气情况：部分多云，气温为16摄氏度。接下来，我将根据这个天气情况推荐适合在伦敦游玩的旅游景点。 \n",
      "Action: get_attraction(city=\"伦敦\", weather=\"Partly cloudy\")\n",
      "🛠️  调用工具: get_attraction({'city': '伦敦', 'weather': 'Partly cloudy'})\n",
      "📊 观察结果: 在伦敦多云天气下，伦敦眼是最值得去的景点。它提供了伟大的城市景观。此外，博物馆和画廊也适合参观。\n",
      "==================================================\n",
      "\n",
      "🔄 循环 3/5\n",
      "正在调用大语言模型...\n",
      "大语言模型响应成功。\n",
      "🤖 模型输出:\n",
      "Thought: 我已经获取了伦敦的天气情况和适合的旅游景点推荐。当前天气为部分多云，推荐旅游景点为伦敦眼，同时博物馆和画廊也非常适合在这种天气下参观。最终我将整合这些信息并给出用户的建议。 \n",
      "Action: finish(answer=\"伦敦当前天气为部分多云，气温16摄氏度。根据天气情况，推荐您去伦敦眼欣赏城市景观，此外博物馆和画廊也是很好的选择。\")\n",
      "🎉 任务完成!\n",
      "📋 最终答案: 伦敦当前天气为部分多云，气温16摄氏度。根据天气情况，推荐您去伦敦眼欣赏城市景观，此外博物馆和画廊也是很好的选择。\n"
     ]
    }
   ],
   "source": [
    "# 主启动入口\n",
    "if __name__ == \"__main__\":\n",
    "    # 可以选择直接运行测试示例\n",
    "    print(\"选择运行模式:\")\n",
    "    print(\"1. 运行测试示例 (北京)\")\n",
    "    print(\"2. 交互模式\")\n",
    "    print(\"3. 快速测试其他城市\")\n",
    "    \n",
    "    choice = input(\"请输入选择 (1/2/3): \").strip()\n",
    "    \n",
    "    if choice == \"1\":\n",
    "        test_basic_example()\n",
    "    elif choice == \"2\":\n",
    "        interactive_travel_assistant()\n",
    "    elif choice == \"3\":\n",
    "        city = input(\"请输入要测试的城市: \").strip() or \"上海\"\n",
    "        quick_test(city)\n",
    "    else:\n",
    "        print(\"无效选择，运行测试示例...\")\n",
    "        test_basic_example()"
   ]
  },
  {
   "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
}
