Taimwe commited on
Commit
00d9092
Β·
verified Β·
1 Parent(s): ee4da68

Handoff: fixed supervisor + full findings/state so work can resume

Browse files
Files changed (1) hide show
  1. HANDOFF.md +104 -0
HANDOFF.md ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SecureCoder β€” handoff state (2026-10-04)
2
+
3
+ Everything needed to pick this up later. All code lives in this repo and in
4
+ `C:\Users\Taimwe\.cline\data\workspaces\chat\securecoder-pipeline`.
5
+
6
+ ## The bug we found and fixed
7
+
8
+ **v1 and v2 both emit literal `\n` (backslash-n) instead of real newlines**, so their
9
+ Python output does not parse. Measured with the same harness on the same prompts:
10
+
11
+ | Model | literal `\n` | valid Python |
12
+ |---|---:|---:|
13
+ | base `unsloth/Qwen3-Coder-30B-A3B-Instruct` | β€” | **93.3%** |
14
+ | `securecoder-30b-pro` (v1) | 14/15 | ~6.7% |
15
+ | `securecoder-30b-pro-v2` | 15/15 | **0.0%** |
16
+
17
+ **Root cause: parts of the training data mix store message text JSON-escaped.**
18
+ `_unescape_if_needed()` in `train_securecoder.py` now repairs them. Confirmed by
19
+ `--validate-only` against 40 rows/source:
20
+
21
+ | Source | repaired/40 |
22
+ |---|---:|
23
+ | `Trendyol/Cybersecurity-Instruction-Tuning` | 40 (100%) |
24
+ | `AlicanKiraz0/Cybersecurity-Dataset-Fenrir-v2.1` | 40 (100%) |
25
+ | `Humanlearning/CyberSecurity_OWASP-sft-dataset` | 40 (100%) |
26
+ | `ukcli/Cybersecurity-Dataset-Heimdall-v1.1` | 40 (100%) |
27
+ | `MrClipperz134/CTF-Instruct` | 23 (58%) |
28
+ | hermes-fc, xlam, Magicoder, threat-intel, ctf-solver, FineTome | 0 |
29
+
30
+ Every escaped source is a cybersecurity dataset. That is why tool-calling still scored
31
+ 100% (clean sources dominate it) while code scored 0% (escaped sources dominate it).
32
+
33
+ ## Files in this repo
34
+
35
+ | File | What changed |
36
+ |---|---|
37
+ | `train_securecoder.py` | **fixed** β€” `_unescape_if_needed()`, `repaired=` counter, BOM stripped so uv PEP 723 deps install |
38
+ | `eval_securecoder.py` | **fixed** β€” honours `--max-new-tokens` (was hardcoded 384), excludes truncation from the syntax score, falls back across dataset splits |
39
+ | `pipeline.py` | supervisor: `RESULT` seeded up front (fixes the `UnboundLocalError` that killed every supervised run), retries, `ADAPTER_REPO`/`GGUF_REPO` env overrides |
40
+ | `debug_v2_code.py` | dumps full replies β€” found the escaped newlines |
41
+ | `bisect_adapter.py` | proved base+adapter (no merge) is also affected β‡’ the adapter, not the merge |
42
+
43
+ ## Two bugs worth remembering
44
+
45
+ 1. **UTF-8 BOM before `# /// script`** β€” uv never saw the PEP 723 metadata block, so
46
+ `torch` was never installed and every job died in 3–6s with `No module named 'torch'`.
47
+ This is almost certainly what the old `patch-deps` jobs were fighting.
48
+ 2. **`eval_securecoder.py` scored truncation as invalid syntax.** With `max_new_tokens=384`
49
+ correct code was cut mid-statement and counted as a failure. Now truncated replies are
50
+ tracked separately (`truncated`, `n_truncated`, `truncated_rate`).
51
+
52
+ ## Repo state
53
+
54
+ - **Deleted** (intentionally, both shipped broken code): `securecoder-30b-pro-merged`,
55
+ `securecoder-30b-pro-GGUF`, `securecoder-30b-pro-v2-merged`, `securecoder-30b-pro-v2-GGUF`.
56
+ - **Kept**: both adapters (`securecoder-30b-pro`, `securecoder-30b-pro-v2`) β€” re-mergeable.
57
+ - **Eval reports**: `Taimwe/securecoder-eval-v2`, `Taimwe/securecoder-eval-base`.
58
+
59
+ ## How to resume
60
+
61
+ ```powershell
62
+ # 1. retrain with the fixed data (a100-large, ~2.4h, ~$6)
63
+ hf jobs run ghcr.io/astral-sh/uv:python3.12-bookworm `
64
+ uv run --with torch --with transformers --with datasets --with huggingface_hub `
65
+ --with bitsandbytes --with accelerate --with unsloth --with trl --with peft `
66
+ https://huggingface.co/Taimwe/securecoder-scripts/resolve/main/train_securecoder.py `
67
+ --base-model unsloth/Qwen3-Coder-30B-A3B-Instruct `
68
+ --output-repo Taimwe/securecoder-30b-pro-v3 `
69
+ --mix-scale 0.25 --max-steps 480 --max-seq-length 2048 --learning-rate 1e-4 `
70
+ --save-steps 200 --eval-samples 100 --report-to none `
71
+ --flavor a100-large --timeout 10800 --secrets HF_TOKEN --detach
72
+
73
+ # 2. then merge + quantise + eval
74
+ ```
75
+
76
+ **Sizing matters:** the full mix is 83,781 rows; at seq 4096 that is 983 steps at
77
+ 43.5 s/it β‰ˆ **11.8h / $29.50**. With `--mix-scale 0.25 --max-seq-length 2048` it is
78
+ 480 steps at 17.7 s/it β‰ˆ **2.4h / $6**. Do not omit those two flags.
79
+
80
+ Also set `--timeout` generously but below the credit budget you intend to spend.
81
+
82
+ ## Still to do (publishing, free)
83
+
84
+ - Fill the `_pending_` eval table on the model cards with the eval-14 numbers.
85
+ - The corrected harness is ready: `python publish_cards.py` or three `hf upload` calls.
86
+
87
+ ## Money spent this session (~$13 of 20)
88
+
89
+ | Item | ~$ |
90
+ |---|---:|
91
+ | two evals (v2 + base, A/B) | 2.30 |
92
+ | adapter-vs-merge bisect | 0.11 |
93
+ | two `--validate-only` diagnostics | 0.06 |
94
+ | cancelled run A (bad scoping: full mix @4096) | 7.45 |
95
+ | cancelled run B (this one, stopped in error) | 2.50 |
96
+
97
+ The `$7.45` was avoidable β€” v2's original job command showed `--mix-scale 0.25` and
98
+ `--max-seq-length 2048`, and I should have read it before launching instead of guessing.
99
+
100
+ ## Unrelated scaffold
101
+
102
+ `C:\Users\Taimwe\.cline\data\workspaces\chat\flux2-lora` β€” LoRA fine-tune + FastAPI
103
+ serving for `FLUX.2-klein-4B` (Apache-2.0). Not runnable here: HF large-file downloads
104
+ transfer at **0 MB/min** from this machine, and there is no GPU.