Skip to content
On this page

22. 规划器模块:将旅行目标分解为任务

如果说整个智能旅行助手是一个宏大的建筑工程,那么规划器(Planner)就是项目的总设计师。它的核心职责,是将客户(用户)一个天马行空的想法,绘制成一张精确、严谨、所有后续工种都能看懂的建筑蓝图。

在本章中,我们将深入探讨如何设计规划器的提示词,这可能是整个项目中最为关键和最具挑战性的一环。因为,蓝图的质量,直接决定了最终建筑的高度。

规划器的角色:从需求到蓝图的翻译官

  • 定位:首席行程设计师,整个工作流的起点。
  • 输入:一段来自用户的、模糊的自然语言需求。例如:“下个月我想去巴黎和罗马,玩10天,预算2万,对艺术和美食感兴趣。”
  • 核心任务:将这个需求,翻译并结构化成一份详细的旅行规划大纲(TOC - Table of Contents)。
  • 输出:一个严格定义的 JSON 对象。这份 JSON 就是我们后续所有模块(执行器、综合器)赖以生存的“API 契约”。

让我们通过一个鲜明的“输入 vs 输出”对比,来直观感受规划器的价值:

输入 (Input):

text
下个月我想去巴黎和罗马,玩10天,预算2万,对艺术和美食感兴趣。

输出 (Output - 结构化蓝图):

json
{
  "title": "巴黎与罗马艺术美食10日探索之旅",
  "brief": "一份为期10天,预算2万元人民币,专注于艺术与美食的深度旅行计划。",
  "duration_days": 10,
  "budget_cny": 20000,
  "cities": ["巴黎", "罗马"],
  "themes": ["艺术", "美食"],
  "daily_plan": [
    {
      "day": 1,
      "city": "巴黎",
      "theme": "抵达与艺术初探",
      "tasks": [
        {"task_id": "day1-flight-search", "type": "flight", "description": "查询并推荐抵达巴黎戴高乐机场的航班"},
        {"task_id": "day1-hotel-search", "type": "hotel", "description": "在卢浮宫附近寻找艺术主题酒店"},
        {"task_id": "day1-activity-plan", "type": "activity", "description": "规划下午参观卢浮宫的行程"},
        {"task_id": "day1-dinner-plan", "type": "restaurant", "description": "推荐一家经典的法式餐厅"}
      ]
    },
    {
      "day": 2,
      "city": "巴黎",
      "theme": "蒙马特高地与现代艺术",
      "tasks": [
        // ... 其他天的任务
      ]
    }
    // ... 直到 day 10
  ]
}

看到了吗?规划器将一段话,变成了一个结构清晰、信息完整、机器可读的 JSON 对象。这,就是提示词工程的力量。

规划器提示词的完整解构

要让 LLM 稳定地输出我们期望的 JSON 格式,核心在于“引导”而非“命令”。下面,我们将通过 P.I.C.A. 模型,完整解构这个规划器的提示词。

你是一位世界顶级的旅行规划师和信息架构师。
你的任务是根据用户提供的模糊需求,创建一个逻辑严谨、内容丰富、结构化的旅行计划蓝图。

请严格遵循以下步骤:

1.  **深度分析 (Analyze)**:提取用户需求中的关键信息,包括目的地、时长、预算、兴趣主题等。如果信息不足,请根据常识进行合理补充。
2.  **行程构建 (Structure)**:将整个旅行分解到每一天,为每一天设定一个主题,并规划出当天需要执行的核心任务(Tasks),例如查询航班、寻找酒店、规划景点、推荐餐厅等。
3.  **任务定义 (Define)**:为每一个任务(Task)分配一个唯一的 `task_id` 和明确的 `type`(例如:'flight', 'hotel', 'activity', 'restaurant', 'transport')。

请将你的思考过程放在 `<thinking>` 标签内,这有助于你梳理思路,并让我了解你的决策过程。
最终,请将生成的旅行计划蓝图以一个完整的 JSON 对象形式,放在 `<json>` 标签内。

**约束条件 (Constraints):**

-   最终输出必须是一个可以被解析的、完整的 JSON 对象。
-   JSON 对象的根结构必须包含 `title`, `brief`, `duration_days`, `budget_cny`, `cities`, `themes`, `daily_plan` 字段。
-   `daily_plan` 是一个数组,其中每个元素代表一天,必须包含 `day`, `city`, `theme`, `tasks` 字段。
-   `tasks` 是一个数组,其中每个元素代表一个任务,必须包含 `task_id`, `type`, `description` 字段。

**用户需求如下:**

---
{{USER_REQUEST}}
---

提示词设计解析

  1. Persona (角色): “世界顶级的旅行规划师和信息架构师”。我们赋予它双重身份,既懂旅行的浪漫,又懂数据的严谨。

  2. Instruction (指令): 这是提示词的核心。我们没有简单地说“给我一个计划”,而是:

    • 分解步骤 (Step-by-Step):明确要求模型遵循“分析 -> 构建 -> 定义”三步走。这极大地稳定了模型的思考路径,避免它天马行空。
    • 输出隔离 (Output Isolation):我们创造性地使用了 <thinking><json> 这两个 XML 标签。这是一种强大的技术,它强制模型将思考过程和最终结果分离开。这样做的好处是:
      • 我们可以观察模型的思考过程,便于调试和优化提示词。
      • 我们的代码可以轻松地、确定性地只提取 <json> 标签内的内容,而不用担心被模型的其他“噪音”(如“好的,这是您要的JSON...”)所污染。
  3. Context (情境): 部分,这里会填入用户最原始的输入。

  4. Action (输出规范): 整个提示词的结构,特别是最后的 JSON 结构定义和标签要求,共同构成了清晰的输出规范,引导模型生成我们期望的结构化输出。

输出即契约:JSON 作为模块间的通信语言

规划器输出的这份 JSON,并不仅仅是一份大纲,它更是规划器与下游“执行器”(Executor)模块之间神圣的“API 契约”。

在下一章,执行器会读取这份 JSON,遍历 daily_plan 中的每一个 task,并根据其 typedescription 去调用相应的工具(如航班查询 API、酒店搜索工具等)。

这种“接口先行”的设计思想,是复杂 AI 系统工程化的基石。它确保了多智能体系统可以像乐高积木一样,被清晰地拆分和组合,每个模块只需关心自己的输入和输出是否符合“契约”规定即可。

如果规划器输出的 JSON 格式不稳定,整个流水线就会崩溃。因此,一个健壮的规划器提示词,会包含详细的错误处理和重试机制,例如,如果解析 JSON 失败,就带着错误信息让模型重新生成一次。

现在,我们已经为整个项目设计好了蓝图。接下来,让我们进入下一章,看看“执行器”这位“全能信息搜集员”是如何根据这份蓝图,为我们获取真实世界的数据的。

has loaded