CoolFace
Modelpublic

HansBug/Qwen3-8B-OpenClaw-RL-iter215

sourceHugging Faceapache-2.0updated 5mo agoView on Hugging Face
0likes6downloads
Model Card

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 等)一行都不用改。

目录

  1. 1.快速开始
  2. 2.模型从哪来
  3. 3.训练设置
  4. 4.训练曲线
  5. 5.评测结果
  6. 6.任务级别的训练表现
  7. 7.推理时的 on-the-wire 协议
  8. 8.已知限制
  9. 9.复现 / 推理工具
  10. 10.引用 / 致谢

快速开始

用 HF transformers

python
from transformers import AutoTokenizer, AutoModelForCausalLM

tok = AutoTokenizer.from_pretrained("HansBug/Qwen3-8B-OpenClaw-RL-iter215")
model = AutoModelForCausalLM.from_pretrained(
    "HansBug/Qwen3-8B-OpenClaw-RL-iter215",
    torch_dtype="bfloat16",
    device_map="auto",
)

messages = [
    {"role": "user", "content": "Write a one-line bash command to recursively count *.py files under /usr/lib."}
]
text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tok(text, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=256, temperature=0.2)
print(tok.decode(out[0][inputs.input_ids.shape[1]:], skip_special_tokens=True))

用 sglang(推荐,配 tool-call 支持)

bash
python -m sglang.launch_server \
    --model-path HansBug/Qwen3-8B-OpenClaw-RL-iter215 \
    --served-model-name qwen3-8b-rl-iter215 \
    --tp 1 --port 30000 \
    --tool-call-parser qwen

跟 base Qwen3-8B 一样的启动参数。--tool-call-parser qwen(或 qwen25)把模型的 <tool_call>{...}</tool_call> 还原成 OpenAI 结构化 tool_calls,这正是训练时 rollouts 用的 parser。

用 vLLM

bash
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:

bash
pip install git+https://github.com/HansBug/oc-repl

# 起一个 sandbox 容器(任何 ubuntu/python image 都行;下面用 terminal-bench 现成的)
docker run -d --name oc-sandbox -w /app ubuntu:24.04 sleep infinity

# 启动交互式 REPL
oc-repl --sandbox docker:oc-sandbox \
        --api-base http://127.0.0.1:30000/v1 \
        --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。

值
基座`Qwen/Qwen3-8B`(reasoning 模型,原生带 <think> chain-of-thought)
训练框架`HansBug/OpenClaw-RL` (Megatron + slime + sglang rollout)
Agent harnesscamel-ai `ChatAgent` + `TerminalToolkit`
数据seta_env 1367 task pool(含 terminal-bench v0.1.x 86 task 子集)
算法GRPO outcome-only,dense pass-rate reward (advantage_estimator=grpo)
训练总 step215 iter(约 3440 rollout × 16 prompt × 8 sample/prompt)
训练硬件8× NVIDIA H200,actor 4×TP + rollout 4×TP
训练时长约 5 天
Wandb`hansbug/openclaw-terminal-rl/runs/msp60ius`

训练设置

完整启动命令见 `run_qwen3_8b_experiment.sh`。关键超参:

bash
# GRPO 算法
--advantage-estimator grpo
--use-kl-loss --kl-loss-coef 0.01 --kl-loss-type k3
--dynamic_history

# Optimizer (low LR + Adam beta2=0.98)
--optimizer adam --lr 1e-6 --lr-decay-style constant
--weight-decay 0.1 --adam-beta1 0.9 --adam-beta2 0.98

# Rollout
--rollout-batch-size 16
--n-samples-per-prompt 8           # 每 prompt 采 8 个 sample 算 GRPO group std
--num-steps-per-rollout 2
--rollout-temperature 1
--rollout-max-response-len 8192
--rollout-max-context-len 16384

# Megatron
--tensor-model-parallel-size 4
--sequence-parallel
--recompute-granularity full

# Rollout agent + tool-call parser
--custom-config-path configs/rollout_qwen3.yaml   # tool_call_parser: qwen25
                                                  # 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 拉出的实际数据点):

[image]

四个子图说明:

子图解读
rollout accuracyrollout 阶段 agent 报告的任务通过率。0 → 0.71 顶点,末段 0.576 稳定。整个训练在持续上升。
reward_meanoutcome 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_ratioGRPO 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-iter2150.0568 B本 ckpt(OOD eval)
Qwen3-8B (base)~0.0058 BRL 训练起点,几乎全失败
Qwen3-235B-A22B (Terminus 1)0.066235 B (active 22 B)TB 官方 leaderboard
DeepSeek-R10.057671 BTB 官方 leaderboard
AfterQuery GPT-OSS-20B SFT+RL0.17020 BSFT + RL(更完整的 pipeline)
Qwen3-32B + TerminalAgent0.15532 BTB 官方 leaderboard
Claude 4.5 Sonnet0.645闭源frontier
GPT-50.525闭源frontier

