第6章:规划与任务分解

面对"帮我策划一场生日派对"这样的复杂任务,优秀的智能体不会一头扎进去盲目执行,而是先思考:"这个任务需要哪些步骤?"这就是规划(Planning)能力。本章将教你如何让智能体像项目经理一样有条不紊地完成任务。

6.1 什么是规划(Planning)

规划就是把大任务拆成小步骤,然后逐个完成的过程。

规划的三个关键问题:
  • 要做什么 - 明确最终目标
  • 怎么做 - 分解成可执行的步骤
  • 何时做 - 确定步骤的执行顺序
规划 vs 无规划:

❌ 无规划(盲目执行):
用户: 帮我策划一场生日派对
AI: 好的!我推荐你去XXX餐厅...
      (没有了解预算、人数、时间等关键信息)

✅ 有规划(系统思考):
用户: 帮我策划一场生日派对
AI: 好的!让我先规划一下这个任务:
      
      步骤1:了解基本信息(预算、人数、时间)
      步骤2:确定派对主题和风格
      步骤3:选择场地
      步骤4:安排餐饮
      步骤5:准备娱乐活动
      步骤6:发送邀请
      
      让我们从步骤1开始:请问您的预算是多少?
          

6.2 为什么需要规划

规划的好处:
  • 降低复杂度 - 把大问题变成小问题,逐个击破
  • 减少错误 - 每一步都经过思考,避免遗漏关键信息
  • 提高成功率 - 有计划的执行更有可能达成目标
  • 便于调试 - 出问题能快速定位到具体步骤
  • 支持回溯 - 某步失败可以重新规划该步骤
⚠️ 没有规划的常见问题:
  • 遗漏关键步骤(忘记确认预算就推荐场地)
  • 步骤顺序混乱(先发了邀请还没定时间地点)
  • 重复劳动(多次询问同样的问题)
  • 陷入死胡同(执行到一半发现前提条件不满足)

6.3 任务分解策略

任务分解有多种方法,我们介绍三种最常用的策略。

6.3.1 目标分解

把最终目标拆成若干子目标,每个子目标相对独立。

目标分解示例:写一份市场调研报告

                    写市场调研报告
                          │
        ┌─────────────────┼─────────────────┐
        │                 │                 │
        ▼                 ▼                 ▼
   ┌─────────┐      ┌─────────┐      ┌─────────┐
   │收集资料 │      │分析数据 │      │撰写报告 │
   └────┬────┘      └────┬────┘      └────┬────┘
        │                 │                 │
   ┌────┴────┐      ┌────┴────┐      ┌────┴────┐
   │•搜索行业│      │•数据清洗│      │•撰写摘要│
   │ 新闻    │      │•统计分析│      │•正文内容│
   │•查找报告│      │•制作图表│      │•结论建议│
   │•采访专家│      │         │      │         │
   └─────────┘      └─────────┘      └─────────┘
          

6.3.2 步骤分解

把子目标进一步拆成具体可执行的动作。

步骤分解示例:预订餐厅

子目标:选择并预订合适的餐厅

步骤1:询问需求
   ├─ 1.1 确认用餐日期和时间
   ├─ 1.2 确认用餐人数
   ├─ 1.3 确认预算范围
   └─ 1.4 确认 cuisine 偏好

步骤2:搜索餐厅
   ├─ 2.1 调用餐厅搜索API
   ├─ 2.2 根据条件筛选
   └─ 2.3 获取餐厅详情(评分、菜单、位置)

步骤3:推荐选择
   ├─ 3.1 排序候选餐厅
   ├─ 3.2 展示Top 3选项
   └─ 3.3 解释推荐理由

步骤4:完成预订
   ├─ 4.1 确认用户选择
   ├─ 4.2 调用预订API
   └─ 4.3 发送确认信息
          

6.3.3 层次分解

用树状结构组织任务,从抽象到具体逐层细化。

