--- license: apache-2.0 base_model: Qwen/Qwen3.6-27B tags: - coding - agent - structured-cot - sft - merged-lora - r2e-gym datasets: - andthattoo/etpi-sft language: - en library_name: transformers pipeline_tag: text-generation --- # etpi-phase1 — Structured-CoT SFT seed for Qwen 3.6 27B `etpi-phase1` is **Qwen 3.6 27B** with one round of supervised fine-tuning on grammar-constrained, structured-CoT coding-agent trajectories. The adapter (LoRA rank 128, `target_modules=all-linear`) has been **merged into the base weights** — this is a normal HuggingFace model checkpoint with no PEFT runtime dependency. This is **phase 1** of a multi-phase training pipeline. Phase 2 is RLVR (GRPO) against R2E-Gym, starting from this checkpoint. ## What's different about this model The base Qwen 3.6 27B reasons in long free-form chains-of-thought (hundreds-to-thousands of tokens per turn). This SFT seed teaches the model a **compact 3-slot IR** inside `...`: ``` STATE: ACTION: EXPECT: ... # or whatever the harness expects ``` Typical thinking-token spend per turn drops from **~1000+ → ~50-100** while preserving multi-turn coherence and tool-use ability. ## Intended use Drive a multi-turn coding agent — e.g., R2E-Gym / SWE-bench / Terminal-Bench style sandboxes — where the model: 1. Reads a task instruction (GitHub issue, terminal prompt, etc.) 2. Issues tool calls in a loop (bash, file editor, search) 3. Observes results and iterates 4. Submits when verified The IR structure compresses the *thinking phase*; tool calls and answers are left unconstrained. ## Training details | | | |---|---| | Base model | `Qwen/Qwen3.6-27B` | | Training data | [`andthattoo/etpi-sft`](https://huggingface.co/datasets/andthattoo/etpi-sft) (318 verified-successful multi-turn trajectories) | | Method | LoRA r=128, α=256, dropout 0.05, target_modules=all-linear, merged at end of training | | Optimizer | AdamW (8-bit), lr 2e-4, cosine schedule, warmup 0.03 | | Epochs | 2 | | Batch | per-device 1, grad accum 8 (effective batch 8) | | Sequence length | 8192 | | Loss masking | assistant tokens only (observations and user messages masked) | | Other | gradient checkpointing on, bf16, Liger fused CE loss | | Hardware | 1× H100 80GB (~40 min) | Final metrics: - train_loss (final): 0.096 - mean_token_accuracy: 95.87% ## Data provenance Trajectories were generated by running grammar-constrained Qwen 3.6 27B as a multi-turn agent against **R2E-Gym-Lite** (real GitHub issue tasks). The grammar enforced the IR structure inside `` while leaving tool calls free. Each task was rolled out 4 times (K=4 best-of-N). Only `reward=1.0` trajectories (passed the R2E unit-test verifier) were kept; among those, the **shortest** trajectory per task was selected as the SFT target — encoding a brevity-given-correctness preference directly into the data. See [`andthattoo/etpi-sft`](https://huggingface.co/datasets/andthattoo/etpi-sft) for the full dataset including system prompt, task instructions, and per-turn messages. ## Limitations - **Small training set (318 examples).** SFT-seed scale, not full SFT. Expected to generalize the IR format rather than acquire new capabilities. The phase-2 RL run is where capability climbs. - **Trained on one task distribution** (R2E-Gym, Python SWE-style issues). Performance on other languages or task types is untested. - **R2E paper authors use the Terminus 2 scaffold with an 80k-token- per-turn budget** to report 77.2% on SWE-bench Verified for the base Qwen 3.6 27B. This model is intentionally trained under a tighter scaffold (bash-only loop, IR-constrained thinking) with a different efficiency objective — direct numerical comparison is not apples to apples. - **Phase 1 only.** No RL has been applied. The expected pass@1 lift on R2E-Gym from SFT alone is modest; the real lift comes from phase 2. ## Recommended inference The model has internalized the IR format. You can drive it with or without grammar enforcement at inference time: ```python from transformers import AutoModelForCausalLM, AutoTokenizer m = AutoModelForCausalLM.from_pretrained("andthattoo/etpi-phase1", torch_dtype="bfloat16", device_map="auto") t = AutoTokenizer.from_pretrained("andthattoo/etpi-phase1") messages = [ {"role": "system", "content": "You are a software-engineering agent. ..."}, {"role": "user", "content": ""}, ] prompt = t.apply_chat_template(messages, add_generation_prompt=True, tokenize=False) ids = t(prompt, return_tensors="pt").to(m.device) out = m.generate(**ids, max_new_tokens=512, temperature=0.0) print(t.decode(out[0][ids["input_ids"].shape[1]:], skip_special_tokens=True)) ``` For maximum compression-safety in production, apply a GBNF grammar that enforces the IR shape on the `` block. ## License Apache 2.0 (matches base Qwen 3.6 27B license). ## Acknowledgements - Base model: [Qwen team](https://qwen.ai) - Training environment: [R2E-Gym](https://github.com/R2E-Gym/R2E-Gym) - Inference: [SGLang](https://github.com/sgl-project/sglang) - Tooling: TRL, PEFT, Liger Kernel, bitsandbytes