| # maxact-fast |
|
|
| Train a model to **generate text that maximally activates an arbitrary linear direction in its own |
| residual stream**, conditioned activation-oracle style (direction injected at layer 1, maximized at |
| layer L). The bet: if we pretrain on a *huge, diverse* set of directions — not just SAE features — |
| the model learns a **general residual-direction→text inverter** that transfers to SAE features for |
| free (cross-uplift). |
|
|
| ## The direction firehose (why this beats SAE-only conditioning) |
|
|
| SAE conditioning caps you at ~65k features and inherits the SAE's blind spots. Instead we mint an |
| effectively unlimited, diverse supply of *concept directions* straight from a corpus: |
|
|
| 1. **Embed** a large corpus (UltraFineWeb, streamed) with a fast embedding model (BGE) — cheap. |
| 2. **Cluster** the embeddings into K≈10k clusters (faiss k-means, GPU). Each cluster ≈ a concept. |
| 3. For a training example, **sample cluster A vs cluster B**, train a quick **linear probe** on the |
| *policy model's* layer-L residuals to separate A from B. The probe weight vector `w` is the |
| conditioning direction — same space as an SAE encoder column, so it drops straight into the |
| existing inject@1 / read@L machinery. |
| 4. **SFT target** = the few real corpus texts closest to cluster A's centroid. "Given direction `w`, |
| write text like this." |
| 5. Pretrain on millions of these (shuffled). Then RL (Dr. GRPO, no KL) on cluster-probes and/or SAE |
| features, and measure whether cluster-pretraining lifts SAE-feature performance. |
|
|
| Probe residuals are **cached once per cluster** (the only expensive Qwen3 pass), so step 3-4 mint |
| millions of (direction, targets) examples cheaply. |
|
|
| ## Objective & injection (unchanged from the activation-oracle line) |
|
|
| - Inject `unit(w) * ‖resid‖ * coeff` into the layer-1 residual at a `?` marker (norm-matched add). |
| - Reward = max over token positions of `(x_L − μ)·unit(w)`, measured on the STANDALONE re-tokenized |
| generation through the clean base model (no adapter, no injection). Same fair protocol as before. |
|
|
| ## RL = Dr. GRPO, done right, no KL |
|
|
| - advantage = `r − group_mean` — **no `/std`** (the removed Dr. GRPO difficulty bias). |
| - loss = `Σ_tokens(−min(ratio·A, clip(ratio)·A) · mask) / total_tokens_in_batch` (global constant |
| normalizer, no per-response length bias). |
| - **No KL term.** Stability comes from lr + grad-clip + fluency/distinct gates (optional), not a leash. |
| - Rollouts via **vllm-lens** (`SteeringVector(norm_match=True)` == our injection), ~5× vs HF generate. |
| - Reuse vLLM generation logprobs as `old_logps` (one on-policy update/batch → ratio≈1, no extra fwd). |
|
|
| ## Pipeline stages (each a CLI in scripts/) |
|
|
| 1. `embed_cluster` — stream corpus → BGE embeddings → faiss k-means K clusters → cluster assignments. |
| 2. `cache_resids` — per cluster, run M member texts through Qwen3, cache layer-L mean residuals. |
| 3. `build_data` — sample cluster pairs, train probes on cached resids, pick centroid targets → |
| (direction, target_text) shards. Millions. |
| 4. `pretrain` — SFT the generator (AO/LoRA) on the direction→text firehose. Massive. |
| 5. `finetune` — final polish on per-feature MAX-activating CORPUS examples (cleanest targets). |
| 6. `rl` — Dr. GRPO (no KL), vllm-lens rollouts, on cluster-probes and/or SAE features. |
| 7. `eval` — beat-corpus / normalized-activation on held-out SAE features (cross-uplift test). |
| 8. `interface` — tiny gradio app: type/pick a direction, watch generations + live activation. |
| |
| ## Speed principles |
|
|
| bf16 + flash-attn everywhere; faiss-GPU k-means; HF streaming (never materialize the corpus); |
| cache the one expensive Qwen3 residual pass; vLLM-lens rollouts; batchmax forwards on H200; |
| torch.compile the training step. Target: pretraining data mine + pretrain in a day, not a week. |
|
|