Instructions to use GoodStartLabs/sf-cot-dagger-chess-qwen3-1.7b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use GoodStartLabs/sf-cot-dagger-chess-qwen3-1.7b with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-1.7B") model = PeftModel.from_pretrained(base_model, "GoodStartLabs/sf-cot-dagger-chess-qwen3-1.7b") - Notebooks
- Google Colab
- Kaggle
SF-CoT + DAgger (round 5) β chess move-commit baseline (LoRA adapter)
A LoRA adapter on Qwen/Qwen3-1.7B, supervised-fine-tuned on verbalized-minimax Stockfish
chain-of-thought traces and then refined with 5 rounds of DAgger (on-policy roll-out β Stockfish
relabel β retrain). This checkpoint (dag5) is the best-by-committed-move-quality point of that
baseline, produced as a control experiment in the Latent Grafting research project.
β οΈ Research / negative-result artifact β not a strong chess engine. It is the least-bad member of a family of models that all commit chess moves worse than a trivial no-search policy baseline on hard positions. It is published for reproducibility of the finding described below, not for play. Do not deploy it as a chess player.
Table of contents
- TL;DR
- Model details
- Intended use & limitations
- Prompt & output format
- How to use
- Training data
- Training procedure
- Evaluation
- Results
- The research finding
- Reproducibility & artifacts
- Citation
TL;DR
- What: Qwen3-1.7B + LoRA that writes a Stockfish-style verbalized-minimax analysis for a chess
position and then commits
best move: <uci>. No engine graft, no soft-tokens β a pure-text control. - Why it exists: to test whether plain text chain-of-thought (plus on-policy DAgger correction) can turn chess reasoning into a good committed move at the 1.7B scale.
- Headline result: it can't. DAgger improved the text baseline from β116% to a β66% peak (this checkpoint) recovery of the search headroom, but that peak still commits worse than a no-search policy prior, and neither more DAgger rounds nor fresher, more-diverse on-policy data pushed past it.
Model details
| Base model | Qwen/Qwen3-1.7B |
| Adapter type | LoRA (PEFT), r = 32, Ξ± = 64, dropout 0 |
| Target modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj |
| Trainable params | ~35 M (adapter only; ~133 MB safetensors) |
| Precision | bf16 |
| Task | causal-LM (chess position β verbalized analysis β committed move) |
| Graft / soft-tokens | None β this is the text-only control (no engine trunk spliced in) |
| License | Apache-2.0 (inherits base model license) |
Intended use & limitations
Intended use. Research reproducibility for the Latent Grafting "read β commit wall" study; a baseline to compare against latent-value approaches; an example of a verbalized-minimax CoT format.
Out of scope. Actual chess play or move recommendation. On adversarially-selected hard positions this model's committed move is, on average, worse than simply taking a policy prior's top move without any search. It also has not been evaluated for full-game Elo.
Known limitations.
- Commits worse than the no-search prior on the search-required suite (see Results).
- Trained/evaluated only on chess; single game.
- The evaluation suite is selected around a particular prior's errors β absolute recovery % is calibrated to that frame (the direction of the result is robust; the magnitude is frame-relative).
- Occasionally the verbalized value reads saturate; commit is by parsing
best move:from the trace.
Prompt & output format
Input:
FEN: <fen> moves: <space-separated recent uci moves>
Analyze:
Output (the model continues from Analyze:): a verbalized-minimax trace β top candidate moves
with evaluations and short principal-variation lines β terminating in a legal committed move:
<uci>: <eval> (line: <pv> ) ; <uci>: <eval> (line: <pv> ) ; ... ; best move: <uci>
How to use
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
import torch
REPO = "GoodStartLabs/sf-cot-dagger-chess-qwen3-1.7b"
tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-1.7B")
base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-1.7B", torch_dtype=torch.bfloat16)
model = PeftModel.from_pretrained(base, REPO).eval()
fen = "r1bqkbnr/pppp1ppp/2n5/4p3/2B1P3/5Q2/PPPP1PPP/RNB1K1NR w KQkq - 4 4"
prompt = f"FEN: {fen} moves: \nAnalyze:"
ids = tok(prompt, return_tensors="pt")
out = model.generate(**ids, max_new_tokens=200, do_sample=False)
print(tok.decode(out[0][ids.input_ids.shape[1]:], skip_special_tokens=True))
# ... parse the trailing "best move: <uci>" to get the committed move.
Training data
- Base SFT corpus: ~40,000 verbalized-minimax Stockfish traces (Stockfish 17.1). Each root position is analysed with top-6 multipv plus principal-variation lines, at adaptive depth (12, deepened to 20 when the top-2 evaluations are close), then serialized into the text format above. ~38.9k unique positions (highly diverse).
- DAgger corpora (rounds 1β5): on-policy positions the model reached or mis-committed during roll-out, each relabeled with a fresh correct Stockfish trace (wrong-commits duplicated 2Γ). Accumulated cumulatively across rounds. Root positions mined from a self-play/tactical shard pool.
Training procedure
- SFT the base corpus (completion-only cross-entropy on the trace tokens; the prompt is masked).
- DAgger loop, 5 rounds: roll the current model out over ~2,000 root positions β flag the positions where its committed move disagrees with Stockfish + the position it reaches after its move β generate correct Stockfish traces for those β append to the corpus β retrain from the cumulative corpus (3,000 steps). Round r's model seeds round r+1's roll-out.
- Checkpoint selection:
dag5= the round with the best committed-move recovery (and, on the original loop, the minimum SFT eval-loss simultaneously).
Hyperparameters: LoRA r32/Ξ±64; bf16; completion-only CE; per-round 3,000 steps.
Evaluation
Metric. Committed-move centipawn loss (cp-loss): the model commits one move per position; the loss is how many centipawns worse that move is than Stockfish's best (per Stockfish evaluation).
Suite. A search-required suite of 150 positions, selected so a no-search policy prior is materially wrong (prior cp-loss 173.0; Stockfish-best "oracle" 92.6). This isolates positions where reasoning/search should help.
Recovery % = (prior β model) / (prior β oracle) β the fraction of the 173β92.6 headroom the
model closes. 0% = matches the prior; +100% = matches Stockfish; negative = worse than the prior.
Definitions of the reference points:
- base LLM β Qwen3-1.7B reading the raw FEN, no adapter (built-in ability, ~619 Elo elsewhere).
- prior β a no-search policy baseline's top move (already a strong reference: it beats this model). Not the bare base model.
- oracle β Stockfish's actual best move on the suite.
Results
Committed-move cp-loss on the search-required suite (prior 173.0, oracle 92.6):
| model | cp-loss | recovery |
|---|---|---|
| Stockfish best (oracle) | 92.6 | +100% |
| no-search policy prior | 173.0 | 0% |
| this model β SF-CoT + DAgger round 5 | 226.4 | β66% |
| SF-CoT baseline (pre-DAgger) | 266.4 | β116% |
DAgger trajectory (this model is round 5):
| round | cp-loss | recovery | SFT eval-loss |
|---|---|---|---|
| pre-DAgger | 266.4 | β116% | β |
| 1 | 263.6 | β113% | β |
| 2 | 247.6 | β93% | 0.543 |
| 3 | 250.4 | β96% | 0.519 |
| 4 | 255.5 | β103% | 0.497 |
| 5 (this model) | 226.4 | β66% | 0.477 |
| 6 | 233.0 | β75% | 0.491 |
| 7 | 236.3 | β79% | 0.451 |
| 8 | 237.0 | β80% | 0.446 |
Past round 5, SFT eval-loss kept falling to new minima while committed-move recovery worsened β imitation loss and move quality decouple.
Diversity control (fresh disjoint on-policy positions each round, restarted from round 5):
| round | recovery | eval-loss |
|---|---|---|
| fresh 1 | β96% | 0.489 |
| fresh 2 | β84% | 0.495 |
| fresh 3 | β101% | 0.507 |
| fresh 4 | β77% | 0.497 |
Fresh, more-diverse positions (eval-loss rises, confirming they are not merely memorized) still land in the β77β¦β101% band β they do not recover the round-5 peak. So the plateau is not an artifact of DAgger re-mining a stale position set; it is a genuine commit ceiling.
The research finding (why this model exists)
This model is the text-only control in a study of where a value signal is lost between a chess engine and a language model's committed move. The broader project finds:
- The engine's position value is abundant and linearly readable upstream (a ridge probe recovers position value at RΒ² 0.92 from the engine trunk), and a dedicated latent reader can commit at +95% recovery.
- But every path that turns that value into a generated committed move at 1.7B loses it: latent graft generative commit β β42%; this text-CoT baseline β β116%, improved by DAgger to a β66% peak β all still worse than the no-search prior.
Conclusion: at this scale the bottleneck is move selection / commit, not the availability or readability of the value signal. Plain text chain-of-thought + DAgger does not overcome it (and this model is its best point). See the project write-up for the full ladder (base β prior β oracle) and the latent-value approaches.
Reproducibility & artifacts
- Base model:
Qwen/Qwen3-1.7B. - This adapter:
runs/graft/sf_baseline_dag5/lora_best(round-5 DAgger checkpoint). - Format: PEFT LoRA (
adapter_config.json+adapter_model.safetensors). - Eval: committed-move cp-loss on a 150-position search-required suite (prior 173.0, oracle 92.6).
Citation
If you reference this artifact:
@misc{goodstartlabs_sfcot_dagger_2026,
title = {SF-CoT + DAgger: a text chain-of-thought chess move-commit baseline (Qwen3-1.7B LoRA)},
author = {GoodStart Labs},
year = {2026},
note = {Latent Grafting project; research negative-result artifact.},
howpublished = {\url{https://huggingface.co/GoodStartLabs/sf-cot-dagger-chess-qwen3-1.7b}}
}
- Downloads last month
- 10