asaverren/openhands-train-ready
openhands-train-ready SFT-ready normalization of nebius/SWE-rebench-openhands-trajectories — 5,000 resolved OpenHands (v0.54.0) agent trajectories on real GitHub issues, bootstrapped by Qwen/Qwen3-Coder-480B-A35B-Instruct, with tool-call arguments deserialized to objects so chat templates just work. What was fixed The upstream parquet stores tool_call.function.arguments as a serialized JSON string "for storage efficiency" (per the Nebius README). Chat templates… See the full description on the dataset page: https://huggingface.co/datasets/asaverren/openhands-train-ready.
openhands-train-ready
SFT-ready normalization of nebius/SWE-rebench-openhands-trajectories — 5,000 resolved OpenHands (v0.54.0) agent trajectories on real GitHub issues, bootstrapped by Qwen/Qwen3-Coder-480B-A35B-Instruct, with tool-call arguments deserialized to objects so chat templates just work.
What was fixed
The upstream parquet stores tool_call.function.arguments as a serialized JSON string "for storage efficiency" (per the Nebius README). Chat templates that iterate arguments|items — including the Qwen3-Coder family — emit empty/broken tool calls if you train on the raw rows. Every record here has:
argumentsdeserializedstr → dict(double-encoded JSON and Python-repr dicts handled),- canonical per-role fields (
system/user/assistant/tool), - the per-trajectory
toolslist kept on the record — pass it straight toapply_chat_template.
Usage
from datasets import load_dataset
from transformers import AutoTokenizer
ds = load_dataset("asaverren/openhands-train-ready", split="train")
tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-Coder-30B-A3B-Instruct")
ex = ds[0]
text = tok.apply_chat_template(ex["messages"], tools=ex["tools"], tokenize=False)TRL/axolotl: point your chat-template mapping at the messages column; tools is a per-row column for templates that accept it.
Qwen3-Coder tool-call format (verified)
- Assistant calls render as
<tool_call><function=NAME><parameter=KEY>VALUE </parameter></function></tool_call>inside the<|im_start|>assistantturn. argumentsmust be a mapping — the template iteratesarguments|items. (This is the upstream storage bug this dataset fixes.)- Tool results render as
<tool_response>...</tool_response>inside auserturn;name/tool_call_idare kept for provenance but unused by the template.
Counts (see meta.json)
Tool calls validated against upstream tools.json (soft; all calls match the 5-tool OpenHands v0.54.0 set). All 5,000 records render through the real Qwen3-Coder chat template with zero errors.
Rebuild / extend
run_normalize.py (+ the traj_normalize package, both in this repo) reproduces this shard and can emit the full 32k resolved set (or failure trajectories via --include-failures):
pip install pyarrow huggingface_hub
python run_normalize.py --input nebius/SWE-rebench-openhands-trajectories \
--out-dir out --max-success 5000 --seed 0 --shufflesft_success.jsonl.gz is the raw tool output; data/ is the same content as parquet for load_dataset + viewer support.
Honest limitations
resolvedis upstream's SWE-bench-style judgment — no re-execution verification was performed downstream.- Trajectories are long (~49k tokens avg); filter/truncate to your context budget.
- Single bootstrap model (Qwen3-Coder-480B) and single scaffold (OpenHands v0.54.0) — behavior/diversity is bounded accordingly.
- Same-instance duplicates are possible (upstream samples multiple attempts per issue); dedupe on
instance_idif that matters to you.
Attribution & license
Upstream data: Nebius, CC-BY-4.0. This derivative shard redistributes normalized data under the same license — please attribute Nebius.
@article{trofimova2025openhandstrajs,
title={OpenHands Trajectories with Qwen3-Coder-480B-A35B-Instruct},
author={Trofimova, Maria and Shevtsov, Anton and Ibragim, Badertdinov and Pyaev, Konstantin and Karasik, Simon and Golubev, Alexander},
year={2025},
journal={Nebius blog},
}