
Framer 重构 Agent 执行框架,代码边生成边运行,成本降 33%
来源标题:Harness 2: executing agent code as it streams
Framer 重构了 Framer Agent 的执行框架,让模型边生成 JavaScript 代码边执行,可直接处理完整工作流。新架构使运行成本降低最多 33%、速度提升 20%,每条消息的工具调用步骤减少一半,缓存输入 token 减少 39%。该框架还能在生成结束前发现错误假设并中止剩余输出,避免额外 token 费用。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
我们重建了 Framer Agent 的执行框架,让它能在单个程序中承担完整的工作流。这让成本降低最多 33%,速度提升 20%。
像“找到我们旧品牌色的所有使用位置并替换掉”这样的请求,可能涉及检查数千个节点、修改数百个属性。现在,agent 可以用 JavaScript 表达这项工作:检查文档、决定要修改哪些节点、并应用更新,而无需为每个决策都回到模型。
为了在单个程序中支持这么大的工作量,我们构建了一个执行系统,在模型还在编写 JavaScript 时就开始运行它。我们把传入的代码编译成可执行的 cell,并在它们就绪时立即运行。你可以在模型生成完剩余代码之前,就在画布上看到第一批更改。我们保留了原始 harness 的实时反馈,同时让 agent 拥有循环、条件判断以及对文档的访问能力。
我们还能在生成结束前发现失败的假设,停止剩余的流式输出,避免继续产生输出 token 费用,并把 agent 重试所需的信息返回给它。
新架构平均使用的工具步骤减少了 2 倍,每条消息的缓存输入 token 减少了 39%。这意味着任务效率有了显著提升,而质量没有测到下降。
Framer 使用树结构来表示你的设计文档。这棵树充当 AST,代码和 CMS 内容都从它确定性地生成。
我们 harness 的第一个版本使用一种 DSL(领域特定语言),让模型描述对这棵树的写入。模型发出命令来创建节点和设置属性。我们可以在命令到达时立即应用它们,因此你可以看到页面逐步成形。
局限性在重复编辑和依赖操作中显现出来:
重复编辑:在 100 个 frame 上修改同一个属性,可能需要 100 条编辑命令。
依赖编辑:读取一个值并在写入中使用它,需要单独的模型调用,并在调用之间重放上下文。
多步骤工作流:检查更改、发布到 staging、再提升到生产环境,每一步之间都需要回到模型。
即使模型事先知道整个工作流,harness 也让它一步一步地完成。
在单个程序中完成任务,避免了许多小程序所需的重复模型调用和输入 token。但更长的程序带来了两个问题:
反馈延迟:整个程序必须生成完毕才能开始执行,因此用户要等更久才能看到任何进展。
生成浪费:一个提前返回或终止性错误可能在仅仅几行之后就停止执行,但模型已经花时间和 token 写完了剩下的部分。
这两个问题都会随着程序变长而加剧:用户等待进展的时间更长,提前停止会在永远不会运行的代码上浪费更多生成时间和计费的输出 token。
为了让更长的程序变得可行,我们需要在生成结束前就开始执行它们。我们让生成和执行重叠,这样文档编辑——或者更耗时的操作,比如发布到 staging——可以在模型编写后续代码的同时开始。
随着代码流式传入,我们解析它以识别完整的 JavaScript 语句,将它们分组为可执行的“cell”,并发送到一个专用的 Web Worker。Cell 按顺序作为经典脚本执行,它们之间的绑定会被保留。我们还会把顶层 await 转译为经典脚本支持的语法。
同样的解析步骤会把像 // @step Building buttons 这样的注释转变成 emit("Building buttons"),在更长的程序中为用户提供进度更新。
在更大的程序中,模型可能会基于一个早期假设来构建许多后续操作。一个缺失的节点或一个意外的属性可能使后续大部分内容失效,浪费时间和输出 token。
我们提示 agent 在依赖它们的工作之前检查所需条件。如果这些检查通过,执行会继续,无需再一次模型往返。终止性错误或提前返回——包括不需要任何更改的情况——会取消剩余的生成。取消会保留已经应用到文档的编辑。
急切执行使这些节省成为可能:我们在模型仍在生成代码时就发现执行已经停止,因此可以取消剩余的流。如果我们先把整个程序缓冲起来再运行,这个发现就太晚了——生成时间和计费的输出 token 已经花掉了。具体节省多少取决于取消生效时生成已经进行到什么程度。
提前取消也改变了我们设计错误的方式。终止性错误可以解释出了什么问题以及如何恢复,让下一次尝试能够纠正失败的假设。
提前开始工作、停止失败尝试、引导恢复的能力,使更长的程序变得可行。急切执行、提前取消和可操作的错误结合在一起,构成了一种新颖且前沿的实时反馈 harness 设计方法。Agent 可以在单个程序中承担更大的工作流,而用户可以在模型编写代码时看到进展。更少的模型往返减少了重复的输入 token,生成和执行的重叠让工作更早开始,提前取消则在永远不会运行的代码上节省了时间和计费的输出 token。这让我们能够追求更宏大的程序,同时保持执行响应迅速、失败尝试成本低廉。
相关工作包括 Executing as You Generate,它将基于 AST 的急切执行应用于 Python。
由于流式代码执行保留了实时视觉更新,我们把树修改 API 重写为单独的方法调用。DSL 命令 INSERT 和 PATCH 变成了 tree.insert() 和 tree.patch(),并且可以使用对其他节点的引用作为值。
// "Clamp all opacity less than 50% to the opacity of this ("xxx") button" const button = tree.get("xxx") for (const node of tree.walk()) { if (node.opacity < 0.5) node.patch({ opacity: button.opacity })
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。