【仓颉 + 鸿蒙 + AI Agent】CangjieMagic框架(17):PlanReactExecutor

CangjieMagic框架:使用华为仓颉编程语言编写,专门用于开发AI Agent,支持鸿蒙、Windows、macOS、Linux等系统。

这篇文章剖析一下 CangjieMagic 框架中的 PlanReactExecutor。

1 PlanReactExecutor的工作原理

用户提问 PlanReactExecutor 知识提取 问题分解 生成多个子任务 执行子任务 汇总结果 返回最终答案

当你要组织一场生日派对时,你会怎么做?你不会一头扎进去就开始准备,而是会先:

  1. 了解寿星的喜好(知识提取)
  2. 分解任务:场地、食物、娱乐、礼物(问题分解)
  3. 一个个完成这些子任务(执行子任务)
  4. 最后把所有准备工作整合起来,举办一场成功的派对(汇总结果)

PlanReactExecutor就是这样工作的!它不会直接尝试解决一个复杂问题,而是先分析、分解,然后一步步解决,最后整合答案。

2 深入代码:构造函数和核心组件

我们先来看看PlanReactExecutor的构造函数:

cangjie 复制代码
protected class PlanReactExecutor <: AgentExecutor {
    protected PlanReactExecutor() { }
    
    // 其他成员...
}

这个构造函数非常简单,它背后连接了几个强大的组件:
PlanReactExecutor 知识提取器 问题分解器 ReactWorker 结果汇总器

就像一个专业厨师虽然看起来很简单地做了一道菜,但背后有一套完整的厨具和步骤一样,PlanReactExecutor看似简单,实则整合了多个专业组件。

3 同步执行流程:像项目经理一样工作

现在,让我们看看同步执行函数的实现:

cangjie 复制代码
override public func run(agent: Agent, request: AgentRequest): AgentResponse {
    // Extract necessary knowledge
    let knowledge = knowledgeExtract(agent, request)
    // Decompose the problem
    let subtasks: Array<Subtask> = problemDecompose(agent, request)
    let planTask = PlanTask(agent, request, subtasks, knowledge)
    // Solve each subtask
    for (subtask in subtasks) {
        let worker = ReactWorker(planTask)
        let result = worker.solve(subtask)
        subtask.result = result
    }
    // Summarize the result
    let result = resultSummarize(planTask)
    LogUtils.info(agent.name, "Summarized answer: ${result}")
    return AgentResponse(result)
}

我们来用一个房屋装修的例子来理解这个过程:
用户 PlanReactExecutor 知识提取 问题分解 ReactWorker 结果汇总 我要装修一套北欧风格的房子 提取需求和关键信息 返回用户喜好和关键需求 分解成多个施工任务 返回水电、木工、油漆等任务 分配子任务 完成子任务并报告 loop [每个子任务] 整合所有工作成果 提供最终验收报告 交付装修完成的房子 用户 PlanReactExecutor 知识提取 问题分解 ReactWorker 结果汇总

  1. 知识提取:就像设计师了解业主的喜好和需求

    cangjie 复制代码
    let knowledge = knowledgeExtract(agent, request)
  2. 问题分解:就像项目经理将装修分解为水电、木工、油漆等工序

    cangjie 复制代码
    let subtasks: Array<Subtask> = problemDecompose(agent, request)
  3. 创建计划任务:汇总需求和任务清单,形成施工方案

    cangjie 复制代码
    let planTask = PlanTask(agent, request, subtasks, knowledge)
  4. 执行每个子任务:安排工人团队依次完成各个工序

    cangjie 复制代码
    for (subtask in subtasks) {
        let worker = ReactWorker(planTask)
        let result = worker.solve(subtask)
        subtask.result = result
    }
  5. 汇总结果:整合所有工作,形成最终成果

    cangjie 复制代码
    let result = resultSummarize(planTask)
  6. 返回结果:向业主交付完工的房子

    cangjie 复制代码
    return AgentResponse(result)

这个过程既有条理又高效,每个步骤都有明确的职责,就像一个专业的项目团队!

4 异步执行流程:实时查看进度的魔力

当我们需要实时查看任务执行进度时,就可以使用异步执行函数:

cangjie 复制代码
override public func asyncRun(agent: Agent, request: AgentRequest): AsyncAgentResponse {
    let planTask = PlanTask(agent, request)
    // Create the worker thread
    let fut: Future<Iterator<String>> = spawn {
        try {
            return workFn(planTask)
        } catch(ex: Exception) {
            planTask.execInfo.verboseChannel.close()
            throw ex
        }
        throw UnsupportedException("Unreachable")
    }
    return AsyncAgentResponse(IteratorWrapper(planTask, fut), execInfo: planTask.execInfo)
}

这就像你在手机APP上订购一份外卖,可以实时看到"商家接单→厨师制作→骑手取餐→配送中→已送达"的全过程,而不是只能干等结果。
用户请求 创建计划任务 创建工作线程 异步执行workFn 返回异步响应 实时进度更新 用户界面

