资讯动态

智能体如何从演示中学习:层次化结构为何优于扁平动作日志

发布时间:2026/8/20 4:10:56 来源:尧图企业网站定制
1. 项目概述从“动作记录”到“结构理解”的范式转变最近在折腾智能体Agents相关的项目特别是如何让它们更高效地从人类演示中学习。我发现一个挺有意思的现象很多团队在构建基于演示编程Programming by Demonstration, PbD的智能体时习惯性地把演示数据当作一长串扁平的“动作日志”Action Logs来喂给模型。比如记录下用户点击了哪个按钮、输入了什么文本、按了什么快捷键然后期望智能体能依葫芦画瓢。但实际效果往往不尽如人意智能体学到的行为要么僵硬死板要么在稍微复杂一点的场景下就“懵”了无法举一反三。这让我开始思考一个核心问题智能体到底应该如何“阅读”演示是应该像看流水账一样逐条记忆动作序列还是应该尝试去理解演示背后隐藏的“剧本”和“意图”标题《How Should Agents Read Demonstrations? Hierarchical Structure Beats Flat Action Logs》直接点明了答案层次化结构Hierarchical Structure完胜扁平的动作日志。这不仅仅是一个技术选型问题更是一种认知范式的转变。它意味着我们不再把智能体看作一个简单的“动作回放机”而是希望它成为一个能理解任务目标、子任务划分、以及行动背后逻辑的“思考者”。这个项目探讨的就是如何将这种“层次化结构”的思想落地到智能体学习人类演示的具体实践中。无论是开发自动化测试脚本的Playwright Test Agents还是构建能处理复杂业务流程的Managed Deep Agents甚至是像CodeBuddy Multi Agents这样的多智能体协作系统其效能瓶颈往往不在于模型本身有多大而在于我们喂给它的“数据食粮”是否易于消化和理解。层次化结构就是那把将生硬的动作数据“烹饪”成营养丰富、易于吸收的知识大餐的关键厨具。2. 核心概念拆解动作日志 vs. 层次化结构要理解为什么层次化结构更优我们得先掰开揉碎看看“动作日志”和“层次化结构”到底指什么以及它们在智能体学习过程中的不同角色。2.1 扁平动作日志的局限与挑战动作日志是最直观、最容易采集的数据形式。它忠实地记录了人机交互过程中每一个原子操作。例如在一个网页自动化任务中日志可能长这样1. 打开浏览器导航至 https://example.com/login 2. 在 idusername 的输入框内输入 “test_user” 3. 在 idpassword 的输入框内输入 “password123” 4. 点击 idlogin_button 的按钮 5. 等待页面跳转检测 classwelcome-msg 的元素出现 6. 点击 link_text‘Settings’ 的链接 ...优点很明显数据采集简单无需额外标注记录精确可完全复现单次操作。但缺点更为致命这正是智能体学习效果不佳的根源缺乏意图与目标信息日志只记录了“做了什么”What但没有说明“为什么这么做”Why。智能体无法区分哪些点击是为了“登录”哪些点击是为了“进入设置页面”。它学到的是特定像素坐标或元素ID上的操作序列而非“登录”这个高层目标。对噪声和变化极度敏感如果下次登录页面的按钮ID从login_button变成了submit_btn或者页面布局微调导致元素定位路径变化基于动作日志训练的智能体就会完全失效。它没有学到“找到代表登录确认的主要按钮并点击”这个抽象概念。无法处理长程依赖和可选路径在复杂任务中很多步骤是可选的或存在条件分支。扁平的日志序列无法表达“如果A情况发生则执行B否则执行C”这样的逻辑。智能体只能机械地记忆一条固定路径。数据效率低下为了让智能体覆盖一个任务的所有可能情况需要提供海量的、覆盖各种边缘情况的动作日志这在实际中成本极高。注意许多初期尝试用LLM驱动智能体LLM Powered Autonomous Agents的项目容易陷入这个陷阱。它们将任务描述和动作历史即动作日志直接拼接成提示词Prompt喂给LLM虽然LLM有一定的推理能力但本质上还是在“猜”下一个最可能的原子动作而非进行有规划的任务分解。这种方式在简单任务上可行但任务复杂度一上来可靠性和泛化性就会急剧下降。2.2 层次化结构的定义与优势与扁平的序列不同层次化结构试图为演示数据赋予一种树状或图状的抽象表达。它不再聚焦于原始动作而是致力于识别和构建以下几个层次目标层Goal Level任务的最终目的。例如“完成用户登录并修改账户昵称”。任务层Task Level为实现最终目标而分解出的关键子目标。例如可分解为【任务1登录系统】和【任务2修改个人资料】。子任务/技能层Sub-task / Skill Level每个任务可以由更细粒度的、可复用的技能或子任务构成。例如【任务1登录系统】可以分解为【技能1.1导航到登录页】、【技能1.2填写凭证】、【技能1.3提交表单】。原子动作层Primitive Action Level最底层的具体操作即传统的动作日志。但在这里它们被组织在相应的技能节点之下。这种结构带来了根本性的优势泛化能力增强智能体在“登录”这个技能节点下学习的是“填写凭证”这个抽象模式。当它遇到一个新的登录界面时它会去寻找用户名和密码输入框并执行填写操作而不是寻找特定的idusername。模型学习的是功能和语义而非具体的定位器。可解释性与可编辑性层次结构本身就是一个任务规划图。开发者可以直观地看到智能体理解的“任务蓝图”并可以在高层任务、技能层进行修改或调整而不必深入到成千上万的原子动作中去。组合与复用一旦“登录”、“搜索”、“表单提交”等被抽象为技能它们就可以像乐高积木一样被组合起来完成新的、更复杂的任务。这极大地提升了开发效率也是构建Multi Agents系统的基础——不同智能体可以负责不同层次的技能或任务。数据效率提升学习一个可复用的“技能”可能只需要几个演示样例。一旦掌握这个技能就可以被应用于无数包含该技能的任务中。相比于为每个具体任务收集海量动作日志这种方式经济得多。鲁棒性提高层次结构允许在高层进行重试和回退。如果“点击提交按钮”这个原子动作失败了技能层的策略可以决定是重试、检查网络还是上报错误而不是让整个冗长的动作序列崩溃。3. 构建层次化演示数据从原始日志到结构树理论很美好但如何从原始的动作日志中自动或半自动地提取出这种层次化结构呢这是项目的核心挑战。完全手动标注成本太高我们需要一套方法。3.1 结构提取的关键信号与算法思路人类演示中天然蕴含着层次结构的线索。我们的操作不是随机的而是围绕意图分组进行的。提取结构的关键在于识别这些“分组边界”。时间间隔与停顿完成一个子任务如填写表单后用户通常会有一个短暂的停顿或思考然后才开始下一个子任务如点击提交。这个时间间隔是一个强烈的分割信号。界面状态变迁一个子任务的完成往往伴随着用户界面UI状态的显著变化。例如点击登录按钮后页面从登录页跳转到了主页。检测URL变化、页面主要视觉区域通过计算机视觉或DOM树快照对比的突变可以标识任务边界。操作对象的语义聚类在同一子任务中用户的操作往往集中在屏幕上某个语义相关的区域。例如在填写收货地址时所有操作都集中在地址表单的各个输入框上。可以利用元素的视觉布局、DOM树中的父子关系、以及元素的语义标签如input[type“text”]进行聚类。演示者的自然语言旁白如果可用在录制演示时如果演示者同步进行语音说明“现在我来登录...好了登录成功了接下来我们去找设置页面...”这些语音是提取高层次任务标签的黄金数据。基于这些信号一个典型的处理流水线可以是输入原始动作日志序列[A1, A2, A3, ..., An]每个动作包含时间戳、动作类型点击、输入等、目标元素描述等信息。步骤1粗粒度分割。利用时间间隔阈值和界面状态突变检测如页面加载完成事件、主要页面内容变化将长序列切分成几个大的“段落”Episode。步骤2细粒度聚类。在每个段落内利用操作对象的视觉/语义相似性将动作进一步聚类成更小的“技能块”Skill Chunk。例如所有对“登录模态框”内元素的操作被聚为一类。步骤3抽象与标签生成。自动生成对每个技能块可以总结其共同模式。例如一个包含“在输入框X输入文本T1”、“在输入框Y输入文本T2”、“点击按钮Z”的技能块可以被抽象为“填写表单Form X并提交”。人工标注/LLM辅助将技能块和其上下文前后的技能块、当前的页面截图或描述提供给大语言模型LLM让其生成一个人类可读的技能名称如“用户登录”、“商品搜索筛选”。对于更高层的任务标签也可以采用类似方法。输出一棵层次化任务树。根节点是总目标叶子节点是原子动作中间节点是自动或半自动生成的任务和技能标签。3.2 实操工具与数据格式设计在实际操作中我们可能需要结合多种工具。对于Web自动化场景Playwright或Selenium可以录制精细的动作日志。我们可以扩展其录制器除了记录动作还同时截取操作前后的页面快照和DOM快照为界面状态分析提供数据。处理这些数据的脚本可以用Python实现会执行上述分割、聚类和抽象算法。最终我们需要一种数据格式来存储层次化演示。JSON是一个不错的选择因为它能很好地表达树状结构。{ goal: 在电商网站购买一本特定书籍, tasks: [ { id: task_1, description: 登录网站账户, skills: [ { id: skill_1_1, description: 导航至登录页并填写凭证, primitives: [ {action: navigate, url: https://example.com/login}, {action: fill, selector: #email, value: userexample.com}, {action: fill, selector: #password, value: ******} ] }, { id: skill_1_2, description: 提交登录表单, primitives: [ {action: click, selector: button[typesubmit]} ] } ] }, { id: task_2, description: 搜索并选择目标书籍, skills: [ { id: skill_2_1, description: 在搜索框输入书名, primitives: [ {action: fill, selector: .search-box input, value: Deep Learning}, {action: click, selector: .search-box button} ] } // ... 更多技能 ] } ] }实操心得在初期不必追求全自动的完美提取。可以采用“人机回环”Human-in-the-loop的方式。让算法先提出一个初步的分割和聚类结果然后由开发者在可视化工具中进行审核、合并、拆分和重命名。这样既能保证质量又能逐步积累训练数据用于优化后续的自动提取模型。许多Managed Deep Agents平台的后台本质上就在做类似的事情。4. 基于层次化结构的智能体训练与推理有了结构化的演示数据我们如何用它来训练智能体并在运行时让智能体利用这种结构进行推理呢这里的范式与端到端的行为克隆Behavior Cloning有显著不同。4.1 训练范式分层学习与技能库构建我们不再训练一个单一的、庞大的策略网络来直接映射状态到原子动作。相反我们采用分层训练底层技能策略学习针对每一个被抽象出来的“技能”如“点击提交按钮”、“填写文本表单”我们可以用相对简单的模型如一个小型神经网络甚至决策树进行训练。输入是当前状态的抽象表示例如围绕焦点的屏幕局部截图编码、相关元素的属性集合输出是该技能所需的原子动作序列或参数如点击坐标、输入的文本。因为每个技能的范围有限所以更容易学习也更容易泛化。高层任务规划器学习这个模块学习如何根据当前的高级目标Goal和环境状态调用合适的技能并确定它们的执行顺序。这可以建模为一个序列决策问题。我们可以使用演示数据中的任务树作为监督信号训练一个规划器模型。输入是目标描述和全局状态输出是一个技能调用序列或技能树。由于技能是抽象的规划器的搜索空间大大缩小。技能库所有学会的技能策略被存储在一个“技能库”Skill Library中。这是智能体可复用能力的核心资产。这种方法的另一个巨大好处是持续学习。当遇到一个新任务时智能体可以尝试用现有技能库中的技能进行组合。如果失败可以录制新的人类演示从中提取出新的技能加入到技能库中。整个系统是模块化增长而非推倒重来。4.2 推理过程分层执行与异常处理在运行时智能体的运作流程更像一个经典的“Sense-Plan-Act”循环但“Plan”和“Act”都是分层的感知Sense智能体获取当前环境的状态表示如当前网页的DOM、截图。高层规划High-level Planning任务规划器根据当前状态和既定目标从技能库中选择下一个要执行的技能并可能确定其参数例如“执行‘搜索商品’技能参数为‘书名Deep Learning’”。技能执行Skill Execution对应的底层技能策略被激活。它接收更具体的环境信息如搜索框的定位生成一系列原子动作点击、输入等并执行它们。状态验证与重规划Verification Replanning技能执行后智能体会检查预期状态是否达成例如是否跳转到了搜索结果页。如果达成则规划器选择下一个技能如果失败如元素未找到、超时则触发异常处理流程。异常处理本身也可以是一个高层技能比如“刷新页面并重试技能X”或“执行备选技能Y”。这种分层架构使得整个系统更加鲁棒和可调试。如果任务失败我们可以很容易地定位是规划器选错了技能还是某个底层技能本身执行出了问题。相比之下一个端到端的黑盒模型失败了我们很难知道是哪里理解错了。5. 行业应用场景与挑战将层次化演示学习应用于智能体开发正在多个领域催生新的解决方案和最佳实践。5.1 典型应用场景软件测试自动化Playwright Test Agents传统的测试脚本脆弱且维护成本高。基于层次化演示的测试智能体可以从测试人员录制的基本流程中自动抽象出“登录”、“添加商品到购物车”、“结账”等测试技能。当UI发生变化时只需更新对应的底层技能如新的元素定位器所有用到该技能的测试用例都会自动适应无需重写大量脚本。机器人流程自动化RPA与业务流程管理在处理发票、录入数据等重复性办公任务时智能体可以从员工的几次操作演示中学习到“打开邮件客户端”、“提取PDF附件中的表格”、“填入ERP系统”等层次化技能。这比编写和维护复杂的、针对特定软件版本的RPA脚本要灵活得多。智能助手与交互式教学想象一个教你使用复杂软件如Photoshop的智能助手。它观察你完成“制作海报”的任务将其分解为“新建画布”、“添加文字”、“应用滤镜”、“导出图片”等技能。当其他用户遇到类似但不同的任务如“制作邀请函”时助手可以组合这些技能进行指导而不是机械地回放你的具体操作。游戏AI与模拟环境智能体在游戏或仿真环境中层次化技能如“寻路到A点”、“打开宝箱”、“使用药剂”可以从专家玩家的演示中学习。智能体然后可以复用这些技能通过高层规划来完成复杂的任务链实现更智能、更拟人的游戏行为。5.2 当前面临的挑战与应对思路尽管前景广阔但将层次化演示学习大规模落地仍面临挑战结构提取的准确性自动从演示中推断出“正确”的层次结构仍然是一个难题。不同的抽象粒度可能导致不同的效果。目前结合时序分析、计算机视觉、自然语言理解和人机回环的半自动方法是最可行的路径。技能的泛化边界一个“点击按钮”的技能到底能泛化到多大范围是所有按钮还是特定样式的按钮定义技能的抽象级别和泛化能力需要权衡。过于具体则复用性差过于抽象则学习困难且执行不可靠。实践中可能需要建立多粒度的技能库。组合爆炸问题当技能库变得庞大时高层规划器如何高效地搜索和组合技能以完成新任务这可能需要引入基于LLM的语义规划或者利用任务之间的相似性进行迁移学习。演示数据的质量与多样性“垃圾进垃圾出”的原则同样适用。低质量、有歧义或过于特殊的演示会导致提取出无用或过拟合的技能。建立演示数据的质量标准如覆盖主要用例、操作清晰和清洗流程至关重要。注意事项在启动这类项目时切忌一开始就追求全自动、通用化的智能体。一个更稳妥的策略是垂直领域先行。选择一个具体的、边界清晰的场景如“电商网站的回归测试”在该场景下收集高质量的演示数据构建初始的技能库和规划器。验证其价值后再逐步扩展场景和技能库的范畴。许多成功的Building Effective Agents案例都是从一个“小切口”做深做透开始的。6. 实战构建一个简单的层次化Web操作智能体原型理论说了这么多我们来动手搭建一个最简单的原型感受一下从扁平日志到层次化结构再到智能体执行的全过程。我们将以“在某个论坛网站进行登录和发帖”作为示例任务。6.1 第一步数据采集与预处理我们使用Playwright的录制功能手动操作一遍“登录-发帖”流程。录制会生成一个包含原子动作的脚本。我们需要对这个脚本进行增强在每一步记录时间戳和页面快照简化起见可以记录页面URL和标题。原始的扁平动作日志简化版如下动作1: goto(‘https://bbs.example.com’) 动作2: click(‘text登录’) 动作3: fill(‘input[name“username”]‘, ‘myuser’) 动作4: fill(‘input[name“password”]‘, ‘mypass’) 动作5: click(‘button:has-text(“登录”)’) 动作6: wait_for_url(‘https://bbs.example.com/forum’) 动作7: click(‘a:has-text(“技术讨论区”)’) 动作8: click(‘text发表新帖’) 动作9: fill(‘input[name“title”]‘, ‘层次化智能体分享’) 动作10: fill(‘textarea[name“content”]‘, ‘这是一篇关于…’) 动作11: click(‘button:has-text(“提交”)’)6.2 第二步层次结构提取规则启发式我们编写一个Python处理脚本应用一些简单的规则来分割和聚类基于URL变化的任务分割观察到动作5点击登录后URL从登录页变为了论坛首页动作6。这是一个明确的任务边界。因此我们将动作1-5聚类为“登录”任务。基于界面语义的细粒度聚类在“登录”任务内部动作3和4都是对“输入框”的fill操作且目标元素名称username, password具有语义相关性。我们将它们聚类为一个“填写凭证”技能。动作2点击登录链接和动作5点击登录按钮是导航和提交动作分别作为独立的技能或归入更高层的“登录”任务中。同理动作7-11可以聚类为“发帖”任务其中动作9和10可以聚类为“填写帖子内容”技能。通过这种简单的规则我们得到了一个初步的层次结构描述可以用字典表示hierarchical_demo { “goal”: “在论坛登录并发布一个新帖子” “tasks”: [ { “name”: “task_login”, “description”: “登录论坛账户” “skill_sequence”: [ {“type”: “skill”, “name”: “nav_to_login”, “primitives”: [1, 2]}, # 动作索引 {“type”: “skill”, “name”: “fill_credentials”, “primitives”: [3, 4]}, {“type”: “skill”, “name”: “submit_login”, “primitives”: [5]} ] }, { “name”: “task_post”, “description”: “在技术讨论区发布新帖” “skill_sequence”: [ {“type”: “skill”, “name”: “nav_to_forum”, “primitives”: [6, 7]}, {“type”: “skill”, “name”: “enter_post_page”, “primitives”: [8]}, {“type”: “skill”, “name”: “fill_post_content”, “primitives”: [9, 10]}, {“type”: “skill”, “name”: “submit_post”, “primitives”: [11]} ] } ] }6.3 第三步技能抽象与策略学习对于每个技能我们需要从具体的动作中抽象出可泛化的策略。以fill_credentials技能为例具体动作在input[name“username”]填入“myuser”在input[name“password”]填入“mypass”。抽象策略在当前的页面或某个特定区域如登录表单内找到所有类型为“text”或“password”的输入框。根据常见的表单模式通常用户名在前密码在后且有placeholder或name属性提示将提供的凭证文本填入对应的输入框。实现我们可以为这个技能编写一个函数它接收“当前页面DOM”和“凭证字典{‘username’: ‘…’ ‘password’: ‘…’}”作为输入函数内部使用启发式规则查找输入框、分析标签文本或一个轻量级模型来定位元素并执行填充操作。这个函数的逻辑就是从单一演示中“学习”到的技能策略。6.4 第四步高层规划与执行高层规划器在这个简单原型中可以是一个硬编码的规则按顺序执行task_login然后执行task_post。在执行每个任务时按顺序调用其下的技能。当智能体面对一个新的论坛网站时流程如下规划器启动task_login。task_login调用skill_nav_to_login。该技能的策略可能是“在页面上寻找包含‘登录’、‘Sign in’等文本的链接或按钮并点击”。它在新网站上成功找到了登录链接并点击。接着调用skill_fill_credentials。该技能的策略上面抽象出来的在新网站的登录表单上运行成功定位到用户名和密码输入框并填入凭证。最后调用skill_submit_login点击提交按钮。登录成功后规划器启动task_post后续技能同理执行。这个原型的核心价值在于即使新论坛的页面布局、元素ID和选择器完全不同只要其基本功能逻辑有登录入口、有用户名密码输入框、有提交按钮不变基于层次化抽象技能的智能体就有很大概率成功完成任务。而一个只记忆了原始选择器的扁平动作日志回放脚本则必然失败。7. 总结与展望通往更通用智能体的路径从“扁平动作日志”到“层次化结构”本质上是我们教智能体“如何学习”的一次升级。我们不再满足于让它模仿表面的“肢体动作”而是引导它去理解人类行为背后的“目标”和“计划”。这种方法显著提升了智能体的泛化能力、鲁棒性和可解释性。回顾像Lilian Weng等人关于LLM Powered Autonomous Agents的论述其核心挑战之一就是如何让智能体进行可靠的长程任务规划与执行。层次化演示学习为这个问题提供了一个坚实的答案通过从演示中提取可复用的技能模块智能体的规划空间被结构化、简化了。LLM可以更专注于高层的任务分解和技能调度而不必为每一个原子动作操心。对于从事Agents开发的工程师和研究者来说投入时间设计并实现一套层次化演示数据的采集、提取和应用 pipeline将是构建下一代更强大、更实用智能体的关键基础设施。这不仅仅是学术上的优化更是工程上解决实际业务自动化、测试自动化、智能辅助等问题的必由之路。当然这条路还很长。如何让结构提取更自动化、更准确如何定义技能的边界使其在可复用性和可靠性之间取得最佳平衡如何让多个智能体Multi Agents共享和协作使用一个庞大的技能库这些都是值得深入探索的方向。但可以肯定的是那些只会“看流水账”的智能体终将被能“读懂剧本”的智能体所取代。而起点就在于我们如何重新设计它们“阅读”演示的方式。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价