04 · 巧妙之处、边界与代码地图
前三章讲「怎么转」,这一章讲「妙在哪、崩在哪、跟别人比怎样」,最后给一张可直接 grep 跳源码的地图。
4.1 巧妙之处(可借鉴的技术)
① 执行式校验,把「信任」从模型移到文件系统。 判分不解析 agent 的自然语言,只进真机读真实产物再比对(desktop_env.py:458 evaluate;metrics/table.py:260 compare_table)。妙在它从根上免疫「模型口头声称完成」的幻觉——这也是 OSWorld 相对纯 LLM-judge 基准最硬的区别。
② 任务是数据不是代码。 一道题 = 一个声明式 JSON(instruction + config + evaluator),加题不用改引擎,只用写 JSON(evaluation_examples/examples/**/*.json)。369 道题因此能被非工程贡献者扩充。
③ host/guest 彻底分离,只靠 HTTP 说话。 编排逻辑在 host(Python),执行发生在 guest(VM 里的 Flask,server/main.py)。好处:同一套 agent/评测代码,底层 VM 换成 vmware/docker/aws 全不用动(providers/base.py 抽象 + providers/__init__.py:4 工厂)。
④ 反射式扩展点,约定优于配置。 setup 动作按 _{type}_setup 反射(setup.py:92)、getter 按 get_{type} 反射(desktop_env.py:385)、metric 按名字 getattr(desktop_env.py:380)。想加一种初始化/取证/判分,只要按命名约定加个函数,JSON 里写上名字即可,引擎零改动。
⑤ 「用过才回滚」省云成本。 用 is_environment_used 标志区分脏/净环境,只有真被弄脏才付回滚快照的代价(desktop_env.py:155-160,298)——针对 AWS 这类回滚昂贵的后端的实在优化。
⑥ 把超时兜底权留给最外层。 agent 的 call_llm 退避重试里禁止捕获通用 Exception(agent.py:548),确保「每题不超时」这条铁律由外层统一保证,不被内层无限重试架空。
⑦ 脏观测的魔数防御。 取截图时校验 PNG/JPEG 文件头再决定是否重试(python.py:83 _is_valid_image_response),挡住真机偶发的坏图。
4.2 边界与局限(诚实)
| 局限 | 说明 | 依据 |
|---|---|---|
| 逐步无奖励 | step 的 reward 恒 0、done 恒 False,只有终局 evaluate 给分;不适合逐步 reward 的 RL | desktop_env.py:423-424(旁注 todo) |
| 判分器是「按题手写规则」 | 每类任务的 metric 各写各的比对逻辑,覆盖面靠人力堆;新软件/新任务型态要新写 metric | evaluators/metrics/*.py |
| 重度依赖真机稳定性 | 全链路 HTTP + 真软件,慢且脆;主循环里散布 sleep(60)/sleep(20) 等界面稳定 | lib_run_single.py:26,64 |
| guest 端零安全检查 | /execute 直接 subprocess.run,注释明说无任何防护——只因 VM 是可弃靶场,别拿去跑不可信外部输入 | server/main.py:92 |
| 无障碍树可能不全/被截断 | a11y 树按 token 硬截到 a11y_tree_max_tokens,长界面尾部信息丢失 | agent.py:217 trim_accessibility_tree |
| 平台完成度不均 | Linux(AT-SPI) 最完整;macOS 构树里带 TODO: Add Dock and MenuBar | server/main.py:933(get_accessibility_tree 的 Darwin 分支注释) |
4.3 横向对比(同 shelf / 同领域的取舍)
OSWorld 属于 evals-observability 里的「computer-use / GUI agent 基准」一支,几条关键取舍:
| 维度 | OSWorld 的选择 | 换一种做法会怎样 |
|---|---|---|
| 环境 真实度 | 真操作系统 + 真软件(VM) | 网页沙箱(WebArena)/模拟器:更快更稳,但离真实桌面远 |
| 判分方式 | 执行式(读真实文件/状态) | LLM-judge/文本匹配:易实现,但会被自述与幻觉污染 |
| 任务表达 | 声明式 JSON + 反射扩展 | 每题写 Python:灵活但扩题门槛高 |
| 观测 | 截图 + 跨平台无障碍树(含 SoM) | 只给截图:更贴近人,但视觉定位更难 |
| 后端 | 多 provider(本地到多家云) | 绑死单一虚拟化:省事但难并行扩规模 |
一句话定位:OSWorld 用「真机 + 执行式校验」换来了最强的可信度,代价是慢、脆、判分器要人力堆规则。
4.4 代码地图(导航索引)
三列表,符号名可直接 grep 定位(比行号抗漂移)。
| 主题 | 文件 | 符号名 |
|---|---|---|
| gym 环境主体 | desktop_env/desktop_env.py | DesktopEnv |
| reset:回滚+布置初始状态 | desktop_env/desktop_env.py | DesktopEnv.reset / _revert_to_snapshot |
| step:执行动作 | desktop_env/desktop_env.py | DesktopEnv.step |
| 观测组装 | desktop_env/desktop_env.py | DesktopEnv._get_obs |
| 判分入 口 | desktop_env/desktop_env.py | DesktopEnv.evaluate |
| evaluator 反射装配 | desktop_env/desktop_env.py | DesktopEnv._set_evaluator_info |
| host→guest HTTP 客户端 | desktop_env/controllers/python.py | PythonController |
| pyautogui 导库前缀 | desktop_env/controllers/python.py | PYAUTOGUI_PKGS_PREFIX |
| computer_13 动作分派 | desktop_env/controllers/python.py | PythonController.execute_action |
| 截图魔数校验 | desktop_env/controllers/python.py | _is_valid_image_response |
| 声明式 setup 分派 | desktop_env/controllers/setup.py | SetupController.setup |
| 初始文件下载(带缓存) | desktop_env/controllers/setup.py | _download_setup |
| guest:无防护执行命令 | desktop_env/server/main.py | execute_command |
| guest:抓无障碍树(三平台) | desktop_env/server/main.py | get_accessibility_tree / _create_atspi_node |
| guest:跑整段脚本 | desktop_env/server/main.py | run_python |
| provider/manager 抽象 | desktop_env/providers/base.py | Provider / VMManager |
| provider 工厂 | desktop_env/providers/__init__.py | create_vm_manager_and_provider |
| 参考 agent | mm_agents/agent.py | PromptAgent |
| 拼 prompt 调模型 | mm_agents/agent.py | PromptAgent.predict / call_llm |
| 无障碍树线性化/截断 | mm_agents/agent.py | linearize_accessibility_tree / trim_accessibility_tree |
| SoM 打标 | mm_agents/agent.py | tag_screenshot |
| 解析模型输出 | mm_agents/agent.py | parse_code_from_string / parse_actions_from_string |
| 系统提示词(6+1 份) | mm_agents/prompts.py | SYS_PROMPT_IN_* / ACTION_SPACE |
| 单题主循环 | lib_run_single.py | run_single_example |
| 单进程实验入口 | run.py | test / get_unfinished |
| 并行实验入口 | scripts/python/run_multienv.py | run_env_tasks / distribute_tasks |
| 执行式判分:表格 | desktop_env/evaluators/metrics/table.py | compare_table / compare_csv |
| 取证:VM 文件/命令 | desktop_env/evaluators/getters/file.py,general.py | get_vm_file / get_vm_command_line |
| 任务清单/样例 | evaluation_examples/ | test_all.json / examples/<domain>/<id>.json |
想从零跟一遍,推荐路径:
quickstart.py→DesktopEnv.reset/step(01 章)→PromptAgent.predict(02 章)→DesktopEnv.evaluate+ 某个compare_*(03 章)。