Qwen3-8B-OpenClaw-RL-iter215
把
Qwen/Qwen3-8B 用
HansBug/OpenClaw-RL 的训练框架做
GRPO outcome-only RL(dense pass-rate reward,无 PRM、无 process reward)跑出来的中间 checkpoint,对应
wandb run msp60ius 的 iter 215。在
terminal-bench v0.1.x 86 个 terminal-agent 任务上把 base Qwen3-8B 的 pass@1 从近 0 推到
0.056(OOD eval)。
完全 drop-in 兼容:config / generation_config / tokenizer 全部跟上游 Qwen/Qwen3-8B 字节级一致(diff 无差);任何能跑 Qwen3-8B 的工具链(HF transformers、vLLM、sglang、ollama、llama.cpp 转 GGUF 等)一行都不用改。
目录
- 快速开始
- 模型从哪来
- 训练设置
- 训练曲线
- 评测结果
- 任务级别的训练表现
- 推理时的 on-the-wire 协议
- 已知限制
- 复现 / 推理工具
- 引用 / 致谢
快速开始
用 HF transformers
1from transformers import AutoTokenizer, AutoModelForCausalLM
2
3tok = AutoTokenizer.from_pretrained("HansBug/Qwen3-8B-OpenClaw-RL-iter215")
4model = AutoModelForCausalLM.from_pretrained(
5 "HansBug/Qwen3-8B-OpenClaw-RL-iter215",
6 torch_dtype="bfloat16",
7 device_map="auto",
8)
9
10messages = [
11 {"role": "user", "content": "Write a one-line bash command to recursively count *.py files under /usr/lib."}
12]
13text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
14inputs = tok(text, return_tensors="pt").to(model.device)
15out = model.generate(**inputs, max_new_tokens=256, temperature=0.2)
16print(tok.decode(out[0][inputs.input_ids.shape[1]:], skip_special_tokens=True))
用 sglang(推荐,配 tool-call 支持)
1python -m sglang.launch_server \
2 --model-path HansBug/Qwen3-8B-OpenClaw-RL-iter215 \
3 --served-model-name qwen3-8b-rl-iter215 \
4 --tp 1 --port 30000 \
5 --tool-call-parser qwen
跟 base Qwen3-8B 一样的启动参数。--tool-call-parser qwen(或 qwen25)把模型的 <tool_call>{...}</tool_call> 还原成 OpenAI 结构化 tool_calls,这正是训练时 rollouts 用的 parser。
用 vLLM
vllm serve HansBug/Qwen3-8B-OpenClaw-RL-iter215 --enable-auto-tool-choice --tool-call-parser hermes
用 oc-repl 直接交互(端到端 demo)
HansBug/oc-repl 是一个针对这个 ckpt 量身写的 Codex 风格 REPL:
1pip install git+https://github.com/HansBug/oc-repl
2
3# 起一个 sandbox 容器(任何 ubuntu/python image 都行;下面用 terminal-bench 现成的)
4docker run -d --name oc-sandbox -w /app ubuntu:24.04 sleep infinity
5
6# 启动交互式 REPL
7oc-repl --sandbox docker:oc-sandbox \
8 --api-base http://127.0.0.1:30000/v1 \
9 --model qwen3-8b-rl-iter215
oc-repl 默认 --protocol camel-terminal-toolkit 对齐训练分布,详见仓库 README。
模型从哪来
Qwen3-8B-OpenClaw-RL-iter215 =
Qwen3-8B +
215 个 RL iteration 的 GRPO outcome-only 训练,rollout 在
SETA terminal env pool 提供的
1367 个 terminal task 上。每个 task 是一个真实的 Linux shell 任务(修脚本、解 base64、起 server、跑 pytest…),在隔离 docker 容器里跑,agent 通过
camel.toolkits.TerminalToolkit 暴露的 4 个工具操作 shell。
简单地说:用 camel-ai 的 agent harness 在 terminal-bench 风格的任务上把 Qwen3-8B 训成一个能干活的 terminal agent。
训练设置
1# GRPO 算法
2--advantage-estimator grpo
3--use-kl-loss --kl-loss-coef 0.01 --kl-loss-type k3
4--dynamic_history
5
6# Optimizer (low LR + Adam beta2=0.98)
7--optimizer adam --lr 1e-6 --lr-decay-style constant
8--weight-decay 0.1 --adam-beta1 0.9 --adam-beta2 0.98
9
10# Rollout
11--rollout-batch-size 16
12--n-samples-per-prompt 8 # 每 prompt 采 8 个 sample 算 GRPO group std
13--num-steps-per-rollout 2
14--rollout-temperature 1
15--rollout-max-response-len 8192
16--rollout-max-context-len 16384
17
18# Megatron
19--tensor-model-parallel-size 4
20--sequence-parallel
21--recompute-granularity full
22
23# Rollout agent + tool-call parser
24--custom-config-path configs/rollout_qwen3.yaml # tool_call_parser: qwen25
25 # max_iteration: 10
Reward signal:dense pass-rate, outcome-only —— 每个 rollout 跑完后由任务自带的 run-tests.sh 在 sandbox 里跑 pytest,reward = passed / total_tests ∈ [0, 1],再线性变换到 score = 2·reward − 1 ∈ [-1, +1] 喂给 GRPO;没有 PRM / process reward,整个 episode 共用一个标量。
max_iteration: 10:训练时 agent loop 上限 10 轮。
tool_call_parser: qwen25:sglang 把模型的 <tool_call>{"name":..., "arguments":...}</tool_call> markup 转回 OpenAI tool_calls 喂给 camel ChatAgent。
训练曲线
来自
wandb run msp60ius(rows=1671;以下是用
scan_history API 拉出的实际数据点):
training curves
四个子图说明:
| 子图 | 解读 |
|---|
| rollout accuracy | rollout 阶段 agent 报告的任务通过率。0 → 0.71 顶点,末段 0.576 稳定。整个训练在持续上升。 |
| reward_mean | outcome score 的均值(score = 2·pass_rate − 1 ∈ [−1, +1]:−1 = 一个 test 都没过,0 = 平均 pass 一半,+1 = 全过)。从 −0.5 升到 +0.42 顶点,最后稳在 +0.15。穿越 0 是关键信号,表示模型从"过的 test < 一半"转向"过的 test > 一半"。 |
| response_len | 每轮 assistant 输出的平均 token 数。一直在涨(150 → 270 → 顶 784),模型在学习更长的多步推理 / 工具调用链。 |
| non_trainable_ratio | GRPO group 里 σ=0(同 prompt 8 sample 全成功 / 全失败)的比例。这部分对 GRPO 不贡献梯度。训练始终保持在 < 5%,说明任务 pool 给出了足够的 reward 方差,绝大多数 prompt 都在产生有效梯度。 |
评测结果
在 terminal-bench v0.1.x(86 task)上的 pass@1
iter215 这个 ckpt 在 OOD eval(agent harness 切到 tb run --agent terminus-2)上的成绩:
| 模型 | pass@1 | 体量 | 备注 |
|---|
| Qwen3-8B-OpenClaw-RL-iter215 | 0.056 | 8 B | 本 ckpt(OOD eval) |
| Qwen3-8B (base) | ~0.005 | 8 B | RL 训练起点,几乎全失败 |
| Qwen3-235B-A22B (Terminus 1) | 0.066 | 235 B (active 22 B) | TB 官方 leaderboard |
| DeepSeek-R1 | 0.057 | 671 B | TB 官方 leaderboard |
| AfterQuery GPT-OSS-20B SFT+RL | 0.170 | 20 B | SFT + RL(更完整的 pipeline) |
| Qwen3-32B + TerminalAgent | 0.155 | 32 B | TB 官方 leaderboard |
| Claude 4.5 Sonnet | 0.645 | 闭源 | frontier |
| GPT-5 | 0.525 | 闭源 | frontier |
把 base Qwen3-8B 从 ~0 拉到与 Qwen3-235B / DeepSeek-R1 同水位,用 30× 更少的参数。
leaderboard chart
在 eval-as-train 设置下的天花板
把 TB v0.1.x 86 个任务
直接当训练集跑 84h / 320 rollout 得到上限 pass@1 =
0.092(同样 OOD 评测路径)。意思:模型在 8B 这个尺寸下、消除分布漂移后,自然能力上限大概在 9.2%。剩下要到 17%+(AfterQuery SFT+RL 那个水位)需要 cold-start SFT + 更好的 agent harness + 更对路的数据,详见
OpenClaw-RL issue #10。
任务级别的训练表现
把训练 log(37k trial × 85 task)按任务切片,每个任务算 reward (mean, std, strict_n):
per-task scatter
8 个 task 类别:
| 类别 | 数量 | 占比 | 含义 |
|---|
truly-cold-flat | 25 | 29% | mean = 0、std = 0:320 rollout × 8 sample 从没采到任何 partial reward。GRPO 对这些 task 永远 0 梯度。 |
truly-cold-noisy | 6 | 7% | 接近 0 mean、低 std:偶尔有微小 partial credit 噪声 |
partial-stuck-flat | 9 | 11% | mean ∈ [0.5, 0.9]、std 极低:模型靠 partial credit 拿了 50-90% 分但永远碰不到 strict=1.0 阈值。最高 swe-bench-astropy-2 mean=0.889 strict=0 |
partial-noisy | 22 | 26% | partial credit 区间但 std 较高,可能可以推到 strict |
weak-learnable | 9 | 11% | low mean、low strict_n:偶有突破但非主流 |
mid-learnable | 5 | 6% | mid mean、中等 strict_n |
truly-learnable | 4 | 5% | mean > 0.6、strict_n > 100:模型在这 4 个 task 上真实学到东西(hello-world / fix-permissions / fibonacci-server / vim-terminal-task) |
strict-flat | 1 | 1% | swe-bench-fsspec 异常:100% strict 但 std=0(verifier shortcut) |
结论:8B + 86 task pool 的瓶颈不是模型容量,是 task pool 信号分布——36% 真冷 + 38% 差一口气;要进一步提升需要换 dataset(seta_env 1367 task pool 已经在主训练里用了,这是为何 iter215 比 eval-as-train 上限 0.092 还低)。详见
OpenClaw-RL issue #10 长 comment。
推理时的 on-the-wire 协议
训练时这个 ckpt 看到的协议是 camel-ai TerminalToolkit 的 4 工具 OpenAI function-calling,
不是 terminal-bench 的
terminus-2 JSON 协议。证据:
System prompt 是
terminal-rl/agent/camel_agent.py::get_developer_agent_prompt() 在
system='Linux (in Docker)', machine='x86_64', non_think_mode=True 配置下产出的整段,结尾加
/no_think(关闭 qwen3 的 think trace,让模型直接 emit tool_call)。
如果你想 100% 复刻训练分布在 inference 用这个 ckpt,用
HansBug/oc-repl 的默认
--protocol camel-terminal-toolkit——它把上面这些设置都字节级对齐了。
已知限制
-
模型不会主动停止 tool_call。训练时 agent loop 由
max_iteration: 10 硬截断 + outcome reward 兜底,模型没学到"做完后不发 tool_call、写一段总结"这个动作。inference 时如果没有 max-turns 兜底,模型会无限制地重复 verify。Inference 端要自己设上限(
oc-repl 默认 12 轮)。
-
task_complete 自报 ≠ 任务真完成。模型说"完成"不一定真完成,验证要做客观检查(diff、tests、verifier)。oc-repl 提供了 --verify / --verify-file hook 专门处理这件事。
-
复杂多步 task adherence 中等。简单任务(chmod、cat、ls)adherence 满分;要写多行 Python 服务器、复杂 awk 这种,模型偶尔会 thinking 太久没产出 tool_call。
-
terminus-2 / terminus-XML 协议是 OOD。模型没在这些协议上 RL 训练过,能不能跑通靠 qwen3 底座的通用指令跟随能力。要复刻训练分布请用 camel TerminalToolkit 协议。
-
不是 frontier 水平。pass@1 0.056 跟 Qwen3-235B 同水位,但跟 Claude 4.5 / GPT-5 还有 10×+ 差距。这个 ckpt 适合做 RL 训练框架的 baseline / case study,不适合直接当 production agent 用。
复现 / 推理工具
引用 / 致谢
License: Apache-2.0(继承自 Qwen3-8B)。
如果你用这个 ckpt 做 paper / blog post,欢迎引用
HansBug/OpenClaw-RL 仓库 + 这个 model card。