HansBug/Qwen3-8B-OpenClaw-RL-iter215
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 等)一行都不用改。目录
快速开始
用 HF transformers
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 支持)
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
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:
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-iter215oc-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。
训练设置
完整启动命令见 `run_qwen3_8b_experiment.sh`。关键超参:
# 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: 10Reward 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 拉出的实际数据点):
四个子图说明:
评测结果
在 terminal-bench v0.1.x(86 task)上的 pass@1
iter215 这个 ckpt 在 OOD eval(agent harness 切到 tb run --agent terminus-2)上的成绩:
把 base Qwen3-8B 从 ~0 拉到与 Qwen3-235B / DeepSeek-R1 同水位,用 30× 更少的参数。
在 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):
8 个 task 类别:
结论: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 协议。证据:
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 兜底,模型没学到"做完后不发 toolcall、写一段总结"这个动作。inference 时如果没有 max-turns 兜底,模型会无限制地重复 verify。Inference 端要自己设上限([oc-repl 默认 12 轮](https://github.com/HansBug/oc-repl/blob/main/src/ocrepl/engine.py))。
- task_complete 自报 ≠ 任务真完成。模型说"完成"不一定真完成,验证要做客观检查(diff、tests、verifier)。oc-repl 提供了
--verify/--verify-filehook 专门处理这件事。
- 复杂多步 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 用。
复现 / 推理工具
引用 / 致谢
- 基座:`Qwen/Qwen3-8B`(Apache-2.0)
- 训练框架:`HansBug/OpenClaw-RL`
- Agent harness:`camel-ai/camel` `TerminalToolkit`
- Eval benchmark:`laude-institute/terminal-bench`
- Rollout 训练数据 pool:`camel-ai/seta` 1367 task
License: Apache-2.0(继承自 Qwen3-8B)。
如果你用这个 ckpt 做 paper / blog post,欢迎引用 `HansBug/OpenClaw-RL` 仓库 + 这个 model card。
