https://arxiv.org/pdf/2509.02544
想象一下,你想让 AI 帮你:
这些任务有个共同特点:需要多步操作、需要看屏幕、需要根据反馈调整策略。这就是 GUI Agent 要干的事儿。
但现有方案有几个大坑:
UI-TARS-2 就是奔着这四个问题去的。
核心思想: 模型和数据互相喂养,越滚越大。
一开始得有种子数据:
注意:Agent 数据只占一小部分,大头还是通用数据(聊天、推理等),目的是保留模型的通用能力。
训练完第一轮 RL 模型后,用它来生成新数据:
展开代码新数据 = rejection sampling (RFT) + interactive annotation
然后用一个验证模型 V(s) 给每条数据打分:
V(s)=1): 扔进下一轮 SFTV(s)=0): 扔进下一轮 CT (让模型见见世面)这样形成正反馈循环:
展开代码更好的模型 → 更多高质量数据 → 更更好的模型
而且没有数据浪费,低质量数据也能用来做 CT。
训练 Agent 需要一个能跑得动、跑得稳的环境。UI-TARS-2 搞了两套:
技术细节:
python展开代码# 伪代码示意
vm = VMManager.allocate(os="ubuntu")
vm.execute_gui_action("click", x=100, y=200)
vm.execute_shell("cat downloaded_file.txt | grep keyword")

为什么要单独搞游戏环境? 因为:
黑科技: 重新实现了浏览器的 Window.setTimeout 等 API,可以暂停/加速游戏时间,同时不改变游戏逻辑。
问题: 之前的数据只有 action,没有 reasoning (思考过程),导致模型只会模仿,不理解为什么这么做。
解决方案: Think-Aloud Protocol (边想边说)
举个例子:
展开代码[标注员操作] 点击搜索框 [录音转文字] "我现在要搜三体,先得点这个搜索框" [LLM 润色] "为了完成任务,首先需要在搜索框中输入关键词'三体'"
还有个妙招:让新手标注员做不会的任务。新手会搜索、试错、查资料,这些过程都是宝贵的训练数据。
问题: 传统标注是 off-policy 的,标注员的操作和模型的操作分布不一样,训练效果差。
解决方案: Human-in-the-Loop (人在回路里)

流程:
关键优势: 标注数据和模型实际 rollout 的分布一致 (on-policy),而且标注员能实时纠错。
RL 需要大量任务 + 可靠的奖励信号。他们设计了三类任务:
目标: 让模型学会通过网页搜索、推理来回答复杂问题。
任务生成方法 1: 多条件模糊化
从维基百科抽取实体 (比如一个乐队),然后故意"脱敏":
展开代码原始信息: - 乐队: AC/DC - 成员来自: Dreghorn 和 Irvine - 签约唱片公司: Atlantic Records 生成问题: "被某人才机构发现,最初阵容包括来自 Dreghorn 和 Irvine 的成员, 主唱是创始成员推荐的。这个乐队签的是哪家唱片公司?" 答案: Atlantic Records
关键:无法直接搜索,必须多步推理。
任务生成方法 2: 多跳链式条件
递归构造推理链:
展开代码问题: "完成某 20 世纪航天计划的指令舱驾驶员毕业的大学, 校园里以他命名的工程楼叫什么?" 推理链: 1. 某航天计划 → 阿波罗 11 号 2. 指令舱驾驶员 → Michael Collins 3. 毕业大学 → 西点军校 4. 以他命名的工程楼 → (搜索答案)
直接从真实网站抽取功能,合成任务:
展开代码"访问京东,搜索'三体',找到刘慈欣著、价格<50元的纸质书,加入购物车"
过滤掉:
收集/生成小游戏,写 JS 验证脚本:
javascript展开代码// 验证脚本示例
function verify_game_state() {
return {
score: game.score,
level: game.level,
success: game.score > 1000
};
}
为什么要训游戏? 游戏是最好的长周期决策训练场,而且能自动生成无限任务。
两种情况:
python展开代码# LLM-as-Judge 伪代码
def evaluate(model_answer, ground_truth):
prompt = f"模型答案:{model_answer}\n标准答案:{ground_truth}\n是否正确?(是/否)"
return llm(prompt) == "是"
问题: 网页操作任务往往没有唯一答案,怎么判断对错?
解决方案: 训练一个专门的 Outcome Reward Model (ORM)
有意思的发现:即使 ORM 有 16% 的错误率,RL 照样能训好。为啥? 因为就算最终任务失败,中间步骤可能是对的,模型还是能学到东西。

