【仓颉 + 鸿蒙 + AI Agent】CangjieMagic框架(17):PlanReactExecutor
CangjieMagic框架:使用华为仓颉编程语言编写,专门用于开发AI Agent,支持鸿蒙、Windows、macOS、Linux等系统。
这篇文章剖析一下 CangjieMagic 框架中的 PlanReactExecutor。
1 PlanReactExecutor的工作原理
当你要组织一场生日派对时,你会怎么做?你不会一头扎进去就开始准备,而是会先:
- 了解寿星的喜好(知识提取)
- 分解任务:场地、食物、娱乐、礼物(问题分解)
- 一个个完成这些子任务(执行子任务)
- 最后把所有准备工作整合起来,举办一场成功的派对(汇总结果)
PlanReactExecutor就是这样工作的!它不会直接尝试解决一个复杂问题,而是先分析、分解,然后一步步解决,最后整合答案。
2 深入代码:构造函数和核心组件
我们先来看看PlanReactExecutor的构造函数:
protected class PlanReactExecutor <: AgentExecutor {protected PlanReactExecutor() { }// 其他成员...
}
这个构造函数非常简单,它背后连接了几个强大的组件:
就像一个专业厨师虽然看起来很简单地做了一道菜,但背后有一套完整的厨具和步骤一样,PlanReactExecutor看似简单,实则整合了多个专业组件。
3 同步执行流程:像项目经理一样工作
现在,让我们看看同步执行函数的实现:
override public func run(agent: Agent, request: AgentRequest): AgentResponse {// Extract necessary knowledgelet knowledge = knowledgeExtract(agent, request)// Decompose the problemlet subtasks: Array<Subtask> = problemDecompose(agent, request)let planTask = PlanTask(agent, request, subtasks, knowledge)// Solve each subtaskfor (subtask in subtasks) {let worker = ReactWorker(planTask)let result = worker.solve(subtask)subtask.result = result}// Summarize the resultlet result = resultSummarize(planTask)LogUtils.info(agent.name, "Summarized answer: ${result}")return AgentResponse(result)
}
我们来用一个房屋装修的例子来理解这个过程:
-
知识提取:就像设计师了解业主的喜好和需求
let knowledge = knowledgeExtract(agent, request) -
问题分解:就像项目经理将装修分解为水电、木工、油漆等工序
let subtasks: Array<Subtask> = problemDecompose(agent, request) -
创建计划任务:汇总需求和任务清单,形成施工方案
let planTask = PlanTask(agent, request, subtasks, knowledge) -
执行每个子任务:安排工人团队依次完成各个工序
for (subtask in subtasks) {let worker = ReactWorker(planTask)let result = worker.solve(subtask)subtask.result = result } -
汇总结果:整合所有工作,形成最终成果
let result = resultSummarize(planTask) -
返回结果:向业主交付完工的房子
return AgentResponse(result)
这个过程既有条理又高效,每个步骤都有明确的职责,就像一个专业的项目团队!
4 异步执行流程:实时查看进度的魔力
当我们需要实时查看任务执行进度时,就可以使用异步执行函数:
override public func asyncRun(agent: Agent, request: AgentRequest): AsyncAgentResponse {let planTask = PlanTask(agent, request)// Create the worker threadlet 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上订购一份外卖,可以实时看到"商家接单→厨师制作→骑手取餐→配送中→已送达"的全过程,而不是只能干等结果。
这里的关键是spawn表达式,它创建了一个新的工作线程来执行workFn函数,这样主线程就不会被阻塞。用生活中的例子来说,这就像你在餐厅点菜后,服务员会给你一个电子呼叫器,你可以去做其他事情,等菜好了会通知你。
5 workFn函数:异步工作的实际执行者
workFn函数是实际执行异步工作的地方,让我们仔细看看它的实现:
private func workFn(planTask: PlanTask): Iterator<String> {let agent = planTask.agentlet request = planTask.request// Extract necessary knowledgeplanTask.knowledge = knowledgeExtract(agent, request)// Decompose the problemlet subtasks: Array<Subtask> = problemDecompose(agent, request)planTask.subtasks = subtasksif (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 subtaskfor (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 agentfor (data in asyncResp.execInfo.getOrThrow().verboseInfo) {planTask.execInfo.verboseChannel.put(data)}}subtask.result = asyncResp.contentif (request.verbose) {planTask.execInfo.verboseChannel.put("# Subtask DONE!\n${subtask.toMarkdown()}".withTag(ReactTag.INFO))}}if (request.verbose) {planTask.execInfo.verboseChannel.close()}// Summarize the resultreturn asyncResultSummarize(planTask)
}
让我们用一个建造乐高模型的例子来理解这个过程:
在这个过程中,最有价值的部分是用户可以看到计划和每个子任务的执行过程,这就是verbose模式的作用:
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))
}
这段代码就像是向用户展示乐高说明书的全貌,让用户知道接下来会发生什么。然后在执行每个子任务时,不断更新进度:
if (request.verbose) {planTask.execInfo.verboseChannel.put("Solve the subtask: ${subtask.name}".withTag(ReactTag.PLAN))
}
这就像是告诉用户"现在正在搭建城堡的塔楼部分",让用户了解当前进度。
6 与其他执行器的对比
如果用餐厅来比喻三种执行器:
- NaiveExecutor:快餐店,直接点餐、直接出餐
- ReActExecutor:普通餐厅,厨师根据订单现做现卖
- PlanReactExecutor:高档餐厅,主厨先设计菜单,然后团队分工协作制作多道菜肴,最后组合成一顿完美的大餐
PlanReactExecutor最适合那些需要多步骤、多角度思考的复杂问题。
7 实际应用案例
案例一:学术研究助手
当用户请求研究神经网络的最新进展时,执行过程可能是:
案例二:旅行规划助手
想象一个用户想规划一次欧洲之旅:
用户: 请帮我规划一次为期7天的法国巴黎和意大利罗马的旅行,包括景点、住宿和交通。
使用PlanReactExecutor,执行过程可能是:
- 知识提取:了解用户想去巴黎和罗马,时间为7天
- 问题分解:
- 子任务1:规划巴黎部分的行程(3天)
- 子任务2:规划罗马部分的行程(3天)
- 子任务3:规划两地之间的交通(1天)
- 子任务4:提供住宿建议
- 子任务5:整合完整行程
- 执行每个子任务:分别解决每个子任务
- 汇总结果:生成完整的7天旅行计划
案例三:复杂数学问题求解
用户: 请求解下列方程组:
3x + 2y - z = 10
2x - 3y + 2z = -5
x + y + z = 7
使用PlanReactExecutor解决这个问题:
- 知识提取:确定这是一个三元一次方程组
- 问题分解:
- 子任务1:使用消元法消去z变量
- 子任务2:解出x和y的关系
- 子任务3:代回求解x、y、z的值
- 子任务4:验证结果是否正确
- 执行子任务:依次解决每个数学步骤
- 汇总结果:提供完整的解答和解释
8 核心组件深度解析
PlanReactExecutor不是独立工作的,它依赖几个核心组件:
-
knowledgeExtract:就像研究生开始论文前的文献综述,先了解相关知识
-
problemDecompose:就像建筑师在开工前绘制详细的施工图纸
-
ReactWorker:就像专业工人按照图纸完成具体工作
-
resultSummarize:就像编辑将多篇文章整合成一本完整的书
这些组件协同工作,使得PlanReactExecutor能够处理非常复杂的问题。
9 PlanReactExecutor的优势与局限
优势:
- 解决复杂问题:像专业律师处理复杂案件,有条不紊
- 思路清晰:用户可以看到完整的思考过程,增强可信度
- 结果全面:考虑问题的多个方面,不会遗漏重要内容
- 可追踪性:出现问题可以定位到具体哪个子任务
局限:
- 执行时间长:就像做一道复杂的菜肴,需要更多时间
- 资源消耗大:需要更多的API调用和计算资源
- 简单问题反而复杂化:用大炮打蚊子,对简单问题过度设计
10 何时选择PlanReactExecutor?
适合使用PlanReactExecutor的场景:
- 多步骤问题:如规划旅行、制定学习计划
- 需要多角度分析:如进行SWOT分析、评估风险
- 需要综合信息:如撰写研究报告、市场分析
- 组织创作内容:如写一本书的大纲、设计课程体系
不适合的场景:
- 简单问答:如"今天天气怎么样"
- 单一工具调用:如"计算123 + 456"
- 快速响应场景:如紧急情况下的决策
11 总结
PlanReactExecutor就像一位经验丰富的项目经理,能够将复杂问题分解为可管理的小任务,然后一步步解决,最终整合成完整的解决方案。在处理复杂问题时,它的表现远超简单的执行器。
当你的AI应用需要处理复杂的多步骤问题时,不妨考虑使用PlanReactExecutor,它将帮助你的Agent像专业团队一样有条不紊地解决问题。
相关文章:
【仓颉 + 鸿蒙 + AI Agent】CangjieMagic框架(17):PlanReactExecutor
CangjieMagic框架:使用华为仓颉编程语言编写,专门用于开发AI Agent,支持鸿蒙、Windows、macOS、Linux等系统。 这篇文章剖析一下 CangjieMagic 框架中的 PlanReactExecutor。 1 PlanReactExecutor的工作原理 #mermaid-svg-OqJUCSoxZkzylbDY…...
docker harbor私有仓库登录报错
docker harbor私有仓库登录报错如下: [rootsrv-1 ~]# docker login -u user1 -p pwd1 harbor.chinacloudapi.cn WARNING! Using --password via the CLI is insecure. Use --password-stdin. Error response from daemon: Get "https://harbor.chinacloudapi.…...
IQ信号和实信号的关系与转换的matlab实现
IQ信号 IQ信号通常是指两路正交的信号(I路和Q路),在实际信号采样中,通常会进行IQ采样,将实信号转换为复基带信号进行存储。 IQ信号转实信号 IQ信号转为实信号,其实就是将IQ两路正交信号通过上变频合并为一个实数的带通信号,这通常在通信系统中用于将基带信号调制到载…...
WSL2-Ubuntu22.04安装URSim5.21.3
WSL2-Ubuntu22.04安装URSim5.21.3 准备安装启动 准备 名称版本WSL2Ubuntu22.04URSim5.21.3VcXsrvNaN WSL2安装与可视化请见这篇:WSL2-Ubuntu22.04-配置。 安装 我们是wsl2-ubuntu22.04,所以安装Linux版本的URSim,下载之前需要注册一下,即…...
blender 录课键位显示插件(图文傻瓜式安装)
1、下载 点击这个链接进行下载https://github.com/nutti/Screencast-Keys 下载好不用解压 2、安装 打开blender进行安装 点击编辑选择偏好设置 选择插件再点击这个下箭头 选择从磁盘安装 然后找到自己刚刚下载好的,点击从磁盘安装 安装完成后勾选上插件 …...
天翼云手机断开连接2小时关机
2025-04-21 天翼云手机断开连接2小时自动 天翼云手机 4元1个月 天翼云手机永不关机 天翼云手机不休眠 天翼云手机断开连接时,界面显示:离线运行,2小时后自动关机 电脑每小时自动连接一次 手机每小时自动连接一次...
基于 FFmpeg 的音视频处理基础原理与实验探究
目录 1 基本知识1.1 解封装1.2 AAC和ADTS说明 1.3 H2641.3.1 H264编码结构解析1.3.2 NALU1.3.2 分类 2 实验1 探究音视频信息2.1 重要结构体介绍2.2 相关的API 3 实验二 提取AAC数据4 实验三 提取h264 1 基本知识 1.1 解封装 封装的逆向操作:封装是把音频流、视频流…...
【Rust 精进之路之第5篇-数据基石·下】复合类型:元组 (Tuple) 与数组 (Array) 的定长世界
系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025-04-20 引言:从原子到分子——组合的力量 在上一篇【数据基石上】中,我们仔细研究了 Rust 的四种基本标量类型࿱…...
【前端样式】用 aspect-ratio 实现等比容器:视频封面与图片占位的终极解决方案
在网页开发中,处理视频封面、图片卡片等需要固定比例的容器一直是前端工程师的必修课。本文将以 aspect-ratio 属性为核心,深入探讨如何优雅实现等比容器,并通过完整代码示例和常见问题解析,助你彻底掌握这一现代布局利器。 目录…...
【网络安全】OWASP 十大漏洞
1. OWASP 十大漏洞 为了应对未来的风险,安全专业人员需要随时掌握最新信息。之前,您了解了CVE 列表,这是一个公开的已知漏洞和暴露列表。CVE 列表是全球安全社区相互共享信息的重要信息来源。 在本文中,您将了解安全专业人士参考…...
我用deepseek做了一个提取压缩文件夹下pdf和word文件工具
由于最近需要把大量的压缩文件的pdf和word文件统一复制到一个文件夹中。 我们一般正常操作方式的是把一个压缩文件一个一个解压,然后在把一个的解压好的文件夹下文件复制到另外一个文件夹中。 这个也需太繁琐了,从以往统计的需要花费两个小时间&#x…...
【Docker】在容器中使用 NVIDIA GPU
解决容器 GPU 设备映射问题,实现 AI 应用加速 🔗 官方文档:NVIDIA Container Toolkit GitHub 常见错误排查 若在运行测试容器时遇到以下错误: docker: Error response from daemon: could not select device driver ""…...
机器人进阶---视觉算法(五)仿射变换和投影变换有什么区别
仿射变换和投影变换有什么区别 1. 定义2. 几何特性3. 变换矩阵4. 应用场景5. Python代码示例仿射变换投影变换6. 总结仿射变换和投影变换都是图像处理中常用的几何变换方法,但它们在变换性质、应用场景和变换矩阵等方面存在一些关键区别。 1. 定义 仿射变换 (Affine Transform…...
如何在 Amazon EC2 上部署 Java(Spring Boot 版)
让我们学习如何将 Java Spring Boot Web 服务器部署到 Amazon EC2。每月只需 3 美元。 使用 Azure,您可能不知道要花费多少钱。 Spring Boot 项目示例 在本教程中,我们将重点介绍如何将 Java Spring Boot 服务器部署到 Amazon EC2,因此我们不…...
IDEA打不开、打开报错
目录 场景异常原因解决 场景 1、本机已经安装了IDEA 2、再次安装另外一个版本的IDEA后打不开、打开报错 异常 这里忘记截图了。。。 原因 情况1-打不开:在同一台电脑安装多个IDEA是需要对idea的配置文件进行调整的,否则打不开 情况2-打开报错&#…...
【React】项目的搭建
create-react-app 搭建vite 搭建相关下载 在Vue中搭建项目的步骤:1.首先安装脚手架的环境,2.通过脚手架的指令创建项目 在React中有两种方式去搭建项目:1.和Vue一样,先安装脚手架然后通过脚手架指令搭建;2.npx create-…...
如何提高单元测试的覆盖率
一、定位未覆盖的代码 利用 IDEA 的覆盖率工具: 右键测试类 → Run with Coverage,或使用 AltShiftF10(Windows)打开运行菜单选择覆盖率。查看高亮标记: 绿色:已覆盖代码行。红色&#x…...
【SAP ME 43】RESRCE表操作导致HANA中表锁定解决方案
症状 SAP ME 通过执行以下 SQL 查询导致 RESRCE 表上的 HANA 数据库锁: 从 RESRCE WHERE HANDLE =? 选择站点待更新 或者 SELECT HANDLE FROM RESRCE WHERE HANDLE =... 用于更新 其他条款 HANA、锁、RESRCE 原因和前提条件 该问题是由运行 SQL FOR UPDATE 查询时的 …...
使用C#和FFmpeg开发RTSP视频播放器的完整指南
RTSP(Real Time Streaming Protocol)是流媒体技术中广泛使用的协议,广泛应用于视频监控、视频会议和在线直播等领域。本文将详细介绍如何使用C#和FFmpeg开发一个功能完整的RTSP视频播放器,涵盖从环境搭建到核心功能实现的全部过程。 一、开发环境准备 …...
CSS例子 > 图片瀑布流布局(vue2)
<template><div class"container"><!-- 临时容器用于计算高度 --><div v-if"!isLayoutReady" class"temp-container"><divv-for"(item, index) in list":key"temp- index":ref"(el) > …...
1.2软考系统架构设计师:系统架构的定义与作用 - 练习题附答案及超详细解析
系统架构定义与作用综合知识单选题 题目覆盖核心概念、发展历程、设计原则、评估标准及易混淆点,附答案解析: 1. 系统架构的标准定义源自于以下哪个标准? A. ISO/IEC 9126 B. IEEE 1471-2000 C. TOGAF 9.2 D. ITIL v4 答案:B 简…...
关于springmvc的404问题的一种猜测解决方案
本文是记录关于在学习动力结点老杜的springmvc时候遇到的404报错的一种解决方式; 由于本人之前学过老杜的springmvc,且运行成功,当时使用的是tomcat10.1.19版本。 idea使用2023.3.2版本。 而这次进行回顾的时候,使用tomcat10.0.1…...
PGSql常用操作命令
1 连接数据库: psql -U postgres (psql -U username -d databse_name -h host -W) -U 指定用户 -d 指定数据库 -h 要链接的主机 -W 提示输入密码 psql -h 主机名/服务器IP -p 端口号 -U 用户名 -d 数据库名 注意:(…...
使用Postman调测“获取IAM用户Token”接口实际操作
概述 Postman是网页调试与辅助接口调用的工具,具有界面简洁清晰、操作方便快捷的特性,可以处理用户发送的HTTP请求,例如:GET,PUT、POST,DELETE等,支持用户修改HTTP请求中的参数并返回响应数据。…...
Java面试(2025)—— Spring MVC
什么是Spring MVC Spring MVC 是 Spring 框架的一个 基于 Java 的 Web 开发模块,它实现了 MVC(Model-View-Controller)架构模式,用于构建灵活、松耦合的 Web 应用程序。 它是 Spring 生态的核心组件之一,通过简化 HTT…...
如何测试雷达与相机是否时间同步?
在多传感器融合系统中,相机与雷达的协同感知已成为环境理解的关键。相机通过捕捉纹理信息识别物体类别,而雷达利用激光或毫米波实现全天候精确测距。两者的数据融合既能避免单一传感器缺陷(如相机受光照影响、雷达缺乏语义信息)&a…...
Redis基本安装和部署
环境: linux docker 安装: sudo apt install -y redis-server运行: 后台模式:redis-server & , 前台模式:redis-server , 用配置文件运行redis: sudo redis-server /etc/redis/redis.conf , /etc/redis/redis.co…...
数据分析与产品、运营、市场之间如何有效对齐
数据分析的重要性在于它能够将海量的原始信息转化为可操作的洞察。以产品开发为例,通过用户行为数据的分析,产品经理可以清晰了解哪些功能被频繁使用,哪些设计导致用户流失,从而优化迭代方向。运营团队则依靠数据分析来监控供应链效率、预测需求波动,甚至通过实时数据调整…...
Pytorch分布式训练(DDP)(记录)
为什么要分布式训练? 随着深度学习模型参数量和数据量不断增大,单卡显存和计算能力有限,单机单卡训练难以满足大模型/大数据集训练需求,因此我们需要: 单机多卡并行:利用一台机器上多张 GPU 加速训练。 …...
爆肝整理!Stable Diffusion的完全使用手册(二)
继续介绍Stable Diffusion的文生图界面功能。 往期文章详见: 爆肝整理!Stable Diffusion的完全使用手册(一) 下面接着对SD的文生图界面的进行详细的介绍。本期介绍文生图界面的截图2,主要包含生成模块下的采用方法、调度类型、迭…...
