SFT Data
A finished job leaves raw trajectories. Tracer can turn reward-1.0 instances into supervised fine-tuning data for the downstream trainer, with deterministic quality scoring and token statistics generated during conversion.
Conversion is powered by the swe_data_process package and driven by scripts/convert_trajectories.sh.
The conversion pipeline
Raw trajectories (per-scaffold format)
└─ converter ─▶ IM format (OpenAI messages + tool_calls, JSONL)
└─ rule / llm scoring ─▶ scored IM
└─ to LF ─▶ LF format (ShareGPT array, JSON)
└─▶ trainer block (LLaMA-Factory)- Raw → IM — a scaffold-specific converter reshapes the raw trajectory into the intermediate "IM" format: OpenAI-style messages carrying
tool_calls, one JSONL row per trajectory. - Scoring — the TQS V2
rule_score.pyruns automatically for main-agent records and attaches acomposite_score; fixed-checklist and dynamic checklist LLM scorers are optional. See Scoring. - IM → LF — the scored IM is reshaped into the LLaMA-Factory "LF" format: a ShareGPT-style JSON array ready for SFT.
Running conversion
Conversion can run automatically at the end of a job, or on demand:
# Convert one job's trajectories (latest, or a named job)
bash scripts/convert_trajectories.sh --job latestWhen using the tracer plugin instead of shell commands, this on-demand
conversion/stat refresh lives under /tracer:dashboard.
Useful flags:
| Flag | Purpose |
|---|---|
--job <name|latest> | Which Harbor job to convert |
--scaffold <auto|claude_code|open_code|openhands_sdk|terminus2> | Override scaffold detection (auto derives from the agent/job name) |
--out-dir <dir> | Output root (default artifacts/sft_data) |
--max-instances <n> | Cap the number of converted instances |
--exclude-repos-file <path> | Exclude trajectories from listed repos (default artifacts/excluded_repos.txt) |
--reasoning-check-mode <strict|adaptive> | Reasoning-content filter mode; default is adaptive |
--reasoning-content-ratio-threshold <0..1> | Adaptive reasoning-content ratio threshold; current default is 0.2 |
--skip-unchanged | Reuse output when the reward-1.0 instance set and conversion inputs match .convert_sig.json |
The tokenizer is required and comes from
sft_conversion.tokenizer_name; keep it aligned with the trainer model. The
reasoning filter applies to Claude Code, OpenCode, and OpenHands SDK conversion
but not Terminus-2.
To run conversion automatically after every successful Harbor command, set
sft_conversion.enabled: true in config.yaml; start.sh then invokes the
converter for that job.
Outputs
artifacts/sft_data/<job>/
├── im.jsonl # PangUML v2 intermediate records, scored
├── lf.json # LLaMA-Factory ShareGPT array
├── lf.stats.json # token / turn / score statistics
└── .convert_sig.json # conversion signaturelf.json is the block's sft_data_dir output, consumed by the trainer block. lf.stats.json powers the dashboard.