explcre commited on
Commit
aeb566f
Β·
verified Β·
1 Parent(s): 9bd3c19

Upload docs/t3_post_v5_followups.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. docs/t3_post_v5_followups.md +304 -0
docs/t3_post_v5_followups.md ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # T3 β€” post-v5 follow-ups (deep-think + work plan)
2
+
3
+ The first-pass v5 work (oracle eval, multi-turn RFT, reasoning expansion,
4
+ sanitiser) is shipped. This doc captures the deeper questions the T3
5
+ rethink raises, what's already been done about them, and what's
6
+ deliberately deferred.
7
+
8
+ ## 1. RFT timing β€” when, relative to T1/T2 + joint training?
9
+
10
+ **TL;DR**: Current order (per-task SFT β†’ T3 RFT β†’ joint multitask) is
11
+ the right *minimum*. A second RFT pass after the joint adapter is a
12
+ worthwhile **ablation** but adds a serial dependency.
13
+
14
+ ### The current order
15
+
16
+ ```
17
+ Stage 1 T1 fusion-SFT (heuristic gold)
18
+ Stage 2 T2 fusion-SFT
19
+ Stage 3 T3 fusion-SFT (heuristic synthetic-edit gold)
20
+ Stage 3b T3 reasoning-only SFT (paper ablation)
21
+ Stage 3c RFT β€” generate K candidates from Stage-3 adapter,
22
+ oracle-filter, retrain on filtered set
23
+ Stage 4 Joint multitask fusion-SFT (T1+T2+T3, 35k each, balanced)
24
+ ```
25
+
26
+ ### Why RFT can't move earlier
27
+
28
+ RFT needs a candidate generator that's already on-task β€” i.e., capable
29
+ of producing T3-shaped enhancer edits. The base Qwen3.5-2B can't do
30
+ that without prior T3 SFT (it doesn't know the
31
+ `<enhancer_dna_start>` schema, the cell-type grammar, or the edit
32
+ budget convention). So RFT must come **after at least one T3 SFT pass**.
33
+
34
+ ### Why current order beats "RFT after joint"
35
+
36
+ The Stage-3 adapter is trained on 35k T3-only rows. The Stage-4 joint
37
+ adapter sees only 35k T3 rows out of a 105k mix (33% T3 share). For
38
+ candidate-generation specifically:
39
+
40
+ * **Stage-3 adapter**: more T3-faithful, fewer cross-task style
41
+ artefacts. Higher per-row keep-rate when scoring against the T3
42
+ oracle.
43
+ * **Stage-4 adapter**: better generalist, slightly weaker T3 grammar.
44
+
45
+ Empirical question β€” the **ablation** to run:
46
+
47
+ > RFT-from-Stage3 (current default) vs RFT-from-Stage4 (joint adapter)
48
+ > β€” does the joint adapter's regularisation produce candidates with
49
+ > higher mean objective margins, or do the format artefacts dominate?
50
+
51
+ This is a one-flag change: `--adapter-state-dict
52
+ runs/exp_joint_multitask_*/final/pytorch_model.bin` instead of the
53
+ T3-only path. Costs one RFT pass + one re-train. Worth a Table 3 row.
54
+
55
+ ### Why a second RFT pass after joint isn't free
56
+
57
+ Re-RFT-ing the joint adapter would chain:
58
+
59
+ ```
60
+ Stage 4 β†’ Stage 4-RFT β†’ retrain joint β†’ ...
61
+ ```
62
+
63
+ Each step is multi-hour on H100. Diminishing returns are likely (the
64
+ oracle is the same, the candidate distribution doesn't gain new
65
+ biology after the second pass). Defer to extended-paper revision.
66
+
67
+ ## 2. T3-specific oracle?
68
+
69
+ **TL;DR**: We use the DeepSTARR-7cell oracle for T3 (and T1). A T3-
70
+ specific oracle is a paper-extension worth doing if reviewers push;
71
+ the minimum-publishable suite ships with the shared oracle.
72
+
73
+ ### What a T3-specific oracle would predict
74
+
75
+ Two candidates:
76
+
77
+ * **"Edit-quality" oracle** β€” input: `(reference, edited, edit_distance,
78
+ cell_type, edit_type)`. Output: `(satisfies_objective, margin)`.
79
+ Trained on RFT-filtered (positive) + RFT-rejected (negative)
80
+ candidates. Self-bootstrap risk: the oracle becomes circular if it
81
+ only learns what the previous oracle's filter did.
82
+
83
+ * **"Pairing" oracle (transferred from T2)** β€” input:
84
+ `(promoter, edited_enhancer, cell_type)`. Output: `pairing_score`.
85
+ Trained on observed pairs (T2 dataset). For T3 we'd score `(promoter,
86
+ edited)` and reward the model when this score increases over
87
+ `(promoter, reference)`. This is biology-grounded and non-circular.
88
+
89
+ ### Why we ship with DeepSTARR-7cell
90
+
91
+ The DeepSTARR-7cell oracle gives per-cell-type activity scores. For T3:
92
+
93
+ * `activity_boost` reduces to "did the activity in the source cell
94
+ go up?" β€” `pred_activity_src > ref_activity_src`. Direct read from
95
+ oracle.
96
+ * `cell_type_transfer` reduces to "did the activity shift toward target?"
97
+ β€” `(pred_tgt - pred_src) - (ref_tgt - ref_src) > 0`. Direct read.
98
+ * `promoter_retarget` reduces to "is the new motif present?" β€” IUPAC
99
+ scan, no oracle needed.
100
+
101
+ So **all three T3 objectives are computable from the existing oracle**
102
+ without a T3-specific one. The DeepSTARR-7cell oracle is weak
103
+ (`val_pearson_mean=0.136`) in absolute terms, but the metrics use
104
+ **deltas and shifts** β€” relative ranking, where weak oracles still
105
+ carry meaningful signal.
106
+
107
+ If the paper review pushes back on oracle weakness, the "T2-pairing-as-
108
+ T3-oracle" path is the right extension β€” concrete and publishable.
109
+
110
+ ## 3. Loop-SFT β€” does it need T3-aware changes?
111
+
112
+ **TL;DR**: No code change. The data source for T3 trajectories should
113
+ swap to the post-RFT JSONL, but Loop-SFT itself is task-agnostic.
114
+
115
+ ### What Loop-SFT does
116
+
117
+ `scripts/train_loop_sft.py` consumes JSONL records of the shape:
118
+
119
+ ```
120
+ {"id": ..., "task_type": ...,
121
+ "messages": [system, user],
122
+ "trajectory": {"steps": [{kind, state, text, tool_name, tool_args, tool_result}, ...]}}
123
+ ```
124
+
125
+ The collator renders the trajectory into a single assistant turn the
126
+ LLM is trained to emit. Task-type doesn't change anything β€” the
127
+ collator looks at trajectory steps, not task semantics.
128
+
129
+ ### What changes for T3
130
+
131
+ The **trajectory dataset** for T3 is currently expanded from the
132
+ heuristic-gold T3 JSONL via `scripts/expand_loop_trajectories.py`. The
133
+ trajectory's final `kind="final"` step contains the gold enhancer
134
+ sequence β€” currently the heuristic synthetic-edit, **not** the
135
+ oracle-validated RFT candidate.
136
+
137
+ To align with v5:
138
+
139
+ ```bash
140
+ # old:
141
+ python scripts/expand_loop_trajectories.py \
142
+ --source data/prod_samples/train.enhancer_editing.strat7c.n35k.jsonl \
143
+ --out data/trajectories/train.enhancer_editing.jsonl
144
+
145
+ # new (post-RFT-aware):
146
+ python scripts/expand_loop_trajectories.py \
147
+ --source runs/exp_t3_fusion_sft_${STAMP}/rft_filtered_train.jsonl \
148
+ --out data/trajectories/train.enhancer_editing.rft.jsonl
149
+ ```
150
+
151
+ Same script, different `--source`. The expander reads the assistant's
152
+ gold answer from `messages[-1]["content"]`, which RFT replaced with
153
+ the candidate. So the trajectory's `final` step inherits the
154
+ candidate. No code change.
155
+
156
+ For the paper, we report Loop-SFT trained on:
157
+
158
+ * Heuristic-gold trajectories (matches the current pipeline default)
159
+ * **Post-RFT trajectories** (new; aligned with v5 evaluation)
160
+
161
+ These give two T3 Loop-SFT rows in Table 1 β€” a clean ablation.
162
+
163
+ ## 4. SV-GSPO β€” does it need T3-aware changes?
164
+
165
+ **TL;DR**: **YES, and it's now done.** The T3 outcome-reward function
166
+ in `regureasoner/rl/reward_shaper.py` was trained on the **wrong**
167
+ objective (sequence-distance window) before this commit. Fixed.
168
+
169
+ ### What was wrong
170
+
171
+ The previous `outcome_enhancer_editing(final, gold, min_edit=1,
172
+ max_edit=60)` returned 1.0 for any edit distance in `[1, 60]` and 0
173
+ for identity. That tells the agent "make a moderately-sized edit" β€”
174
+ which is exactly the wrong signal under the v5 framework where the
175
+ metric of record is *objective satisfaction*, not edit-distance window.
176
+
177
+ ### What's changed
178
+
179
+ `outcome_enhancer_editing(final, gold)` now returns the average of three
180
+ binary checks aligned with `scripts/eval_t3_oracle.py`:
181
+
182
+ * `within_budget` β€” Hamming ≀ `gold["edit_budget"]` (or 5%-of-len(ref)
183
+ fallback when no budget).
184
+ * `length_preserved` β€” `len(pred) == len(ref)`.
185
+ * `target_motif_present` β€” IUPAC regex (fwd + revcomp) for
186
+ `gold["target_motif"]`.
187
+
188
+ Score ∈ {0, 1/3, 2/3, 1}. SV-GSPO group-normalisation handles the
189
+ discreteness; rollouts are expected to land between 0 and 1 with most
190
+ mass at 2/3 (budget + length usually pass; motif is the bottleneck).
191
+
192
+ ### What's NOT done (deliberate)
193
+
194
+ The activity-based objectives (`activity_delta_src`,
195
+ `activity_relative_shift`) require an oracle forward-pass per rollout
196
+ β€” too slow for the hot RL loop. The evaluator-backed scorer
197
+ infrastructure in `reward_shaper.py` (the `OUTCOME_SCORERS_EVAL`
198
+ hook) is the right place to wire that in for **offline rescoring**
199
+ of completed rollouts; we'd then either include it as a `--reward-mode
200
+ oracle` flag or report both as a sanity check.
201
+
202
+ If reviewers push for "RL with the actual headline metric" we can:
203
+
204
+ 1. Add an `OutcomeFnOracle` that takes the oracle as a closure and
205
+ computes `activity_delta_src` per rollout.
206
+ 2. Cache oracle outputs by `(seq, cell_type)` hash to amortise repeat
207
+ eval across rollouts.
208
+
209
+ Estimated cost: ~50 LoC + a slow-but-correct ablation row.
210
+
211
+ ## 5. External baselines β€” how do we compare against prior work?
212
+
213
+ **TL;DR**: Currently weak. Adding two strong external baselines (TACO
214
+ + HyenaDNA / NT-v2) would harden the paper.
215
+
216
+ ### What we have (internal)
217
+
218
+ * Zero-shot Qwen3.5-2B (raw + tool-enriched prompts)
219
+ * Fusion-SFT (NTv3-650M + LLM + cell context, our architecture)
220
+ * Loop-SFT (trajectory-augmented Fusion-SFT)
221
+ * SV-GSPO (RL on top of Loop-SFT)
222
+ * NTv3-MDLM T1, NTv3-direct T2 (no-LLM baselines, our architecture
223
+ but no language model)
224
+
225
+ ### What's missing (external SOTA)
226
+
227
+ | Model | Task fit | Comparable for | Effort to add | Priority |
228
+ |---|---|---|---|---|
229
+ | **TACO** (Lin et al. NeurIPS 2024) | T3 native | T3 (paper-precedent) | Medium β€” repo public; needs DeepSTARR oracle re-fit | **HIGH** |
230
+ | **HyenaDNA** (Nguyen et al. NeurIPS 2023) | T1 / T2 | T1 generation, T2 binary classification | Low β€” already wired as encoder; needs head training only | **HIGH** |
231
+ | **DNABERT-2 / NT-v2** | T1 / T2 / T3 | All three (small encoder baseline) | Low β€” `regureasoner_loop` has NT-v2 wired | MEDIUM |
232
+ | **CtrlDNA** | T1 conditional generation | T1 only | Medium β€” repo public, training data alignment needed | MEDIUM |
233
+ | **Evo / Evo2** | Generation, fluency | T1 (but they're 7B+, hard to run on H100) | High β€” vortex install on lab cluster | LOW |
234
+ | **Caduceus** | DNA encoder | Same as NT-v2; redundant | Low | LOW |
235
+ | **DeepSTARR** (predictor) | Activity prediction | Used as our oracle, NOT a baseline for our tasks | N/A | N/A |
236
+
237
+ **Recommended for the minimum-publishable submission**: add TACO (T3
238
+ paper precedent) + HyenaDNA (T2 fluency baseline). DNABERT-2 is
239
+ nice-to-have. The rest go into the extended-paper version.
240
+
241
+ The exact recipe:
242
+
243
+ * TACO: clone their repo, drop in our DeepSTARR-7cell oracle, run
244
+ their trainer on our T3 train split. Eval with our
245
+ `eval_t3_oracle.py`. Apples-to-apples.
246
+ * HyenaDNA: their HF model card already has T2-style heads. Wire as
247
+ a `--encoder hyenadna` option in `run_genomefm_benchmark.py` and
248
+ retrain the pair head.
249
+
250
+ Both ~1 day of work each.
251
+
252
+ ## 6. Pipeline state β€” does any in-flight job need modification?
253
+
254
+ **No.** Audit:
255
+
256
+ * **Bench grid (in flight)** β€” vLLM zero-shot inference. T3 zs eval
257
+ uses the heuristic gold's metadata only (target_motif, edit_budget)
258
+ β€” no leakage from the v5 framework changes. Safe to let finish.
259
+ * **post_bench_pipeline.sh** β€” already updated with multi-turn RFT
260
+ (commit `25504fd`) and Stage 3d post-RFT reasoning (commit `3e65c96`).
261
+ Will pick up the changes when it auto-fires.
262
+ * **No fusion-SFT job is currently running.** Stages 1–4 fire only
263
+ after the bench grid finishes.
264
+
265
+ The `outcome_enhancer_editing` reward fix lands in `regureasoner/rl/
266
+ reward_shaper.py` β€” used only by SV-GSPO (Stage C, not yet running on
267
+ H100). Lab-side SV-GSPO runs would need to pull this commit.
268
+
269
+ ## 7. Concrete addition to the experiment suite
270
+
271
+ These lines belong in [`docs/minimal_publishable_suite.md`](minimal_publishable_suite.md)
272
+ once the H100 clears its current backlog:
273
+
274
+ ```bash
275
+ # Phase B-T3-RFT-from-joint (new ablation; 6h)
276
+ STAGE_4_FINAL=runs/exp_joint_multitask_${STAMP}/final/pytorch_model.bin
277
+ pixi run python scripts/rft_t3.py \
278
+ --adapter-state-dict $STAGE_4_FINAL \
279
+ --train-jsonl data/prod_samples/train.enhancer_editing.strat7c.n35k.jsonl \
280
+ --oracle-path runs/exp_oracle_ds_7cell_min/oracle.pt \
281
+ --output-jsonl runs/exp_t3_rft_from_joint_${STAMP}/rft_filtered_train.jsonl \
282
+ --candidates 4 --rounds 4 --temp-ramp 0.15
283
+
284
+ # Phase B-T3-Loop-SFT-on-RFT (new ablation; 4h)
285
+ pixi run python scripts/expand_loop_trajectories.py \
286
+ --source runs/exp_t3_fusion_sft_${STAMP}/rft_filtered_train.jsonl \
287
+ --out data/trajectories/train.enhancer_editing.rft.jsonl
288
+ TASK=enhancer_editing \
289
+ TRAIN_JSONL=data/trajectories/train.enhancer_editing.rft.jsonl \
290
+ ... \
291
+ bash slurm/run_train_loop_sft.sh
292
+ ```
293
+
294
+ ## TL;DR for the paper story
295
+
296
+ * **T3 dataset regen**: train labels, yes via RFT (in the pipeline).
297
+ Test labels, no β€” eval ignores the heuristic gold.
298
+ * **T3 benchmark code**: clean. `eval_t3_oracle.py` is the new headline
299
+ scorer; old `genqual.json` argmax_acc is informative-only.
300
+ * **T3 reward shaper**: fixed in this commit. SV-GSPO will now
301
+ optimise the right objective.
302
+ * **Loop-SFT**: no code change; just point at the post-RFT JSONL.
303
+ * **External baselines**: TACO + HyenaDNA are the two we should add
304
+ before submission. Both ~1 day each.