三个关键设计:
传统方式:
python展开代码for task in tasks:
trajectory = model.rollout(task) # 阻塞等待
train(trajectory) # 训练
问题:长尾任务 (比如 1000 步的游戏) 会卡住整个训练流程。
新方式:
python展开代码# 伪代码
rollout_pool = []
for task in tasks:
async_start(model.rollout, task) # 异步启动
while True:
if len(rollout_pool) >= min_batch_size:
train(rollout_pool) # 够一个 batch 就训练
rollout_pool = [未完成的轨迹] # 未完成的留着
效果: 不用等所有任务都跑完,够一个 batch 就可以开始训练。
传统 RL 环境每次 reset 都重新开始,UI-TARS-2 的环境保持状态:
python展开代码# 传统方式
env.reset()
for step in range(max_steps):
action = model(obs)
obs = env.step(action)
# UI-TARS-2 方式
session = env.create_session() # 创建持久 session
for step in range(max_steps):
action = model(obs)
obs = session.step(action) # session 保持状态
# session 自动清理
好处: 支持需要多轮工具调用、文件读写的复杂任务。
不用等整个 batch 跑完:
展开代码Rollout Pool: [完成的轨迹1, 完成的轨迹2, ..., 未完成的轨迹N] ↓ 只要够 min_batch_size 就开始训练 ↓ 未完成的轨迹继续跑,下次再训练
基础算法是 PPO (Proximal Policy Optimization),目标函数:
其中:
但直接用 PPO 训长周期任务会炸,他们加了 5 个关键技巧:
问题: 游戏可能 1000 步才结束,前 999 步奖励都是 0,模型不知道哪步做对了。
解决方案:
python展开代码reward = final_success * 100 # 主奖励
if valid_format:
reward += 1 # 格式奖励
reward -= 0.01 * num_steps # 长度惩罚
背景知识: Advantage 衡量"这个动作比平均好多少",计算公式:
其中 (TD error)
问题: 长序列 (比如 1000 步) 时, 太大会放大噪声, 太小会丢失长期信息。
解决方案: 策略网络和价值网络用不同的 :
直觉: 策略网络需要看到远期回报来学习规划,价值网络需要稳定估计来指导训练。
问题: 10 步的简单任务和 1000 步的复杂任务,用同一个 不合理。
解决方案: 根据序列长度 动态调整:
其中 (超参数)
效果:
问题: PPO 开始时,价值网络是随机初始化的,给出的 乱七八糟,导致 Advantage 估计很差。
解决方案: 先用固定策略 (比如 SFT 模型) 跑一堆轨迹,用 Monte Carlo 真实回报 () 训练价值网络:
训练到 Explained Variance > 0.9 (价值网络能解释 90% 的回报方差) 再开始 PPO。
效果: 避免训练初期因为价值估计太烂导致策略崩溃。
标准 PPO: 把概率比裁剪到 (对称)
UI-TARS-2: 裁剪到 (非对称)
直觉:
问题: GUI-Browsing、GUI-General、Game 三个领域差异很大,联合训练不稳定。
解决方案: 分别训练,然后参数加权平均:
其中
理论依据: 从同一个预训练模型微调出来的模型,在参数空间里是线性模式连接的 (linearly mode-connected),即参数插值后的模型性能不会太差。
实验发现: 合并后的模型在每个领域的表现都接近该领域的专家模型,而且能处理需要跨领域技能的复合任务。
| 模型 | OSWorld | WindowsAgentArena | AndroidWorld | Online-Mind2Web |
|---|---|---|---|---|
| Claude-4 | 43.9 | - | - | - |
| OpenAI CUA-o3 | 42.9 | - | 52.5 | 71.0 |
| UI-TARS-1.5 | 42.5 | 42.1 | 64.2 | 75.8 |
| UI-TARS-2 | 47.5 | 50.6 | 73.3 | 88.2 |
关键发现:
15 款游戏的平均归一化分数 (人类=100):
| 模型 | 平均分 |
|---|---|
| 人类 | 100.0 |
| UI-TARS-2 | 59.8 |
| OpenAI CUA | 24.7 |
| Claude Computer Use | 21.6 |
亮点:

发现: 随着允许的最大步数增加,UI-TARS-2 的表现持续上升,其他模型很快就饱和了。
为什么? UI-TARS-2 学会了解锁新子目标,而不是瞎转悠。
传统 reasoning RL (比如 OpenAI o1) 训练时,熵单调下降 (模型越来越确定)。
UI-TARS-2 的熵先升后降:

解释: GUI 和游戏环境需要持续探索,模型在学习过程中发现了更多有效策略,而不是过早收敛到单一解法。

GUI 任务: Think length 持续下降
解释: 一旦知道该点哪个按钮,就不需要长篇大论的推理了,直接行动更高效。
游戏任务: Think length 呈周期性
解释: 每次游戏升级难度,Think length 就上升 (需要思考新策略),熟悉后又下降。
用 UI-TARS-2 自己当 ORM (奖励模型),F1=83.8,错误率 16%。
惊人发现: 即使错误率这么高,RL 照样训得好!
原因: 即使任务最终失败,中间很多步骤可能是对的,模型还是能从正确的中间步骤学到东西。这些正确步骤的奖励 > 错误奖励的负面影响。
GRPO 在推理任务上很强,但在 GUI Agent 上 PPO 碾压 GRPO:

推测: GRPO 更适合单轮推理,PPO 更适合多轮交互。
实验设置:
结果:
启示: 更强大的接口能帮助模型学习更好的表征,即使最终只用弱接口。
在线 Interactive Annotation 是王道
Think-Aloud 标注法
数据飞轮
必须上 RL
长周期 RL 的关键技巧
流式训练 + 异步 Rollout
Stateful Environment
GUI + SDK 混合
硬件加速 + 时间操控
奖励模型的假阳率
长周期任务的信用分配
参数插值的权重
量化带来的精度损失
UI-TARS-2 最牛的地方不是某个单点技术,而是系统性的方法论:
如果你想做 GUI Agent,这篇论文是必读的。不仅技术细节清晰,而且很多坑都帮你踩过了。
最后提一句:开源万岁! 字节愿意把这么多细节公开,对整个社区都是巨大贡献。
参考文献:


本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!