基于 cua-bench 搭建 Computer-Use RL 环境:从脚手架指南到 spreadsheet-cell 任务实战
【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua
本篇技术指南以libs/cua-bench/datasets/cua-bench-basic/spreadsheet-cell/CLAUDE.md(cua-bench 环境脚手架指南)为骨架,结合该任务目录下的真实源码展开,系统讲解如何利用 cua-bench 的四个核心装饰器(tasks_config/setup_task/solve_task/evaluate_task)构建可供训练、评估与数据生成使用的 Computer-Use 强化学习环境。读完本文,你将掌握 cua-bench 任务环境的完整编写范式:如何定义任务参数、启动沙箱与 WebView、编写带 AI 基线的 GUI、通过env.step/env.bot执行动作闭环,以及如何用window.__score与window.__cellData类全局状态完成 RL 奖励反馈。
cua-bench 环境结构总览
cua-bench(位于 libs/cua-bench)是一个面向 Computer-Use 的 RL 环境与评测框架,每个任务环境的标准结构如下:
main.py:Python 装饰器定义任务逻辑(加载任务、环境搭建、求解、评估);gui/:HTML/CSS/JS 实现的界面,自动引入 Tailwind 与 Iconify 图标;pyproject.toml:项目元数据与依赖声明;CLAUDE.md:本任务目录内的 cua-bench 脚手架文档,即本指南的源文档。
以spreadsheet-cell任务(向电子表格单元格输入数据)为例,其目录结构为:
libs/cua-bench/datasets/cua-bench-basic/spreadsheet-cell/ ├── gui/ │ └── index.html # 电子表格界面(Tailwind + 语义 HTML + 全局状态) ├── CLAUDE.md # 环境脚手架指南 ├── main.py # 四个装饰器定义的任务生命周期 └── pyproject.toml # 项目元数据与依赖该任务所属的cua-bench-basic数据集(libs/cua-bench/datasets/cua-bench-basic/README.md)覆盖了按钮点击、表单填写、下拉选择、拖拽、滑块、日期选择等 13 类基础 UI 交互基准任务,spreadsheet-cell对应其中"Text & Input"类别,用于评估智能体将文本精准输入到指定单元格的 grounding 能力。
四个核心装饰器:任务生命周期的骨架
main.py通过四个装饰器定义任务的完整生命周期。它们的底层实现位于 libs/cua-bench/cua_bench/decorators.py,每个装饰器都会将包装后的函数注册进按环境路径索引的_env_registry(键为tasks_config/setup_task/solve_task/evaluate_task),并通过_td_type与_td_split属性标注函数类型与数据划分。装饰器支持两种用法:裸用@cb.tasks_config或参数化@cb.tasks_config("train")/@cb.tasks_config(split="train"),默认 split 为"train"。
@cb.tasks_config:声明任务与参数化变体
tasks_config装饰的函数返回list[cb.Task]。其中description是 AI 智能体听到的任务指令(如 "Play 2048"、"Book a hotel"),metadata存放任务参数(难度、游戏尺寸、操作系统等),供 setup / solve / evaluate 三个阶段读取。
spreadsheet-cell的 main.py 演示了用场景列表参数化生成多个任务变体的写法:
@cb.tasks_config(split="train") def load(): os_types = ["linux"] # ["macos", "win11", "win10"] # Different spreadsheet cell entry scenarios cell_scenarios = [ {"cell": "A1", "value": "Product", "description": 'Enter "Product" into cell A1'}, {"cell": "B2", "value": "150", "description": 'Enter "150" into cell B2'}, {"cell": "C3", "value": "=SUM(A1:A10)", "description": 'Enter "=SUM(A1:A10)" into cell C3'}, { "cell": "D4", "value": "Total Revenue", "description": 'Enter "Total Revenue" into cell D4', }, {"cell": "A5", "value": "42.50", "description": 'Enter "42.50" into cell A5'}, ] return [ cb.Task( description=scenario["description"] + ".", metadata={ "cell": scenario["cell"], "value": scenario["value"], }, computer={ "provider": "native", "setup_config": { "os_type": os_type, "width": 1024, "height": 768, "background": "#c0c0c0", }, }, ) for os_type in os_types for scenario in cell_scenarios ]值得注意的实战要点:
- 通过
for os_type in os_types for scenario in cell_scenarios的双重循环,一条任务定义即可批量生成 1×5=5 个变体;扩展os_types即可横向覆盖多操作系统。 metadata中的cell与value是后续求解与评估阶段的"答案参照",体现了"参数化变体"的最佳实践。computer字段配置运行环境:provider: "native"指定原生桌面驱动,setup_config中的os_type、width、height、background(此处为灰色桌面背景#c0c0c0)共同决定沙箱外观。- 任务元数据在
pyproject.toml的[tool.cua-bench]中声明:description = "basic spreadsheet cell entry task"、difficulty = "easy"、category = "grounding",与代码注释中的类别划分一致。
@cb.setup_task:搭建沙箱与启动 WebView
setup_task负责创建沙箱并启动 webview 窗口,应保持最小化——只做环境搭建。指南中的原型示例:
global pid env.create_sandbox(provider="computer", setup_config={"os_type": "linux", "width": 800, "height": 600}) pid = env.launch_window(html=html_content, title="Game", width=400, height=400) # create webview windowspreadsheet-cell的真实实现(main.py)使用异步DesktopSessionAPI,直接读取同目录gui/index.html的内容渲染窗口:
pid = None @cb.setup_task(split="train") async def start(task_cfg: cb.Task, session: cb.DesktopSession): global pid pid = await session.launch_window( html=(Path(__file__).parent / "gui/index.html").read_text("utf-8"), title="Spreadsheet Task", width=700, height=500, )关键点:launch_window的width/height(700×500)是 webview 窗口尺寸,与沙箱屏幕尺寸(1024×768)相互独立,二者共同决定了智能体"看到"的界面。代码注释明确标注了"All code below will be running in a separate process per task",即每个任务实例在独立进程中运行,pid作为模块级全局变量在阶段间传递窗口句柄。
@cb.solve_task:执行动作闭环
solve_task从 GUI 的 AI 基线获取下一步动作,并用env.step或env.bot执行。指南给出了标准的动作分派循环:
global pid action = env.execute_javascript(pid, "window.__next_move()") while action is not None and action["type"] != "done": if not action or action["type"] == "wait": env.step(WaitAction(seconds=1.0)) elif action["type"] == "click_element": env.bot.click_element(pid, f"#{action['element_id']}") # safest way to click an element elif action["type"] == "click_absolute": env.step(ClickAction(x=action["x"], y=action["y"])) # x,y must be in screen coordinates (requires offsetting by window.screenX and window.screenY) elif action["type"] == "type": env.step(TypeAction(text=action["text"])) action = env.execute_javascript(pid, "window.__next_move()") env.step(DoneAction())spreadsheet-cell的求解实现(main.py)展示了无 AI 基线的"硬编码参考解"写法,三步完成"点击单元格 → 输入值 → 回车确认":
@cb.solve_task(split="train") async def solve(task_cfg: cb.Task, session: cb.DesktopSession): global pid target_cell = task_cfg.metadata["cell"] await session.click_element(pid, f"#cell-{target_cell}") await session.execute_action(cb.TypeAction(text=task_cfg.metadata["value"])) await session.execute_action(cb.KeyAction(key="Return"))这里#cell-{target_cell}直接对应gui/index.html中每个输入框的id="cell-A1"这类元素标识。三种解法路径对比:
env.bot.click_element(pid, selector):最安全的元素点击方式,内部带 actionability 逻辑(自动等待元素可点击),适合带语义 id 的页面元素;env.step(ClickAction(x, y)):绝对屏幕坐标点击,坐标原点在屏幕左上角,浏览器视口内需用window.screenX/window.screenY换算偏移;session.execute_action(...):spreadsheet-cell 采用的会话级动作执行入口,配合TypeAction与KeyAction完成文本输入与回车确认。
@cb.evaluate_task:从 GUI 状态提取奖励
evaluate_task返回奖励列表,RL 场景优先使用 0.0–1.0 区间。指南原型:
global pid score = env.execute_javascript(pid, "window.__score") return [float(score)] # 0.0-1.0 range preferredspreadsheet-cell的评估实现(main.py)不依赖window.__score标量,而是从全局状态window.__cellData精确比对目标单元格:
@cb.evaluate_task(split="train") async def evaluate(task_cfg: cb.Task, session: cb.DesktopSession) -> list[float]: global pid cell_data = await session.execute_javascript(pid, "window.__cellData") if cell_data is None: return [0.0] target_cell = task_cfg.metadata["cell"] expected_value = task_cfg.metadata["value"] actual_value = cell_data.get(target_cell) return [1.0] if actual_value == expected_value else [0.0]该实现的评估语义:window.__cellData为空返回 0.0(未产生任何输入);metadata["cell"]指定格的值与期望值精确相等才给 1.0,否则 0.0。这种"二进制奖励"是 grounding 类任务(单元格定位 + 文本输入)的典型度量方式——比宽松的部分匹配更能暴露定位与输入的精确性问题。
GUI 编写规范:语义化、响应式与全局状态
gui/目录承载全部任务逻辑。HTML 会在 Tailwind + Iconify 模板中渲染到桌面 webview 窗口内,不要使用<html>或<body>标签,根元素直接使用语义标签。spreadsheet-cell的 gui/index.html 是这份规范的完整范例。
语义 HTML 与 ARIA
指南要求使用<main>、<section>、<button>、<nav>等语义元素,并添加aria-label、aria-describedby、role属性,既保证可访问性,也帮助视觉模型/Agent 更好地识别元素。范例实现:
<main class="flex flex-col h-full w-full p-4 overflow-auto" role="main" aria-label="Spreadsheet interface" >每个单元格输入框都带有可定位的语义标识:
cellInput.type = 'text'; cellInput.id = 'cell-' + cellId; cellInput.setAttribute('aria-label', 'Cell ' + cellId); cellInput.setAttribute('data-cell', cellId);id="cell-A1"正是solve_task中session.click_element(pid, "#cell-A1")的选择器来源,aria-label="Cell A1"则服务于基于语义标签的 Agent 定位。
响应式与紧凑布局
指南强调:使用紧凑 padding/margin(p-1、p-2、gap-1、gap-2),布局需从弹窗尺寸(300×200)到全桌面均可工作;避免固定宽高,使用min-h-0、overflow-auto,保证视口缩小时关键元素仍可见;根元素用class="flex h-full w-full"填满整个窗口。范例中根容器使用flex flex-col h-full w-full p-4 overflow-auto,表格行由 JavaScript 按grid grid-cols-5生成,天然适配不同宽度。
全局状态:RL 奖励的桥接通道
指南约定:
window.__score:保存当前得分(RL 奖励使用 0.0–1.0 区间);window.__next_move():在 JavaScript 中实现的 AI 策略,暴露给solve_task循环调用,只返回下一个动作、绝不执行动作或修改环境状态;- 二者(以及任意自定义全局状态)由
env.execute_javascript在 Python 与 GUI 之间桥接。
spreadsheet-cell用window.__cellData字典替代标量分数作为评估状态,blur、Enter、input 三个事件统一维护:
window.__cellData = {}; // focus: 高亮父容器(ring-2 ring-blue-500) // blur: 保存 this.value.trim() 到 __cellData[cellId],空值则 delete // Enter: 保存值并 this.blur() // input: 实时同步 __cellData图标与界面提示
图标统一使用<iconify-icon>元素,渲染时自动替换为内联 SVG,支持全部 iconify 图标集(eva、mingcute、mdi 等)。spreadsheet-cell在操作提示条中使用了mdi:information图标并配以text-blue-600颜色类:
<iconify-icon icon="mdi:information" class="text-blue-600"></iconify-icon>同时界面底部给出了面向智能体的明确操作引导文案:"Click a cell to select it, then type to enter data. Press Enter to confirm."——这类内嵌提示能显著提升 Agent 对任务完成条件的理解。
动作类型参考
env.step()支持的动作类定义于 libs/cua-bench/cua_bench/actions.py 并由 libs/cua-bench/cua_bench/types.py 导出,分为三类:
鼠标动作:
ClickAction(x, y)— 左键单击RightClickAction(x, y)— 右键单击DoubleClickAction(x, y)— 双击DragAction(from_x, from_y, to_x, to_y, duration=1.0)— 拖拽ScrollAction(direction="up|down", amount=100)— 滚动
键盘动作:
TypeAction(text="hello")— 输入文本KeyAction(key="Enter")— 按键HotkeyAction(keys=["ctrl", "c"])— 组合键
控制动作:
DoneAction()— 宣告任务完成WaitAction(seconds=1.0)— 等待
源码细节:actions.py还提供了两套文本解析器——repr_to_action解析ClickAction(x=100, y=200)形式的 repr 字符串,snake_case_to_action解析click(0.5, 0.5)、type("hello")形式的指令文本(坐标支持整数与浮点数,整数值自动转 int)。这意味着除直接构造动作对象外,Agent 也可输出动作描述字符串交由框架解析,动作类型还额外支持MiddleClickAction、MoveToAction等。
屏幕尺寸:setup_config 的关键参数
屏幕尺寸在env.create_sandbox的setup_config参数中指定。spreadsheet-cell使用 1024×768,而指南完整列出了 cua-bench 支持的全部标准分辨率(当前默认 1920×1080):
| 分类 | 分辨率 | 说明 |
|---|---|---|
| 桌面标准 | 1920×1080 | Full HD(当前默认) |
| 桌面标准 | 1366×768 | HD(笔记本标准) |
| 桌面标准 | 2560×1440 | 2K/QHD |
| 桌面标准 | 3840×2160 | 4K/UHD |
| 桌面标准 | 1280×720 | HD Ready |
| 桌面标准 | 1600×900 | HD+ |
| 桌面标准 | 1920×1200 | WUXGA |
| 桌面标准 | 2560×1600 | WQXGA |
| 桌面标准 | 3440×1440 | Ultrawide QHD |
| 桌面标准 | 5120×1440 | Super Ultrawide |
| 移动/平板 | 1024×768 | iPad(竖屏) |
| 移动/平板 | 768×1024 | iPad(横屏) |
| 移动/平板 | 360×640 | 手机竖屏 |
| 移动/平板 | 640×360 | 手机横屏 |
| 传统 | 1024×600 | Netbook |
| 传统 | 800×600 | SVGA |
| 传统 | 640×480 | VGA |
| 其他常见 | 1440×900 / 1680×1050 / 1920×1440 / 2560×1080 / 3440×1440 / 3840×1080 | 定制笔记本、WSXGA+、4:3 及超宽屏 |
实战建议:选择与任务真实场景匹配的屏幕尺寸——桌面办公类任务用 1920×1080 或 1366×768,移动端任务用 360×640 系列;窗口内布局需保证在目标尺寸下无溢出。注意setup_config中同时存在width/height(沙箱屏幕)与launch_window的width/height(webview 窗口)两套尺寸,需分别设置。
最佳实践与常见陷阱
综合指南与源码,编写 cua-bench 任务环境时应遵循:
- 保持
main.py最小化:只写装饰器与基础逻辑(环境搭建、任务加载),游戏/任务逻辑全部放入gui/的 JavaScript 中。 - AI 策略放 GUI 侧:通过
window.__next_move()暴露;该函数只返回下一个动作,不执行任何动作、不修改环境状态,实际执行一律交给env.step/env.bot(在solve_task中循环调用直至任务解决)。 - 奖励走全局状态:用
window.__score(0.0–1.0 区间)或自定义状态(如window.__cellData)承载 RL 奖励所需数据。 - 参数化变体:用 Task metadata 参数化难度、尺寸、OS、轮数等,一次声明批量生成变体。
- 慎用
WaitAction:除非任务确实需要(如等待页面加载、等待下一个动作可用),否则优先依赖env.bot内置的 actionability 逻辑(自动等待元素可点击),减少无谓等待。 - 坐标换算:所有
x,y均为屏幕坐标,原点在屏幕左上角;浏览器视口坐标需用window.screenX/window.screenY换算偏移。 - 按需选择屏幕尺寸:选择与任务和环境匹配的分辨率,桌面任务避免过小窗口,移动任务避免桌面分辨率。
- GUI 可访问性:语义标签 +
aria-label+ 明确的提示文案(如界面中的操作说明条),既能提升真实可用性,也显著改善视觉模型与 Agent 的元素识别成功率。
运行与验证
单个任务可交互式运行(libs/cua-bench/datasets/cua-bench-basic/README.md):
# 运行 cua-bench 基础任务(交互式) python -m cua_bench.interact spreadsheet-cell/main.pymain.py末尾的if __name__ == "__main__": cb.interact(__file__)提供了同一入口。cua-bench 框架的完整入口、批处理与训练管线可继续查看 libs/cua-bench/cua_bench 下的cli/、runner/、trainer/等子模块,以及基准任务数据集 libs/cua-bench/datasets/cua-bench-basic(含 click-button、fill-form、drag-drop 等 13 类任务)与其他任务库 libs/cua-bench/datasets/cua-bench-kicad、libs/cua-bench/datasets/cua-bench-workflows,均遵循本文所述的同一脚手架规范。
小结:spreadsheet-cell是理解 cua-bench 任务环境脚手架的最小完整样本——tasks_config用双重循环参数化 5 个变体,setup_task启动 700×500 的 WebView,solve_task以"点击#cell-{cell}→ 输入值 → 回车"三步参考解执行,evaluate_task通过window.__cellData精确比对给出 0/1 奖励。掌握这四个装饰器与 GUI 全局状态约定,即可按同一模式为任意 Computer-Use 交互场景(表单、表格、编辑器、多媒体控制等)搭建可用于 RL 训练、基准评测与轨迹数据生成的环境。
【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考