层次分解:电商订单处理系统

                        ┌─────────────┐
                        │  处理订单    │  ← 第一层:总任务
                        └──────┬──────┘
                               │
           ┌───────────────────┼───────────────────┐
           │                   │                   │
           ▼                   ▼                   ▼
      ┌─────────┐        ┌─────────┐        ┌─────────┐
      │验证订单 │        │处理库存 │        │安排物流 │  ← 第二层:子任务
      └────┬────┘        └────┬────┘        └────┬────┘
           │                   │                   │
      ┌────┴────┐        ┌────┴────┐        ┌────┴────┐
      │检查用户 │        │查询库存 │        │选择快递 │
      │  信息   │        │  数量   │        │  公司   │  ← 第三层:具体步骤
      │验证支付 │        │锁定库存 │        │生成运单 │
      │  状态   │        │更新库存 │        │通知发货 │
      └─────────┘        └─────────┘        └─────────┘
          

6.4 规划的方法

如何让AI进行有效的规划?介绍三种主流方法。

6.4.1 Chain of Thought(思维链)

让AI一步步思考,把思考过程显式地写出来。

Chain of Thought 示例:

问题:用户想要一本关于Python编程的书,预算200元以内。

AI的思考过程:
1. 用户需要什么类型的书?
   → Python编程书
   
2. 有什么限制条件?
   → 预算200元以内
   
3. 我需要做什么?
   → a. 搜索Python编程书籍
   → b. 筛选价格≤200元的
   → c. 按评分排序
   → d. 推荐Top 3
   
4. 第一步做什么?
   → 调用图书搜索API,关键词"Python编程"

执行动作:[调用搜索API...]
          

6.4.2 Tree of Thoughts(思维树)

探索多种可能路径,选择最优方案。

Tree of Thoughts 示例:规划旅行路线

                          从北京到上海
                               │
          ┌────────────────────┼────────────────────┐
          │                    │                    │
          ▼                    ▼                    ▼
     ┌─────────┐         ┌─────────┐         ┌─────────┐
     │方案A:  │         │方案B:  │         │方案C:  │
     │  高铁   │         │  飞机   │         │  自驾   │
     │ 4.5小时 │         │ 2.5小时 │         │ 12小时  │
     │ ¥553    │         │ ¥800    │         │ ¥600    │
     └────┬────┘         └────┬────┘         └────┬────┘
          │                    │                    │
          ▼                    ▼                    ▼
     评价:性价比         评价:最快            评价:自由度高
     高,推荐!           但较贵                但耗时太长
     
AI决策:选择方案A(高铁),向用户推荐。
          

6.4.3 反思与重规划

执行中遇到问题时,重新评估并调整计划

反思与重规划示例:

原 plan:
1. 询问用户预算 ✓
2. 询问用户时间 ✓
3. 搜索餐厅 → 执行中...

执行步骤3时发现问题:
❌ 用户所在区域没有符合预算的餐厅

反思:
- 为什么失败?预算限制太严格
- 有什么替代方案?
  a) 扩大搜索范围到邻近区域
  b) 建议用户稍微提高预算
  c) 推荐其他类型的餐饮

重规划:
3a. 向用户说明情况
3b. 询问是否接受邻近区域或调整预算
3c. 根据用户选择重新搜索

新 plan 继续执行...
          

6.5 规划的表示

如何存储和展示规划?常见的表示方式有:

6.5.1 列表表示

// JSON格式表示规划

{
  "task": "策划生日派对",
  "steps": [
    {
      "id": 1,
      "name": "确定预算",
      "status": "completed",
      "dependencies": [],
      "result": "预算2000元"
    },
    {
      "id": 2,
      "name": "选择场地",
      "status": "in_progress",
      "dependencies": [1],
      "action": "search_venues",
      "parameters": { "budget": 2000 }
    },
    {
      "id": 3,
      "name": "准备餐饮",
      "status": "pending",
      "dependencies": [2],
      "action": "arrange_catering"
    },
    {
      "id": 4,
      "name": "发送邀请",
      "status": "pending",
      "dependencies": [2, 3],
      "action": "send_invitations"
    }
  ]
}
          

6.5.2 流程图表示