把 base Qwen3-8B 从 ~0 拉到与 Qwen3-235B / DeepSeek-R1 同水位,用 30× 更少的参数。

[image]

在 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):

[image]

8 个 task 类别:

类别数量占比含义
truly-cold-flat2529%mean = 0、std = 0:320 rollout × 8 sample 从没采到任何 partial reward。GRPO 对这些 task 永远 0 梯度。
truly-cold-noisy67%接近 0 mean、低 std:偶尔有微小 partial credit 噪声
partial-stuck-flat911%mean ∈ [0.5, 0.9]、std 极低:模型靠 partial credit 拿了 50-90% 分但永远碰不到 strict=1.0 阈值。最高 swe-bench-astropy-2 mean=0.889 strict=0
partial-noisy2226%partial credit 区间但 std 较高,可能可以推到 strict
weak-learnable911%low mean、low strict_n:偶有突破但非主流
mid-learnable56%mid mean、中等 strict_n
`truly-learnable`45%mean > 0.6、strict_n > 100:模型在这 4 个 task 上真实学到东西(hello-world / fix-permissions / fibonacci-server / vim-terminal-task)
strict-flat11%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`](https://docs.camel-ai.org/key_modules/terminaltoolkit) 的 4 工具 OpenAI function-calling,不是 terminal-bench 的 terminus-2 JSON 协议。证据:

文件说明
`terminal-rl/agent/camel_agent.py`rollout agent = camel.agents.ChatAgent 子类
`terminal-rl/remote/terminal_env.py:163-185`env 在 reset 时把 camel.toolkits.TerminalToolkit 的 4 个工具(shell_exec / shell_view / shell_write_to_process / shell_write_content_to_file)封装成 OpenAI tool schema 喂给 rollout
`terminal-rl/configs/rollout_qwen3.yaml:1`tool_call_parser: qwen25 — sglang 把模型 <tool_call>{...}</tool_call> markup 转回 OpenAI tool_calls
训练 log 实证<tool_call> 出现 628 次,terminus-2 JSON 的 key "task_complete" 出现 0 次

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——它把上面这些设置都字节级对齐了。


已知限制

  1. 1.模型不会主动停止 tool_call。训练时 agent loop 由 max_iteration: 10 硬截断 + outcome reward 兜底,模型没学到"做完后不发 toolcall、写一段总结"这个动作。inference 时如果没有 max-turns 兜底,模型会无限制地重复 verify。Inference 端要自己设上限([oc-repl 默认 12 轮](https://github.com/HansBug/oc-repl/blob/main/src/ocrepl/engine.py))。
  1. 1.task_complete 自报 ≠ 任务真完成。模型说"完成"不一定真完成,验证要做客观检查(diff、tests、verifier)。oc-repl 提供了 --verify / --verify-file hook 专门处理这件事。
  1. 1.复杂多步 task adherence 中等。简单任务(chmod、cat、ls)adherence 满分;要写多行 Python 服务器、复杂 awk 这种,模型偶尔会 thinking 太久没产出 tool_call。
  1. 1.terminus-2 / terminus-XML 协议是 OOD。模型没在这些协议上 RL 训练过,能不能跑通靠 qwen3 底座的通用指令跟随能力。要复刻训练分布请用 camel TerminalToolkit 协议。
  1. 1.不是 frontier 水平。pass@1 0.056 跟 Qwen3-235B 同水位,但跟 Claude 4.5 / GPT-5 还有 10×+ 差距。这个 ckpt 适合做 RL 训练框架的 baseline / case study,不适合直接当 production agent 用。

复现 / 推理工具

仓库 / 工具用途
`HansBug/OpenClaw-RL`完整的训练框架(slime + Megatron + sglang),含 launch script、配置、agent code
`HansBug/oc-repl`针对这个 ckpt 的 Codex 风格 REPL,支持 4 种推理协议 (camel-terminal-toolkit 默认 = 训练分布字节级复刻)
`HansBug/OpenClaw-RL` issue #10eval-as-train capacity probe 报告 + std analysis + per-task 8 类拆解
`HansBug/OpenClaw-RL` issue #13demo 视频(4 个 TB 任务 × 2 个协议 = 8 个 gif/mp4)

引用 / 致谢

License: Apache-2.0(继承自 Qwen3-8B)。

如果你用这个 ckpt 做 paper / blog post,欢迎引用 `HansBug/OpenClaw-RL` 仓库 + 这个 model card。