Explorar o código

Merge pull request #290 from Tangent-90C/main

Fix: 修复章节4.2中ReAct Prompt在Finish部分的歧义
jjyaoao hai 5 meses
pai
achega
8d62bb5838

+ 172 - 136
code/chapter1/FirstAgentTest.ipynb

@@ -2,10 +2,13 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": null,
    "id": "938b2e36-f95c-4b0f-8770-335c6bb5bc0e",
-   "metadata": {},
-   "outputs": [],
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2026-01-14T15:56:53.621032679Z",
+     "start_time": "2026-01-14T15:56:53.608893241Z"
+    }
+   },
    "source": [
     "import requests\n",
     "import os\n",
@@ -36,29 +39,27 @@
     "# 行动格式:\n",
     "你的回答必须严格遵循以下格式。首先是你的思考过程,然后是你要执行的具体行动,每次回复只输出一对Thought-Action:\n",
     "Thought: [这里是你的思考过程和下一步计划]\n",
-    "Action: [这里是你要调用的工具,格式为 function_name(arg_name=\"arg_value\")]\n",
+    "Action: 你决定采取的行动,必须是以下格式之一:\n",
+    "- `function_name(arg_name=\"arg_value\")`:调用一个可用工具。\n",
+    "- `Finish[最终答案]`:当你认为已经获得最终答案时。\n",
+    "- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在Action:字段后使用 Finish[最终答案] 来输出最终答案。\n",
     "\n",
-    "# 任务完成:\n",
-    "当你收集到足够的信息,能够回答用户的最终问题时,你必须在`Action:`字段后使用 `finish(answer=\"...\")` 来输出最终答案。\n",
     "\n",
     "请开始吧!\n",
     "\"\"\""
-   ]
+   ],
+   "outputs": [],
+   "execution_count": 8
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
    "id": "66d9d404-3c95-42f2-8975-436769b3cb87",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "✅ 工具函数定义完成!\n"
-     ]
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2026-01-14T15:56:54.595070634Z",
+     "start_time": "2026-01-14T15:56:54.532054736Z"
     }
-   ],
+   },
    "source": [
     "def get_weather(city: str) -> str:\n",
     "    \"\"\"\n",
@@ -132,22 +133,27 @@
     "    \"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"
+      "✅ 工具函数定义完成!\n"
      ]
     }
    ],
+   "execution_count": 9
+  },
+  {
+   "cell_type": "code",
+   "id": "e953fee4-9e3c-4e34-bf48-4ea002c3bb92",
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2026-01-14T15:56:55.726641969Z",
+     "start_time": "2026-01-14T15:56:55.671146801Z"
+    }
+   },
    "source": [
     "class OpenAICompatibleClient:\n",
     "    \"\"\"\n",
@@ -205,23 +211,29 @@
     "        \"\"\"添加观察结果到历史\"\"\"\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"
+      "✅ 智能助手类定义完成!\n"
      ]
     }
    ],
+   "execution_count": 10
+  },
+  {
+   "cell_type": "code",
+   "id": "ab5d3142-c119-46ad-a7a1-ec1aa2e79435",
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2026-01-14T15:56:56.670907293Z",
+     "start_time": "2026-01-14T15:56:56.608751066Z"
+    }
+   },
    "source": [
+    "\n",
     "def display_conversation(history):\n",
     "    \"\"\"美观地显示对话历史\"\"\"\n",
     "    print(\"\\n\" + \"=\"*60)\n",
@@ -244,8 +256,8 @@
     "\n",
     "def parse_action(action_str):\n",
     "    \"\"\"解析行动字符串\"\"\"\n",
-    "    if action_str.startswith(\"finish\"):\n",
-    "        match = re.search(r'finish\\(answer=\"(.*)\"\\)', action_str)\n",
+    "    if action_str.startswith(\"Finish\"):\n",
+    "        match = re.match(r\"\\w+\\[(.*)\\]\", action_str)\n",
     "        if match:\n",
     "            return \"finish\", {\"answer\": match.group(1)}\n",
     "        return \"finish\", {\"answer\": \"任务完成\"}\n",
@@ -264,14 +276,27 @@
     "    \n",
     "    return tool_name, kwargs\n",
     "print(\"✅ 显示函数定义完成!\")"
-   ]
+   ],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "✅ 显示函数定义完成!\n"
+     ]
+    }
+   ],
+   "execution_count": 11
   },
   {
    "cell_type": "code",
-   "execution_count": null,
    "id": "cc543309-fe16-44a9-9735-bce828b9c7ad",
-   "metadata": {},
-   "outputs": [],
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2026-01-14T15:56:57.497421849Z",
+     "start_time": "2026-01-14T15:56:57.463244826Z"
+    }
+   },
    "source": [
     "def run_assistant(user_input, max_iterations=5, display=True):\n",
     "    \"\"\"\n",
@@ -350,13 +375,41 @@
     "        print(f\"⏰ 达到最大循环次数: {timeout_answer}\")\n",
     "    \n",
     "    return timeout_answer, assistant.prompt_history"
-   ]
+   ],
+   "outputs": [],
+   "execution_count": 12
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
    "id": "3f6e44eb-ff3d-4060-b4c2-ea3e139bf307",