用户咨询 → 理解意图 → 需要规划?
                        │
              ┌─────────┴─────────┐
              │                   │
             是                   否
              │                   │
              ▼                   ▼
        分解任务              直接回答
              │
              ▼
        检查依赖关系
              │
              ▼
        确定执行顺序 ──→ 生成执行计划
              │
              ▼
        执行步骤 ←────── 完成?──┐
              │               │
              └───────────────┘
              │
              ▼
        反思结果 ──→ 需要重规划?──┐
              │                 │
              否                是
              │                 │
              ▼                 └──────────┐
        完成任务 ←─────────────────────────┘
          

6.6 执行与调整

规划只是第一步,更重要的是执行并根据实际情况调整

规划执行循环:

        ┌─────────────────────────────────────┐
        │                                     │
        ▼                                     │
   ┌─────────┐    ┌─────────┐    ┌─────────┐ │
   │  规划   │───→│  执行   │───→│  观察   │ │
   │  Planning│    │ Execute │    │ Observe │ │
   └─────────┘    └─────────┘    └────┬────┘ │
        ▲                              │      │
        │                              ▼      │
        │                         ┌─────────┐ │
        └─────────────────────────│  反思   │─┘
                                  │Reflect  │
                                  └─────────┘

这个循环叫做"观察-思考-行动"循环(Observe-Reflect-Act Loop)
          

6.6.1 代码实现示例

class TaskPlanner {
  constructor() {
    this.plan = null;
    this.currentStep = 0;
    this.results = {};
  }

  // 生成规划
  async createPlan(goal, context) {
    const prompt = `
      目标:${goal}
      上下文:${JSON.stringify(context)}
      
      请将这个目标分解成具体的执行步骤。
      每个步骤包含:步骤名、需要执行的动作、依赖的前置步骤。
      以JSON格式返回。
    `;
    
    this.plan = await callAI(prompt);
    this.currentStep = 0;
    return this.plan;
  }

  // 执行下一步
  async executeNextStep() {
    if (this.currentStep >= this.plan.steps.length) {
      return { done: true, message: "所有步骤已完成" };
    }

    const step = this.plan.steps[this.currentStep];
    
    // 检查依赖是否满足
    const dependenciesMet = step.dependencies.every(
      dep => this.results[dep]
    );
    
    if (!dependenciesMet) {
      return { error: "前置步骤未完成" };
    }

    try {
      // 执行步骤
      const result = await this.executeAction(step.action, step.parameters);
      
      // 保存结果
      this.results[step.id] = result;
      step.status = "completed";
      this.currentStep++;
      
      return { step: step.name, result };
      
    } catch (error) {
      step.status = "failed";
      step.error = error.message;
      
      // 触发重规划
      return await this.replan(step, error);
    }
  }

  // 重规划
  async replan(failedStep, error) {
    const prompt = `
      步骤"${failedStep.name}"执行失败:${error.message}
      
      当前计划:${JSON.stringify(this.plan)}
      已执行结果:${JSON.stringify(this.results)}
      
      请重新规划,提供替代方案。
    `;
    
    this.plan = await callAI(prompt);
    return { replanned: true, newPlan: this.plan };
  }
}
          

6.7 完整示例:策划生日派对

让我们实现一个能规划生日派对的智能体。

6.7.1 规划结构

目标:策划生日派对

分解树:

                    策划生日派对
                          │
        ┌─────────────────┼─────────────────┐
        │                 │                 │
        ▼                 ▼                 ▼
   ┌─────────┐      ┌─────────┐      ┌─────────┐
   │  预算   │      │  场地   │      │  餐饮   │
   └────┬────┘      └────┬────┘      └────┬────┘
        │                 │                 │
   ┌────┴────┐      ┌────┴────┐      ┌────┴────┐
   │询问预算 │      │确定人数 │      │计算数量 │
   │         │      │         │      │         │
   │记录预算 │      │搜索场地 │      │选择餐品 │
   │         │      │         │      │         │
   └─────────┘      │对比选择 │      │下单预订 │
                    │         │      │         │
                    │确认预订 │      └─────────┘
                    └─────────┘
                           │
        ┌──────────────────┼──────────────────┐
        │                  │                  │
        ▼                  ▼                  ▼
   ┌─────────┐       ┌─────────┐       ┌─────────┐
   │  装饰   │       │  活动   │       │  邀请   │
   └────┬────┘       └────┬────┘       └────┬────┘
        │                 │                 │
   ┌────┴────┐       ┌────┴────┐       ┌────┴────┐
   │确定主题 │       │设计游戏 │       │列出名单 │
   │         │       │         │       │         │
   │采购装饰 │       │准备道具 │       │制作邀请 │
   │         │       │         │       │         │
   └─────────┘       │安排流程 │       │发送邀请 │
                     │         │       │         │
                     └─────────┘       └─────────┘
          