这里的关键是spawn表达式,它创建了一个新的工作线程来执行workFn函数,这样主线程就不会被阻塞。用生活中的例子来说,这就像你在餐厅点菜后,服务员会给你一个电子呼叫器,你可以去做其他事情,等菜好了会通知你。

5 workFn函数:异步工作的实际执行者

workFn函数是实际执行异步工作的地方,让我们仔细看看它的实现:

cangjie 复制代码
private func workFn(planTask: PlanTask): Iterator<String> {
    let agent = planTask.agent
    let request = planTask.request
    // Extract necessary knowledge
    planTask.knowledge = knowledgeExtract(agent, request)
    // Decompose the problem
    let subtasks: Array<Subtask> = problemDecompose(agent, request)
    planTask.subtasks = subtasks
    if (request.verbose) {
        let strBuilder = StringBuilder()
        strBuilder.append("# The Plan\n")
        for (subtask in subtasks) {
            strBuilder.append(subtask.toMarkdown())
            strBuilder.append("\n")
        }
        planTask.execInfo.verboseChannel.put(strBuilder.toString().withTag(ReactTag.PLAN))
    }
    // Solve each subtask
    for (subtask in subtasks) {
        if (request.verbose) {
            planTask.execInfo.verboseChannel.put("Solve the subtask: ${subtask.name}".withTag(ReactTag.PLAN))
        }
        let worker = ReactWorker(planTask)
        let asyncResp = worker.asyncSolve(subtask, verbose: request.verbose)
        if (request.verbose) {
            // Transfer the internal information from the react worker to this agent
            for (data in asyncResp.execInfo.getOrThrow().verboseInfo) {
                planTask.execInfo.verboseChannel.put(data)
            }
        }
        subtask.result = asyncResp.content
        if (request.verbose) {
            planTask.execInfo.verboseChannel.put("# Subtask DONE!\n${subtask.toMarkdown()}".withTag(ReactTag.INFO))
        }
    }
    if (request.verbose) {
        planTask.execInfo.verboseChannel.close()
    }
    // Summarize the result
    return asyncResultSummarize(planTask)
}

让我们用一个建造乐高模型的例子来理解这个过程:
用户 PlanReactExecutor 计划 子任务 ReactWorker 结果 准备阶段 我想搭建一个乐高城堡 提取关键信息 生成搭建计划 展示整体计划和分步骤 执行阶段 开始执行当前步骤 使用合适的零件和工具 完成当前部分 实时展示搭建进度 loop [每个搭建步骤] 完成阶段 整合所有部分 展示完整的乐高城堡 用户 PlanReactExecutor 计划 子任务 ReactWorker 结果

在这个过程中,最有价值的部分是用户可以看到计划和每个子任务的执行过程,这就是verbose模式的作用:

cangjie 复制代码
if (request.verbose) {
    let strBuilder = StringBuilder()
    strBuilder.append("# The Plan\n")
    for (subtask in subtasks) {
        strBuilder.append(subtask.toMarkdown())
        strBuilder.append("\n")
    }
    planTask.execInfo.verboseChannel.put(strBuilder.toString().withTag(ReactTag.PLAN))
}

这段代码就像是向用户展示乐高说明书的全貌,让用户知道接下来会发生什么。然后在执行每个子任务时,不断更新进度:

cangjie 复制代码
if (request.verbose) {
    planTask.execInfo.verboseChannel.put("Solve the subtask: ${subtask.name}".withTag(ReactTag.PLAN))
}

这就像是告诉用户"现在正在搭建城堡的塔楼部分",让用户了解当前进度。

6 与其他执行器的对比

执行器类型 NaiveExecutor ReActExecutor PlanReactExecutor 特点: 简单直接 场景: 简单问答 特点: 思考-行动-观察循环 场景: 需要使用工具 特点: 先规划后执行 场景: 复杂多步骤问题

如果用餐厅来比喻三种执行器:

  • NaiveExecutor:快餐店,直接点餐、直接出餐
  • ReActExecutor:普通餐厅,厨师根据订单现做现卖
  • PlanReactExecutor:高档餐厅,主厨先设计菜单,然后团队分工协作制作多道菜肴,最后组合成一顿完美的大餐

PlanReactExecutor最适合那些需要多步骤、多角度思考的复杂问题。

7 实际应用案例

案例一:学术研究助手

当用户请求研究神经网络的最新进展时,执行过程可能是:
用户请求: 研究神经网络最新进展 知识提取: 确定研究领域为神经网络和图像识别 问题分解 子任务1: 查找最新论文 子任务2: 阅读关键论文 子任务3: 总结主要发现 子任务4: 比较不同方法 执行子任务 汇总: 综合报告 最终结果: 全面的研究报告

案例二:旅行规划助手

想象一个用户想规划一次欧洲之旅:

复制代码
用户: 请帮我规划一次为期7天的法国巴黎和意大利罗马的旅行,包括景点、住宿和交通。

使用PlanReactExecutor,执行过程可能是:

  1. 知识提取:了解用户想去巴黎和罗马,时间为7天
  2. 问题分解
    • 子任务1:规划巴黎部分的行程(3天)
    • 子任务2:规划罗马部分的行程(3天)
    • 子任务3:规划两地之间的交通(1天)
    • 子任务4:提供住宿建议
    • 子任务5:整合完整行程
  3. 执行每个子任务:分别解决每个子任务
  4. 汇总结果:生成完整的7天旅行计划