-   "metadata": {},
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2026-01-14T15:57:56.198306041Z",
+     "start_time": "2026-01-14T15:56:58.506429375Z"
+    }
+   },
+   "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()"
+   ],
    "outputs": [
     {
      "name": "stdout",
@@ -370,38 +423,37 @@
       "正在调用大语言模型...\n",
       "大语言模型响应成功。\n",
       "🤖 模型输出:\n",
-      "Thought: 用户希望查询今天北京的天气情况,然后基于该天气推荐一个合适的旅游景点。我的第一步是获取北京的实时天气信息,以便了解当前的天气状况。执行查询天气的操作。\n",
-      "\n",
+      "Thought: 我将先查询今天北京的实时天气,然后根据天气选择合适的景点并给出推荐。\n",
       "Action: get_weather(city=\"北京\")\n",
       "🛠️  调用工具: get_weather({'city': '北京'})\n",
-      "📊 观察结果: 北京当前天气:Clear,气温9摄氏度\n",
+      "📊 观察结果: 北京当前天气:Clear,气温-1摄氏度\n",
       "==================================================\n",
       "\n",
       "🔄 循环 2/5\n",
       "正在调用大语言模型...\n",
       "大语言模型响应成功。\n",
       "🤖 模型输出:\n",
-      "Thought: 我已经获得了北京当前的天气信息:晴天,气温9摄氏度。接下来的步骤是根据这个天气条件推荐一个合适的旅游景点。晴天通常适合户外活动,这将影响我的选择。接下来,我将调用工具获取推荐的旅游景点。 \n",
+      "Thought: 现在北京天气为晴朗且气温-1°C,适合观光但需保暖;接下来根据晴天条件从景点中筛选一个合适的推荐。\n",
       "\n",
       "Action: get_attraction(city=\"北京\", weather=\"Clear\")\n",
       "🛠️  调用工具: get_attraction({'city': '北京', 'weather': 'Clear'})\n",
-      "📊 观察结果: 在晴天,北京的长城(如八达岭)和故宫是最值得去的景点。晴天下,这些地方的景色最美,游览最舒适。\n",
+      "📊 观察结果: In clear weather, Beijing's top attractions include the Forbidden City, the Great Wall at Mutianyu, and the Summer Palace. Plan for at least three days to explore major sites.\n",
       "==================================================\n",
       "\n",
       "🔄 循环 3/5\n",
       "正在调用大语言模型...\n",
       "大语言模型响应成功。\n",
       "🤖 模型输出:\n",
-      "Thought: 我已经获得了关于北京当前天气的信息,并找到了两个适合在晴天游览的旅游景点。长城和故宫都是著名的地标性景点,特别在晴天时更是吸引游客。接下来,我准备输出最终的推荐答案。\n",
+      "Thought: 我将基于当前天气信息,选择一个在 Beijing 今天适合的景点并给出简要理由和出行提示。\n",
       "\n",
-      "Action: finish(answer=\"今天北京的天气晴,气温9摄氏度。推荐您去长城(如八达岭)或故宫游览,这两个景点在这样的天气下非常适合。\")\n",
+      "Action: Finish[今天北京的天气是晴(Clear),气温约-1°C。基于当前天气,推荐的景点是颐和园(Summer Palace)。原因:晴朗但寒冷的日子,颐和园的广阔园林和昆明湖景观非常适合观光,且园区内有多处室外赏景点与室内亭榭可提供避寒休憩点。穿着方面请穿厚外套、带帽子和手套,鞋子建议防滑防水。出行建议:尽量乘坐地铁等公共交通前往,出发前可查看开放时间和路线信息。若更倾向室内参观,故宫等室内空间也同样值得一看。]\n",
       "🎉 任务完成!\n",
-      "📋 最终答案: 今天北京的天气晴,气温9摄氏度。推荐您去长城(如八达岭)或故宫游览,这两个景点在这样的天气下非常适合。\n",
+      "📋 最终答案: 今天北京的天气是晴(Clear),气温约-1°C。基于当前天气,推荐的景点是颐和园(Summer Palace)。原因:晴朗但寒冷的日子,颐和园的广阔园林和昆明湖景观非常适合观光,且园区内有多处室外赏景点与室内亭榭可提供避寒休憩点。穿着方面请穿厚外套、带帽子和手套,鞋子建议防滑防水。出行建议:尽量乘坐地铁等公共交通前往,出发前可查看开放时间和路线信息。若更倾向室内参观,故宫等室内空间也同样值得一看。\n",
       "\n",
       "============================================================\n",
       "📊 测试完成!\n",
       "============================================================\n",
-      "最终答案: 今天北京的天气晴,气温9摄氏度。推荐您去长城(如八达岭)或故宫游览,这两个景点在这样的天气下非常适合。\n",
+      "最终答案: 今天北京的天气是晴(Clear),气温约-1°C。基于当前天气,推荐的景点是颐和园(Summer Palace)。原因:晴朗但寒冷的日子,颐和园的广阔园林和昆明湖景观非常适合观光,且园区内有多处室外赏景点与室内亭榭可提供避寒休憩点。穿着方面请穿厚外套、带帽子和手套,鞋子建议防滑防水。出行建议:尽量乘坐地铁等公共交通前往,出发前可查看开放时间和路线信息。若更倾向室内参观,故宫等室内空间也同样值得一看。\n",
       "\n",
       "============================================================\n",
       "📝 对话历史\n",
@@ -409,53 +461,34 @@
       "\n",
       "👤 用户 [1]:  你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。\n",
       "\n",
-      "🤔 思考 [2]: 用户希望查询今天北京的天气情况,然后基于该天气推荐一个合适的旅游景点。我的第一步是获取北京的实时天气信息,以便了解当前的天气状况。执行查询天气的操作。\n",
-      "\n",
+      "🤔 思考 [2]: 我将先查询今天北京的实时天气,然后根据天气选择合适的景点并给出推荐。\n",
       "Action: get_weather(city=\"北京\")\n",
-      "📊 观察 [3]: 北京当前天气:Clear,气温9摄氏度\n",
+      "📊 观察 [3]: 北京当前天气:Clear,气温-1摄氏度\n",
       "\n",
-      "🤔 思考 [4]: 我已经获得了北京当前的天气信息:晴天,气温9摄氏度。接下来的步骤是根据这个天气条件推荐一个合适的旅游景点。晴天通常适合户外活动,这将影响我的选择。接下来,我将调用工具获取推荐的旅游景点。 \n",
+      "🤔 思考 [4]: 现在北京天气为晴朗且气温-1°C,适合观光但需保暖;接下来根据晴天条件从景点中筛选一个合适的推荐。\n",
       "\n",
       "Action: get_attraction(city=\"北京\", weather=\"Clear\")\n",
-      "📊 观察 [5]: 在晴天,北京的长城(如八达岭)和故宫是最值得去的景点。晴天下,这些地方的景色最美,游览最舒适。\n",
+      "📊 观察 [5]: In clear weather, Beijing's top attractions include the Forbidden City, the Great Wall at Mutianyu, and the Summer Palace. Plan for at least three days to explore major sites.\n",
       "\n",
-      "🤔 思考 [6]: 我已经获得了关于北京当前天气的信息,并找到了两个适合在晴天游览的旅游景点。长城和故宫都是著名的地标性景点,特别在晴天时更是吸引游客。接下来,我准备输出最终的推荐答案。\n",
+      "🤔 思考 [6]: 我将基于当前天气信息,选择一个在 Beijing 今天适合的景点并给出简要理由和出行提示。\n",
       "\n",
-      "Action: finish(answer=\"今天北京的天气晴,气温9摄氏度。推荐您去长城(如八达岭)或故宫游览,这两个景点在这样的天气下非常适合。\")\n",
+      "Action: Finish[今天北京的天气是晴(Clear),气温约-1°C。基于当前天气,推荐的景点是颐和园(Summer Palace)。原因:晴朗但寒冷的日子,颐和园的广阔园林和昆明湖景观非常适合观光,且园区内有多处室外赏景点与室内亭榭可提供避寒休憩点。穿着方面请穿厚外套、带帽子和手套,鞋子建议防滑防水。出行建议:尽量乘坐地铁等公共交通前往,出发前可查看开放时间和路线信息。若更倾向室内参观,故宫等室内空间也同样值得一看。]\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()"
-   ]
+   "execution_count": 13
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
    "id": "68c735c1-eb3e-40e7-8b70-2be941798187",
-   "metadata": {},
-   "outputs": [],
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2026-01-14T15:58:30.343440202Z",
+     "start_time": "2026-01-14T15:58:30.317379757Z"
+    }
+   },
    "source": [
     "def interactive_travel_assistant():\n",
     "    \"\"\"\n",
@@ -501,13 +534,41 @@
     "    print(f\"🚀 快速测试: {user_input}\")\n",
     "    final_answer, _ = run_assistant(user_input, display=True)\n",
     "    return final_answer"
-   ]
+   ],
+   "outputs": [],
+   "execution_count": 14
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
    "id": "bc58c911-8502-4cf5-aa3f-a9f57a94b679",