6.7.2 完整代码

class PartyPlanner {
  constructor() {
    this.context = {
      budget: null,
      guestCount: null,
      date: null,
      preferences: {}
    };
    this.tasks = [
      { id: 'budget', name: '确定预算', done: false, fn: this.askBudget },
      { id: 'guests', name: '确认人数', done: false, fn: this.askGuestCount },
      { id: 'date', name: '选择日期', done: false, fn: this.askDate },
      { id: 'venue', name: '预订场地', done: false, fn: this.searchVenue },
      { id: 'catering', name: '安排餐饮', done: false, fn: this.arrangeCatering },
      { id: 'invite', name: '发送邀请', done: false, fn: this.sendInvites }
    ];
    this.currentTaskIndex = 0;
  }

  // 主循环
  async chat(userMessage) {
    // 更新上下文
    this.updateContext(userMessage);
    
    // 找到下一个未完成的任务
    const currentTask = this.tasks[this.currentTaskIndex];
    
    if (!currentTask) {
      return "🎉 生日派对策划完成!祝您派对愉快!";
    }

    // 执行任务
    const response = await currentTask.fn.call(this, userMessage);
    
    // 标记完成并前进
    if (this.isTaskComplete(currentTask, userMessage)) {
      currentTask.done = true;
      this.currentTaskIndex++;
      
      // 告诉用户下一步
      const nextTask = this.tasks[this.currentTaskIndex];
      if (nextTask) {
        response += `\n\n📋 接下来:${nextTask.name}`;
      }
    }

    return response;
  }

  // 显示当前进度
  getProgress() {
    const completed = this.tasks.filter(t => t.done).length;
    const total = this.tasks.length;
    const percent = Math.round(completed / total * 100);
    
    let progress = `📊 当前进度:${percent}%\n`;
    progress += `┌${'─'.repeat(20)}┐\n`;
    progress += `│${'█'.repeat(completed * 20 / total)}${' '.repeat(20 - completed * 20 / total)}│\n`;
    progress += `└${'─'.repeat(20)}┘\n`;
    
    this.tasks.forEach((task, i) => {
      const icon = task.done ? '✅' : (i === this.currentTaskIndex ? '⏳' : '⬜');
      progress += `${icon} ${task.name}\n`;
    });
    
    return progress;
  }

  // 各个任务执行函数
  async askBudget(message) {
    if (!this.context.budget) {
      return "🎂 让我们开始策划生日派对吧!\n\n首先,请问您的预算是多少?(比如:2000元)";
    }
    return `好的,预算${this.context.budget}元,我会根据这个预算来推荐。`;
  }

  async askGuestCount(message) {
    if (!this.context.guestCount) {
      return "请问大约有多少位客人参加?";
    }
    return `收到,${this.context.guestCount}位客人。`;
  }

  async askDate(message) {
    if (!this.context.date) {
      return "派对计划在哪一天举办?";
    }
    return `${this.context.date},记住了。`;
  }

  async searchVenue(message) {
    // 模拟场地搜索
    return `🔍 正在为您搜索适合${this.context.guestCount}人、预算内的场地...\n\n推荐场地:\n1. 星光派对馆 - 可容纳30人,费用1500元\n2. 欢乐谷餐厅 - 包间可容纳20人,费用1800元\n\n您倾向哪个?`;
  }

