
cua-bench 环境脚手架实战用四个装饰器构建计算机使用 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/cuacua-bench 环境脚手架指南仓库中位于 drag-drop/CLAUDE.md定义了创建计算机使用Computer Use强化学习环境的统一编程模型用四个 Python 装饰器声明任务配置、环境搭建、求解与评估再用一份gui/index.html承载全部界面逻辑。读完本文你将掌握 cua-bench 任务环境从零搭建的完整流程理解env.step/env.bot/window.__next_move()之间的职责边界并能基于仓库中 13 个基础任务的真实代码独立编写可被run_benchmark批量运行的 RL 任务。一、环境脚手架的整体结构cua-bench 创建计算机使用 RL 环境的目录结构约定为两部分职责划分非常清晰task-folder/ ├── main.py # Python 装饰器承载全部任务逻辑 ├── gui/ │ └── index.html # HTML/CSS/JS 界面自动引入 Tailwind 与 Iconify ├── pyproject.toml # 项目元数据与依赖 └── CLAUDE.md # 脚手架开发文档其中main.py只负责「任务逻辑」gui/负责「界面与交互」。这一约定在 cua-bench-basic 数据集 的每个任务目录中保持一致——click-button、drag-slider、fill-form、right-click-menu、drag-drop等 13 个基础任务均遵循该结构。数据集的 README.md 将其归纳为main.py承载任务配置/搭建/评估/求解gui/index.html提供带 Tailwind 样式的界面CLAUDE.md为脚手架开发文档。二、四个核心装饰器任务环境的四段生命周期main.py中的全部逻辑通过四个装饰器声明它们按执行顺序覆盖了一个任务从定义到打分的完整生命周期。装饰器定义于 cua_bench/decorators.py统一导出在cua_bench命名空间下即代码中的cb。2.1cb.tasks_config声明任务与参数化变体tasks_config装饰的函数返回list[cb.Task]每个cb.Task包含两件事descriptionAI Agent 听到的任务描述例如 Play 2048、Book a hotelmetadata任务的参数化元数据难度、棋盘大小、操作系统等。return [cb.Task(descriptionPlay 2048, metadata{size: 4, os_type: linux})]从 cua_bench/core.py 可以看到Task的完整字段定义dataclass class Task: description: str task_id: Optional[str] None metadata: Optional[dict] None computer: Optional[dict] Nonemetadata是参数化的关键通道——通过枚举不同取值难度、尺寸、轮数、OS一个任务文件即可批量生成大量训练/评估变体。computer字段则允许在任务级别直接声明运行环境provider 与setup_config详见后文「环境生命周期」一节。2.2cb.setup_task搭建沙箱与启动窗口setup_task负责创建沙箱并启动 webview 窗口保持最小化——只做环境搭建global pid env.create_sandbox(providercomputer, setup_config{os_type: linux, width: 800, height: 600}) pid env.launch_window(htmlhtml_content, titleGame, width400, height400) # create webview window两点值得展开providercomputer是nativeprovider 的别名。在 cua_bench/computers/base.py 的get_session()中session 名统一走simulated别名webtop基于 Playwright 的浏览器模拟无需 Docker与native别名computerDocker/QEMU 中的真实桌面环境两条路径。launch_window是DesktopSession协议的标准接口完整签名见 base.py支持url、html、folder三种内容来源另有x/y、width/height默认 600×400、icon、use_inner_size、title_bar_style等窗口参数返回窗口进程 IDpid。在实际任务中也可以在Task.computer字段里直接声明环境由Environment.reset()自动完成沙箱创建见第四节。2.3cb.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(seconds1.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(xaction[x], yaction[y])) # x,y must be in screen coordinates (requires offsetting by window.screenX and window.screenY) elif action[type] type: env.step(TypeAction(textaction[text])) action env.execute_javascript(pid, window.__next_move()) env.step(DoneAction())该循环明确划分了三条职责边界这是整个脚手架最重要的设计约束只有env.step或env.bot能真正执行解决任务的动作env.execute_javascript只能执行返回「最优动作信息」的辅助函数如目标元素、或暴露了window.__next_move()的 AI 策略输出window.__next_move()只返回下一步动作绝不执行动作或修改环境/状态——它通常被solve_task循环调用直至任务解决实际动作统一交由env.step/env.bot落地。这一「策略与执行分离」的设计保证了轨迹数据中观察observation与动作action的干净边界便于训练与评估复用同一套任务。2.4cb.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 preferred2.5 装饰器背后的注册机制这四个装饰器并非简单标记而是把函数注册进全局环境注册表。源码 decorators.py 的实现要点每个装饰器都支持两种用法裸用cb.tasks_config或参数化cb.tasks_config(train)/cb.tasks_config(splittest)默认 split 为train被装饰的函数会被打上_td_typetasks_config/setup_task/solve_task/evaluate_task与_td_split两个属性Environment.make_from_module()遍历模块成员按_td_type与_td_split匹配当前 split 对应的四个函数组装出完整的Environment见 environment.py。也就是说你可以用同一份main.py同时定义train与test两套函数运行时按 split 自动选择数据泄漏风险从结构上被隔离。三、gui/ 目录界面即任务载体gui/index.html中所有游戏/任务逻辑都在这里HTML 会被渲染进一个内置 Tailwind Iconify 模板的桌面 webview 窗口内因此不要使用html或body标签直接写语义化内容即可。3.1 关键编写模式语义化 HTML ARIA 描述使用main、section、button、nav等语义元素并添加aria-label、aria-describedby、role属性既服务无障碍也让视觉模型/Agent 更容易识别元素。紧凑响应式设计使用最小化 padding/marginp-1、p-2、gap-1、gap-2布局需在弹窗尺寸300×200到全屏桌面之间自适应避免固定宽高优先min-h-0、overflow-auto保证视口缩小时关键元素仍可见。全局状态当前得分存入window.__scoreRL 奖励统一为 0.0–1.0 区间。AI 基线在 JavaScript 中实现 AI 策略通过window.__next_move()暴露。窗口填充根元素使用classflex h-full w-full填满整个窗口所有元素保持紧凑响应HTML 通常渲染在小尺寸桌面 webview 窗口或手机屏幕中。图标使用iconify-icon iconprefix:name/iconify-icon。3.2 以 drag-drop 任务为例一份完整的 gui/index.html仓库中 drag-drop/gui/index.html 是上述模式的真实落地。它用main包裹、根元素flex flex-col h-full w-full p-6 overflow-auto填充窗口rolemainaria-labelDrag and drop interface提供无障碍描述可拖拽物品与放置区分别用rolebuttonaria-labelApple item等与roleregionaria-labelFruits drop zone等标注为 Agent 的元素定位提供语义锚点。图标全部使用 Iconifyiconify-icon iconmdi:food-apple classtext-red-600 stylefont-size: 1.25rem/iconify-icon其 JavaScript 部分展示了「全局状态」与「AI 基线」的具体写法——用window.__dropResults {}记录每次投放结果供评估读取window.__dropResults {}; // ... zone.addEventListener(drop, function (e) { e.preventDefault(); if (draggedElement) { const itemName draggedElement.getAttribute(data-item); const targetName this.getAttribute(data-target); window.__dropResults[itemName] targetName; // 记录投放结果供 evaluate 读取 // ...将物品克隆进目标容器并隐藏原元素 } });四、Action 类型全集env.step()的可用动作脚手架定义了完整的动作类全部位于 cua_bench/types.py统一作为env.step(action)的参数鼠标动作ClickAction(x, y)RightClickAction(x, y)DoubleClickAction(x, y)DragAction(from_x, from_y, to_x, to_y, duration1.0)ScrollAction(directionup|down, amount100)键盘动作TypeAction(texthello)KeyAction(keyEnter)HotkeyAction(keys[ctrl, c])控制动作DoneAction()WaitAction(seconds1.0)types.py 中实际还定义了MiddleClickAction鼠标中键与MoveToAction(x, y, duration0.0)纯移动并导出Action联合类型供类型标注使用。env.step()的底层行为可在 environment.py 中看到每次 step 校验会话与max_steps步数预算超限抛MaxStepsExceeded、经session.execute_action()落地动作、截图并记录step:before/step:after轨迹事件、递增step_count最后返回截图。step还支持dry_runbefore|after用于只观察不执行的调试场景。五、env.bot更安全的元素级操作助手指南特别强调env.bot.click_element(pid, f#{action[element_id]})是「最安全的点击方式」。其实现位于 cua_bench/bot.pyBot通过 provider 的get_element_rect桥接层获取元素在屏幕坐标系中的矩形计算中心点后派发ClickAction/RightClickAction从而避免 Agent 手工估算像素坐标的误差def click_element(self, pid: int, selector: str) - None: rect self.env.get_element_rect(pid, selector, spacescreen) if not rect: raise RuntimeError(fElement not found for selector: {selector}) cx int(rect[x] rect[width] / 2) cy int(rect[y] rect[height] / 2) self.env.step(ClickAction(xcx, ycy))六、Iconify 图标界面图标统一使用iconify-icon元素支持可缩放矢量图标iconify-icon iconeva:people-outline/iconify-icon iconify-icon iconmingcute:ad-circle-line width24 height24/iconify-icon iconify-icon iconmdi:play classtext-blue-500 stylefont-size: 2rem;/iconify-icon图标会被自动处理并替换为内联 SVG支持所有 iconify 图标集eva、mingcute、mdi 等。drag-drop 任务的界面即使用了mdi:food-apple、mdi:carrot、mdi:fruit-citrus、mdi:fruit-grapes、mdi:corn、mdi:information等多组图标区分物品类别与提示信息。七、屏幕尺寸在setup_config中指定屏幕尺寸通过env.create_sandbox的setup_config参数或Task.computer.setup_config指定。脚手架在 cua_bench/types.py 中定义了完整的StandardScreenSize联合类型# --- Screen size options for desktop environments --- StandardScreenSize Union[ # Standard Desktop Resolutions tuple[Literal[1920], Literal[1080]], # Full HD (current default) tuple[Literal[1366], Literal[768]], # HD (laptop standard) tuple[Literal[2560], Literal[1440]], # 2K/QHD tuple[Literal[3840], Literal[2160]], # 4K/UHD tuple[Literal[1280], Literal[720]], # HD Ready tuple[Literal[1600], Literal[900]], # HD tuple[Literal[1920], Literal[1200]], # WUXGA tuple[Literal[2560], Literal[1600]], # WQXGA tuple[Literal[3440], Literal[1440]], # Ultrawide QHD tuple[Literal[5120], Literal[1440]], # Super Ultrawide # Mobile/Tablet Resolutions tuple[Literal[1024], Literal[768]], # iPad (portrait) tuple[Literal[768], Literal[1024]], # iPad (landscape) tuple[Literal[360], Literal[640]], # Mobile portrait tuple[Literal[640], Literal[360]], # Mobile landscape # Legacy Resolutions tuple[Literal[1024], Literal[600]], # Netbook tuple[Literal[800], Literal[600]], # SVGA tuple[Literal[640], Literal[480]], # VGA # Additional Common Resolutions tuple[Literal[1440], Literal[900]], # Custom laptop tuple[Literal[1680], Literal[1050]], # WSXGA tuple[Literal[1920], Literal[1440]], # Custom 4:3 ratio tuple[Literal[2560], Literal[1080]], # Ultrawide Full HD tuple[Literal[3440], Literal[1440]], # Ultrawide QHD tuple[Literal[3840], Literal[1080]], # Super Ultrawide Full HD ]选择屏幕尺寸时遵循两条原则选择与任务和环境匹配的尺寸桌面环境默认 1920×1080Full HD移动端任务可选用 360×640 等竖屏尺寸。DesktopSetupConfig见 computers/base.py还支持更丰富的配置字段os_typewin11/win10/macos/linux/android等、background、wallpaper、installed_apps以及 Docker/VM 相关的image、storage、memory、cpu、provider_typedocker/lume/cloud。八、完整实战drag-drop 任务的 main.py 剖析仓库中 drag-drop/main.py 是一个可运行的完整范本将前面所有概念串联在一起。① 任务配置与变体生成tasks_config定义 5 种拖放场景Apple→Fruits、Carrot→Vegetables、Banana→Fruits、Broccoli→Vegetables、Orange→Fruits并枚举os_types [linux]通过列表推导生成 5 个变体每个变体的description与metadataitem、target、item_label、target_label各不相同且直接通过computer字段声明providernative与setup_config1024×768、灰色背景#c0c0c0cb.tasks_config(splittrain) def load(): os_types [linux] # [macos, win11, win10] drag_scenarios [ {item: apple, target: fruit, item_label: Apple, target_label: Fruits, description: Drag the Apple to the Fruits box}, # ...更多场景 ] return [ cb.Task( descriptionscenario[description] ., metadata{...}, computer{ provider: native, setup_config: { os_type: os_type, width: 1024, height: 768, background: #c0c0c0, }, }, ) for os_type in os_types for scenario in drag_scenarios ]② 环境搭建setup_task读取同目录gui/index.html文本并启动 600×500 的 webview 窗口cb.setup_task(splittrain) 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), titleDrag and Drop Task, width600, height500, )③ 求解solve_task用execute_javascript读取物品与目标框的屏幕坐标注意代码中itemRect.left window.screenX的偏移处理与指南「所有 x,y 均为屏幕坐标需用window.screenX/screenY计算浏览器视口到屏幕左上角的偏移」完全对应再用DragAction一次拖拽到位cb.solve_task(splittrain) async def solve(task_cfg: cb.Task, session: cb.DesktopSession): global pid coords await session.execute_javascript(pid, f ... 读取 item/target 矩形中心并加 window.screenX/screenY ... ) await session.execute_action( cb.DragAction( from_xcoords[item_x], from_ycoords[item_y], to_xcoords[target_x], to_ycoords[target_y], duration0.5, ) )④ 评估evaluate_task读取window.__dropResults判定物品是否落入了正确分类返回1.0或0.0的稀疏奖励cb.evaluate_task(splittrain) async def evaluate(task_cfg: cb.Task, session: cb.DesktopSession) - list[float]: global pid drop_results await session.execute_javascript(pid, window.__dropResults) if drop_results is None: return [0.0] item task_cfg.metadata[item] target task_cfg.metadata[target] item_location drop_results.get(item) return [1.0] if item_location target else [0.0]文件末尾的cb.interact(__file__)是本地交互式调试入口实现在 core.py以非 headless 模式加载环境、执行 setup、等待用户回车后打印评估结果。九、环境生命周期从 reset 到 evaluate 的源码视角Environmentenvironment.py是整个运行时的核心。关键调用链如下make(env_path)core.py通过importlib动态加载任务的main.py模块再经make_from_module按 split 匹配四个装饰器函数构建Environment实例env.reset(task_id)负责生命周期前置关闭旧会话、重置步数计数器、惰性加载tasks_config结果、根据Task.computer自动调用create_sandbox(provider, setup_config)随后调用setup_task并截图、记录reset轨迹事件env.step(action)执行单步动作并截图返回见第四节env.solve()调用solve_task捕获MaxStepsExceeded优雅终止env.evaluate()调用evaluate_task返回奖励并记录evaluate轨迹事件与遥测数据。值得注意create_sandbox也可以在setup_task内直接调用脚手架指南示例的写法而reset()会自动从Task.computer读取并创建——两种方式等价但推荐后者因为环境声明与任务变体绑定天然支持「一个文件批量变体、每个变体不同的 OS/分辨率」。十、运行与批量验证数据集的 README.md 给出了交互式运行方式# 运行单个任务交互式 python -m cua_bench.interact task-folder/main.py # 示例 python -m cua_bench.interact click-button/main.py如果要在程序中批量运行cua_bench/runners.py 提供了三组高阶接口run_single_task(env_path, task_index, split, agent_fn, max_steps100, oracleFalse)按 gym 接口make→reset→step→evaluate运行单个任务变体oracleTrue时调用solve_task验证任务自身可解性agent_fn模式则注入外部 Agent 循环奖励 ≥ 0.5 判定成功run_benchmark(dataset_path, agent_fn, max_steps100, max_parallel4, oracleFalse, task_filterNone)自动发现数据集下所有含main.py的任务目录、展开全部参数化变体用asyncio.Semaphore控制并发汇总BenchmarkResult含success_count、avg_reward、duration_seconds——这是验证新任务脚手架是否合格的关键工具先用oracleTrue确认任务可解再接入真实 Agent 评测run_interactive(env_path, task_index, headlessFalse)返回(env, screenshot, task_cfg)三元组供脚本内交互控制。十一、最佳实践清单综合脚手架指南与源码实现编写高质量任务环境时应遵守main.py保持最小化——只放装饰器与基本逻辑环境搭建、任务加载AI 策略全部放gui/的 JavaScript 中通过window.__next_move()暴露奖励统一用window.__score0.0–1.0 区间便于跨任务横向对比与 RL 训练通过 Task metadata 参数化变体难度、尺寸、OS、轮数一份main.py产出整个变体矩阵谨慎使用WaitAction——仅当任务确实需要如等待页面加载或等待下一步动作就绪时使用env.bot助手自带可操作性判断等待元素可点击会自动向前推进环境所有 x,y 均为屏幕坐标0,0 为屏幕左上角计算浏览器内元素坐标时必须用window.screenX/window.screenY加上视口到屏幕的偏移选择与任务、环境匹配的屏幕尺寸桌面任务默认 1920×1080移动端任务选 360×640 等保持window.__next_move()纯净——只返回下一步动作、不执行动作、不修改状态把执行权完整交给env.step/env.bot。遵循这套脚手架约定你可以在 cua-bench 中快速沉淀可训练、可评估、可复用的计算机使用任务并为 cua-bench-basic 这样的基础交互任务集持续贡献新的环境。【免费下载链接】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),仅供参考