案例三:复杂数学问题求解

复制代码
用户: 请求解下列方程组:
3x + 2y - z = 10
2x - 3y + 2z = -5
x + y + z = 7

使用PlanReactExecutor解决这个问题:

  1. 知识提取:确定这是一个三元一次方程组
  2. 问题分解
    • 子任务1:使用消元法消去z变量
    • 子任务2:解出x和y的关系
    • 子任务3:代回求解x、y、z的值
    • 子任务4:验证结果是否正确
  3. 执行子任务:依次解决每个数学步骤
  4. 汇总结果:提供完整的解答和解释

8 核心组件深度解析

PlanReactExecutor不是独立工作的,它依赖几个核心组件:
PlanReactExecutor knowledgeExtract problemDecompose ReactWorker resultSummarize 功能: 提取关键知识 实现: 使用LLM分析问题 功能: 分解为子任务 实现: 让LLM进行任务规划 功能: 解决单个子任务 实现: 使用ReAct方法 功能: 整合所有结果 实现: 让LLM综合所有信息

  1. knowledgeExtract:就像研究生开始论文前的文献综述,先了解相关知识

  2. problemDecompose:就像建筑师在开工前绘制详细的施工图纸

  3. ReactWorker:就像专业工人按照图纸完成具体工作

  4. resultSummarize:就像编辑将多篇文章整合成一本完整的书

这些组件协同工作,使得PlanReactExecutor能够处理非常复杂的问题。

9 PlanReactExecutor的优势与局限

PlanReactExecutor 优势 局限 能解决复杂问题 思路清晰可追踪 结果全面系统 可并行执行子任务 执行时间较长 资源消耗较大 简单问题反而复杂化

优势:

  1. 解决复杂问题:像专业律师处理复杂案件,有条不紊
  2. 思路清晰:用户可以看到完整的思考过程,增强可信度
  3. 结果全面:考虑问题的多个方面,不会遗漏重要内容
  4. 可追踪性:出现问题可以定位到具体哪个子任务

局限:

  1. 执行时间长:就像做一道复杂的菜肴,需要更多时间
  2. 资源消耗大:需要更多的API调用和计算资源
  3. 简单问题反而复杂化:用大炮打蚊子,对简单问题过度设计

10 何时选择PlanReactExecutor?

简单 复杂 只需一两个工具 需要多步规划 面对一个问题 是否复杂? 使用NaiveExecutor 需要工具吗? 使用ReActExecutor 使用PlanReactExecutor

适合使用PlanReactExecutor的场景:

  1. 多步骤问题:如规划旅行、制定学习计划
  2. 需要多角度分析:如进行SWOT分析、评估风险
  3. 需要综合信息:如撰写研究报告、市场分析
  4. 组织创作内容:如写一本书的大纲、设计课程体系

不适合的场景:

  1. 简单问答:如"今天天气怎么样"
  2. 单一工具调用:如"计算123 + 456"
  3. 快速响应场景:如紧急情况下的决策

11 总结

PlanReactExecutor就像一位经验丰富的项目经理,能够将复杂问题分解为可管理的小任务,然后一步步解决,最终整合成完整的解决方案。在处理复杂问题时,它的表现远超简单的执行器。

当你的AI应用需要处理复杂的多步骤问题时,不妨考虑使用PlanReactExecutor,它将帮助你的Agent像专业团队一样有条不紊地解决问题。

相关推荐
博睿谷IT99_4 分钟前
华为HCIP-AI认证考试版本更新通知
人工智能·华为
连续讨伐13 分钟前
ensp的华为小实验
华为
一点.点1 小时前
SafeDrive:大语言模型实现自动驾驶汽车知识驱动和数据驱动的风险-敏感决策——论文阅读
人工智能·语言模型·自动驾驶
concisedistinct1 小时前
如何评价大语言模型架构 TTT ?模型应不应该永远“固定”在推理阶段?模型是否应当在使用时继续学习?
人工智能·语言模型·大模型
沙振宇1 小时前
【Web】使用Vue3开发鸿蒙的HelloWorld!
前端·华为·harmonyos
找了一圈尾巴1 小时前
AI Agent-基础认知与架构解析
人工智能·ai agent
jzwei0231 小时前
Transformer Decoder-Only 参数量计算
人工智能·深度学习·transformer
小言Ai工具箱2 小时前
PuLID:高效的图像变脸,可以通过文本提示编辑图像,通过指令修改人物属性,个性化文本到图像生成模型,支持AI变脸!艺术创作、虚拟形象定制以及影视制作
图像处理·人工智能·计算机视觉
白熊1882 小时前
【计算机视觉】基于深度学习的实时情绪检测系统:emotion-detection项目深度解析
人工智能·深度学习·计算机视觉
TextIn智能文档云平台2 小时前
PDF文档解析新突破:图表识别、公式还原、手写字体处理,让AI真正读懂复杂文档!
图像处理·人工智能·算法·自然语言处理·pdf·ocr