  async arrangeCatering(message) {
    const perPerson = Math.floor(this.context.budget * 0.4 / this.context.guestCount);
    return `🍽️ 餐饮安排:\n按预算40%用于餐饮,人均约${perPerson}元\n推荐套餐:\n- 自助餐形式\n- 包含蛋糕、饮料\n\n需要我帮您联系餐饮供应商吗?`;
  }

  async sendInvites(message) {
    return `📧 邀请函模板已生成:\n\n"亲爱的朋友,\n诚挚邀请您参加我的生日派对!\n时间:${this.context.date}\n地点:[已预订场地]\n期待与您相聚!"\n\n您可以直接复制发送,需要我帮您通过邮件发送吗?`;
  }

  // 辅助方法
  updateContext(message) {
    // 简单提取数字作为预算
    const budgetMatch = message.match(/(\d+)元?/);
    if (budgetMatch && !this.context.budget) {
      this.context.budget = parseInt(budgetMatch[1]);
    }
    
    const countMatch = message.match(/(\d+)人/);
    if (countMatch && !this.context.guestCount) {
      this.context.guestCount = parseInt(countMatch[1]);
    }
  }

  isTaskComplete(task, message) {
    // 简单判断:如果关键信息已获取,认为任务完成
    if (task.id === 'budget') return this.context.budget !== null;
    if (task.id === 'guests') return this.context.guestCount !== null;
    if (task.id === 'date') return this.context.date !== null;
    return message.includes('好') || message.includes('可以') || message.includes('确定');
  }
}
          

6.7.3 对话演示

实际对话效果:

用户: 帮我策划一场生日派对

AI: 🎂 让我们开始策划生日派对吧!
    
    📋 整体规划:
    1️⃣ 确定预算
    2️⃣ 确认人数  
    3️⃣ 选择日期
    4️⃣ 预订场地
    5️⃣ 安排餐饮
    6️⃣ 发送邀请
    
    首先,请问您的预算是多少?

─────────────────────────────────

用户: 大概3000元

AI: 好的,预算3000元,我会根据这个预算来推荐。
    
    📋 接下来:确认人数
    请问大约有多少位客人参加?

─────────────────────────────────

用户: 15个人

AI: 收到,15位客人。
    
    📋 接下来:选择日期
    派对计划在哪一天举办?

─────────────────────────────────

[继续执行后续步骤...]
          

6.8 常见规划模式

常用的任务执行模式:
1. 顺序执行(Sequential)
   
   步骤1 → 步骤2 → 步骤3 → 步骤4
   
   适用场景:有明确依赖关系的任务
   示例:写报告(先收集资料 → 再分析 → 最后撰写)


2. 并行执行(Parallel)
   
        ┌→ 步骤2a ─┐
   步骤1 ┼→ 步骤2b ─┼→ 步骤3
        └→ 步骤2c ─┘
   
   适用场景:子任务相互独立,可同时执行
   示例:数据分析(同时查询多个数据源)


3. 条件分支(Conditional)
   
         条件判断
         /      \
       是        否
       /          \
   分支A          分支B
      \            /
       └→ 汇合 ←─┘
   
   适用场景:根据中间结果选择不同路径
   示例:客服(根据问题类型转接不同部门)


4. 循环迭代(Iterative)
   
   ┌─────────────────┐
   │                 │
   ▼                 │
   步骤 → 检查条件 ──┤
           ↓ 不满足  │
         满足        │
           ↓         │
         退出 ←──────┘
   
   适用场景:需要反复优化的任务
   示例:代码审查(修改 → 检查 → 再修改)
          

本章小结

核心知识点回顾:
  • 规划 - 把大任务拆成小步骤,逐个完成
  • 任务分解 - 目标分解、步骤分解、层次分解三种策略
  • 规划方法 - Chain of Thought(一步步思考)、Tree of Thoughts(多路径探索)、反思重规划
  • 规划表示 - 列表、树状图、流程图等多种形式
  • 执行与调整 - 观察-思考-行动循环,根据实际情况动态调整
  • 执行模式 - 顺序、并行、条件分支、循环迭代

至此,你已经掌握了智能体开发的核心技能:记忆管理让智能体能记住用户,规划能力让智能体有条不紊地完成复杂任务。继续学习,你将能构建出真正强大的AI智能体!