-   "metadata": {},
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2026-01-14T16:02:32.575540116Z",
+     "start_time": "2026-01-14T16:00:39.668510589Z"
+    }
+   },
+   "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()"
+   ],
    "outputs": [
     {
      "name": "stdout",
@@ -516,78 +577,53 @@
       "选择运行模式:\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",
+      "3. 快速测试其他城市\n",
+      "🚀 快速测试: 请帮我查询广州的天气,并推荐适合的旅游景点\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",
+      "Thought: Plan to fetch Guangzhou的天气信息作为第一步,然后根据天气来筛选推荐的景点。  \n",
+      "Action: get_weather(city=\"广州\")\n",
+      "🛠️  调用工具: get_weather({'city': '广州'})\n",
+      "📊 观察结果: 广州当前天气:Clear,气温15摄氏度\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",
+      "Thought: Guangzhou当前天气为Clear,适合户外活动。我将基于晴天的条件获取推荐的景点列表。  \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",
-      "Action: finish(answer=\"伦敦当前天气为部分多云,气温16摄氏度。根据天气情况,推荐您去伦敦眼欣赏城市景观,此外博物馆和画廊也是很好的选择。\")\n",
+      "Thought: 计划基于广州晴天条件提供景点推荐,先查询符合晴天的景点。\n",
+      "Action: get_attraction(city=\"广州\", weather=\"Clear\")\n",
+      "🛠️  调用工具: get_attraction({'city': '广州', 'weather': 'Clear'})\n",
+      "📊 观察结果: 在广州天气晴朗时,最值得去的旅游景点是越秀公园和广州塔。这些地方风景优美,适合观光和休闲。\n",
+      "==================================================\n",
+      "\n",
+      "🔄 循环 4/5\n",
+      "正在调用大语言模型...\n",
+      "大语言模型响应成功。\n",
+      "🤖 模型输出:\n",
+      "Thought: 我不能提供内部推理过程,但会直接给出结果。  \n",
+      "Action: Finish[广州天气:晴朗,气温15°C。推荐景点:越秀公园、广州塔。]\n",
       "🎉 任务完成!\n",
-      "📋 最终答案: 伦敦当前天气为部分多云,气温16摄氏度。根据天气情况,推荐您去伦敦眼欣赏城市景观,此外博物馆和画廊也是很好的选择。\n"
+      "📋 最终答案: 广州天气:晴朗,气温15°C。推荐景点:越秀公园、广州塔。\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()"
-   ]
+   "execution_count": 17
   },
   {
    "cell_type": "code",

+ 6 - 6
code/chapter1/FirstAgentTest.py

@@ -8,10 +8,10 @@ AGENT_SYSTEM_PROMPT = """
 # 行动格式:
 你的回答必须严格遵循以下格式。首先是你的思考过程,然后是你要执行的具体行动,每次回复只输出一对Thought-Action:
 Thought: [这里是你的思考过程和下一步计划]
-Action: [这里是你要调用的工具,格式为 function_name(arg_name="arg_value")]
-
-# 任务完成:
-当你收集到足够的信息,能够回答用户的最终问题时,你必须在`Action:`字段后使用 `finish(answer="...")` 来输出最终答案。
+Action: 你决定采取的行动,必须是以下格式之一:
+- `function_name(arg_name="arg_value")`:调用一个可用工具。
+- `Finish[最终答案]`:当你认为已经获得最终答案时。
+- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在Action:字段后使用 Finish[最终答案] 来输出最终答案。
 
 请开始吧!
 """
@@ -178,8 +178,8 @@ for i in range(5): # 设置最大循环次数
         break
     action_str = action_match.group(1).strip()
 
-    if action_str.startswith("finish"):
-        final_answer = re.search(r'finish\(answer="(.*)"\)', action_str).group(1)
+    if action_str.startswith("Finish"):
+        final_answer = re.match(r"Finish\[(.*)\]", action_str).group(1)
         print(f"任务完成,最终答案: {final_answer}")
         break
     

+ 2 - 1
code/chapter4/ReAct.py

@@ -15,7 +15,7 @@ Thought: 你的思考过程,用于分析问题、拆解任务和规划下一
 Action: 你决定采取的行动,必须是以下格式之一:
 - `{{tool_name}}[{{tool_input}}]`:调用一个可用工具。
 - `Finish[最终答案]`:当你认为已经获得最终答案时。
-- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在`Action:`字段后使用 `finish(answer="...")` 来输出最终答案。
+- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在`Action:`字段后使用 `Finish[最终答案]` 来输出最终答案。
 
 
 现在,请开始解决以下问题:
@@ -52,6 +52,7 @@ class ReActAgent:
             if not action: print("警告:未能解析出有效的Action,流程终止。"); break
             
             if action.startswith("Finish"):
+                # 如果是Finish指令,提取最终答案并结束
                 final_answer = self._parse_action_input(action)
                 print(f"🎉 最终答案: {final_answer}")
                 return final_answer

+ 7 - 7
docs/chapter1/Chapter1-Introduction-to-Agents.md

@@ -240,10 +240,10 @@ You are an intelligent travel assistant. Your task is to analyze user requests a
 # Action Format:
 Your response must strictly follow the following format. First is your thinking process, then the specific action you want to execute. Each response should output only one Thought-Action pair:
 Thought: [Here is your thinking process and next step plan]
-Action: [Here is the tool you want to call, in the format function_name(arg_name="arg_value")]
-
-# Task Completion:
-When you have collected enough information to answer the user's final question, you must use `finish(answer="...")` after the Action: field to output the final answer.
+Action: The action you decide to take, which must be in one of the following formats:
+- function_name(arg_name="arg_value"): Call an available tool.
+- Finish[final answer]: When you believe you have obtained the final answer.
+- When you have collected enough information to answer the user's final question, you must use `Finish[final answer]` after the Action: field to output the final answer.
 
 Let's begin!
 """
@@ -435,8 +435,8 @@ for i in range(5): # Set maximum number of loops
         break
     action_str = action_match.group(1).strip()
 
-    if action_str.startswith("finish"):
-        final_answer = re.search(r'finish\(answer="(.*)"\)', action_str).group(1)
+    if action_str.startswith("Finish"):
+        final_answer = re.match(r"Finish\[(.*)\]", action_str).group(1)
         print(f"Task completed, final answer: {final_answer}")
         break
 
@@ -490,7 +490,7 @@ Calling large language model...
 Large language model responded successfully.
 Model output:
 Thought: I have obtained two attraction suggestions suitable for sunny days, now I can provide a satisfactory response to the user based on this information.
-Action: finish(answer="Today's weather in Beijing is sunny with a temperature of 26 degrees Celsius, very suitable for outdoor activities. I recommend you visit the Summer Palace to enjoy the beautiful lake views and ancient architecture, or go to the Great Wall to experience its spectacular scenery and profound historical significance. Hope you have a pleasant trip!")
+Action: Finish[Today's weather in Beijing is sunny with a temperature of 26 degrees Celsius, very suitable for outdoor activities. I recommend you visit the Summer Palace to enjoy the beautiful lake views and ancient architecture, or go to the Great Wall to experience its spectacular scenery and profound historical significance. Hope you have a pleasant trip!]
 
 Task completed, final answer: Today's weather in Beijing is sunny with a temperature of 26 degrees Celsius, very suitable for outdoor activities. I recommend you visit the Summer Palace to enjoy the beautiful lake views and ancient architecture, or go to the Great Wall to experience its spectacular scenery and profound historical significance. Hope you have a pleasant trip!
 ```

+ 7 - 8
docs/chapter1/第一章 初识智能体.md

@@ -244,10 +244,10 @@ AGENT_SYSTEM_PROMPT = """
 # 行动格式:
 你的回答必须严格遵循以下格式。首先是你的思考过程,然后是你要执行的具体行动,每次回复只输出一对Thought-Action:
 Thought: [这里是你的思考过程和下一步计划]
-Action: [这里是你要调用的工具,格式为 function_name(arg_name="arg_value")]
-
-# 任务完成:
-当你收集到足够的信息,能够回答用户的最终问题时,你必须在`Action:`字段后使用 `finish(answer="...")` 来输出最终答案。
+Action: 你决定采取的行动,必须是以下格式之一:
+- `function_name(arg_name="arg_value")`:调用一个可用工具。
+- `Finish[最终答案]`:当你认为已经获得最终答案时。
+- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在Action:字段后使用 Finish[最终答案] 来输出最终答案。
 
 请开始吧!
 """
@@ -440,8 +440,8 @@ for i in range(5): # 设置最大循环次数
         break
     action_str = action_match.group(1).strip()
 
-    if action_str.startswith("finish"):
-        final_answer = re.search(r'finish\(answer="(.*)"\)', action_str).group(1)
+    if action_str.startswith("Finish"):
+        final_answer = re.match(r"Finish\[(.*)\]", action_str).group(1)
         print(f"任务完成,最终答案: {final_answer}")
         break
     
@@ -495,8 +495,7 @@ Observation: 北京在晴天最值得去的旅游景点是颐和园,因其美
 大语言模型响应成功。
 模型输出:
 Thought: 已经获得了两个适合晴天游览的景点建议,现在可以根据这些信息给用户提供满意的答复。
-Action: finish(answer="今天北京的天气是晴朗的,气温26摄氏度,非常适合外出游玩。我推荐您去颐和园欣赏美丽的湖景和古建筑,或者前往长城体验其壮观的景观和深厚的历史意义。希望您有一个愉快的旅行!
-")
+Action: Finish[今天北京的天气是晴朗的,气温26摄氏度,非常适合外出游玩。我推荐您去颐和园欣赏美丽的湖景和古建筑,或者前往长城体验其壮观的景观和深厚的历史意义。希望您有一个愉快的旅行!]
 
 任务完成,最终答案: 今天北京的天气是晴朗的,气温26摄氏度,非常适合外出游玩。我推荐您去颐和园欣赏美丽的湖景和古建筑,或者前往长城体验其壮观的景观和深厚的历史意义。希望您有一个愉快的旅行!
 ```

+ 1 - 1
docs/chapter4/Chapter4-Building-Classic-Agent-Paradigms.md

@@ -366,7 +366,7 @@ Thought: Your thinking process, used to analyze problems, decompose tasks, and p
 Action: The action you decide to take, must be in one of the following formats:
 - {{tool_name}}[{{tool_input}}]`: Call an available tool.
 - `Finish[final answer]`: When you believe you have obtained the final answer.
-- When you have collected enough information to answer the user's final question, you must use `finish(answer="...")` after the Action: field to output the final answer.
+- When you have collected enough information to answer the user's final question, you must use `Finish[final answer]` after the Action: field to output the final answer.
 
 Now, please start solving the following problem:
 Question: {question}

+ 1 - 1
docs/chapter4/第四章 智能体经典范式构建.md

@@ -366,7 +366,7 @@ Thought: 你的思考过程,用于分析问题、拆解任务和规划下一
 Action: 你决定采取的行动,必须是以下格式之一:
 - `{{tool_name}}[{{tool_input}}]`:调用一个可用工具。
 - `Finish[最终答案]`:当你认为已经获得最终答案时。
-- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在Action:字段后使用 finish(answer="...") 来输出最终答案。
+- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在Action:字段后使用 Finish[最终答案] 来输出最终答案。
 
 现在,请开始解决以下问题:
 Question: {question}