Ablation context
These runs study whether the gain from lowering the trajectory-inclusion threshold comes from
data quality or data quantity. Lowering the threshold changes both at once (2,040 -> 3,291
trajectories, +61%), so the arms below hold N fixed and vary only composition.
Table with columns: arm, N, fully-passing, imperfect, imperfect %| arm | N | fully-passing | imperfect | imperfect % |
|---|
| A (all-pass baseline) | 2,040 | 2,040 | 0 | 0% |
| B (size-matched mix) | 2,040 | 1,255 | 785 | 38% |
| C (all-pass subset of B) | 1,255 | 1,255 | 0 | 0% |
| D-dose20 | 2,040 | 1,632 | 408 | 20% |
| R (full, lowest threshold) | 3,291 | 2,040 | 1,251 | 38% |
This model: 2,040 trajectories: 1,632 fully-passing + 408 imperfect (20% imperfect).
Training data
Multi-turn bash-agent rollouts. Tool calls are emitted as plain text inside the assistant turn
using a <tool_call>{"name": "bash", ...}</tool_call> protocol defined in the system prompt
(not native function calling); tool output returns in a tool role. Loss is computed on
assistant turns only.
Training procedure
Full-parameter SFT via LLaMA-Factory,
DeepSpeed ZeRO-3, BF16, on 8x B200.
Table with columns: hyperparameter, value| hyperparameter | value |
|---|
| learning rate | 5e-6 |
| lr scheduler | cosine, warmup ratio 0.1 |
| weight decay | 0.0 |
| optimizer | AdamW |
| epochs | 5 |
| per-device batch size | 1 |
| gradient accumulation | 8 |
| effective batch size | 64 |
| max sequence length | 20,000 |
Results
Final train loss 0.2765 (from 0.9122 at the first logged step); mean train loss
0.3887 over 160 steps / 5 epochs.
Runtime 2.45h.
Note: a small fraction of samples (~5%) exceed the 20,000-token cutoff and are truncated.
Loss is not comparable across arms: arms containing imperfect trajectories are fitting
partly-failing rollouts, so a lower loss does not imply a better agent. These checkpoints must
be compared by task success rate, not by training loss.
Framework versions
- Transformers 5.8.0
- PyTorch 2.11.0+cu130
- DeepSpeed 0.18.9
- Datasets 4.0.0
Usage
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "March07/Qwen2.5-Coder-32B-terminal-agent-sft-mix2040-dose20"
tok = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, dtype="bfloat16", device_map="auto")
messages = [
{"role": "system", "content": "You are an expert technical assistant with access to bash tools."},
{"role": "user", "content": "List the files in /workspace."},
]
inputs = tok.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device)
out = model.generate(inputs, max_new_tokens=512)
print(tok.decode(out[0][inputs.shape[-1]:], skip_special_tokens=True))