|
|
@@ -0,0 +1,616 @@
|
|
|
+{
|
|
|
+ "cells": [
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 1,
|
|
|
+ "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",
|
|
|
+ "你的回答必须严格遵循以下格式。首先是你的思考过程,然后是你要执行的具体行动。\n",
|
|
|
+ "Thought: [这里是你的思考过程和下一步计划]\n",
|
|
|
+ "Action: [这里是你要调用的工具,格式为 function_name(arg_name=\"arg_value\")]\n",
|
|
|
+ "\n",
|
|
|
+ "# 任务完成:\n",
|
|
|
+ "当你收集到足够的信息,能够回答用户的最终问题时,你必须使用 `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": 5,
|
|
|
+ "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",
|
|
|
+ " \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
|
|
|
+}
|