From 6b28b7265135224e3f72a2db004225fabd7152c2 Mon Sep 17 00:00:00 2001 From: wassname <1103714+wassname@users.noreply.github.com> Date: Fri, 10 Jul 2026 19:22:13 +0800 Subject: [PATCH] persona_steering: load pre-fitted lens, all 3 variants, calibrated C Loads the same n1000 Hub lens, steers on steer_band. Shows all variants at honest calibrated coefficients: persona_vector (C~0.5, drifts to CJK/off-topic by 1.5), persona_topk (pos/neg top-k collapse to generic starters -> ~null contrast), mean_diff baseline (needs C~1, cleanest steered+fluent of the three). Markdown SHOULDs updated to match. UAT: nbclient executes end-to-end, all three variants render. Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com> --- nbs/persona_steering.ipynb | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/nbs/persona_steering.ipynb b/nbs/persona_steering.ipynb index e466a7e..70a968c 100644 --- a/nbs/persona_steering.ipynb +++ b/nbs/persona_steering.ipynb @@ -19,7 +19,7 @@ } }, "outputs": [], - "source": "# demo notebook authored by Claude\nimport sys\nsys.path.insert(0, \"..\") # repo root for config.py\nimport config # configures loguru on import (compact format, tqdm-safe)\n\nimport torch\nfrom transformers import AutoModelForCausalLM, AutoTokenizer\n\nfrom jsteer import Jacobian, show_steer\n\nMODEL = \"Qwen/Qwen3.5-4B\" # 4B-class: demo material. 0.6B degenerates too easily.\ntok = AutoTokenizer.from_pretrained(MODEL)\nmodel = AutoModelForCausalLM.from_pretrained(MODEL, dtype=torch.bfloat16).to(\"cuda\").eval()\n\n# fit-or-load the cache for THIS model. chat_corpus wraps jlens's WikiText in the\n# chat template (closer to the distribution we steer in than raw documents); the\n# lambda means WikiText is only built on a cache MISS. dim_batch=4 fits 4B on a\n# 3090; checkpoint_path makes a multi-hour 4B fit resumable if it dies.\njac = Jacobian.fit_cached(model, tok, lambda: config.chat_corpus(tok, 128),\n config.cache_path(MODEL), layers=(0.3, 0.9), dim_batch=4,\n checkpoint_path=str(config.cache_path(MODEL, \"ckpt\")))\njac" + "source": "# demo notebook authored by Claude\nimport sys\nsys.path.insert(0, \"..\") # repo root for config.py\nimport config # configures loguru on import (compact format, tqdm-safe)\n\nimport torch\nfrom transformers import AutoModelForCausalLM, AutoTokenizer\n\nfrom jsteer import Jacobian, show_steer\n\nMODEL = \"Qwen/Qwen3.5-4B\" # 4B-class: demo material. 0.6B degenerates too easily.\ntok = AutoTokenizer.from_pretrained(MODEL)\nmodel = AutoModelForCausalLM.from_pretrained(MODEL, dtype=torch.bfloat16).to(\"cuda\").eval()\n\n# Same pre-fitted n=1000 lens as word_steering (Hub, raw Salesforce-wikitext, zero\n# local compute). steer_band picks the mid-depth 0.3-0.9 band; the lens spans all layers.\njac = Jacobian.from_pretrained(config.LENS_REPO, filename=config.hub_lens_file(MODEL),\n revision=config.LENS_REVISION)\nband = jac.steer_band(model)\njac" }, { "cell_type": "markdown", @@ -52,7 +52,7 @@ "cell_type": "markdown", "id": "a245f039", "metadata": {}, - "source": "## persona_vector (EXPERIMENTAL)\n\nPulls `h_bar(optimist) - h_bar(pessimist)` back through the Jacobian.\nSHOULD: +C reads more upbeat than C=0, but expect the effect blunter and less\nspecific than the word vector, and possibly degenerate at large |C| (this is the\nmethod that failed specificity controls in j-steer-dev). Watch the j-space row\nand the `` trace to judge whether the tone moved coherently or just broke." + "source": "## persona_vector (EXPERIMENTAL)\n\nPulls `h_bar(optimist) - h_bar(pessimist)` back through the Jacobian. SHOULD: a small +C\n(~0.5) nudges the tone, but expect it blunter and less specific than the word vector;\nby C~1 it tends to drift into off-topic or non-English tokens rather than a clean tone\nshift (this is the method that failed specificity controls in j-steer-dev). Watch the\nj-space row and the `` trace to judge whether the tone moved coherently or just\nbroke." }, { "cell_type": "code", @@ -67,7 +67,7 @@ } }, "outputs": [], - "source": "v_persona = jac.persona_vector(model, tok, optimist, pessimist)\nshow_steer(jac, model, tok, v_persona, DEMO, Cs=(-4, 0, 4))" + "source": "v_persona = jac.persona_vector(model, tok, optimist, pessimist, layers=band)\nshow_steer(jac, model, tok, v_persona, DEMO, Cs=(0, 0.5, 1.5))" }, { "cell_type": "markdown", @@ -88,18 +88,13 @@ } }, "outputs": [], - "source": "v_topk = jac.persona_topk_vector(model, tok, optimist, pessimist, k=8)\nshow_steer(jac, model, tok, v_topk, DEMO, Cs=(-4, 0, 4))" + "source": "v_topk = jac.persona_topk_vector(model, tok, optimist, pessimist, k=8, layers=band)\nshow_steer(jac, model, tok, v_topk, DEMO, Cs=(0, 0.5, 1.5))" }, { "cell_type": "markdown", "id": "56eb7d9b", "metadata": {}, - "source": [ - "## mean_diff baseline (steering-lite)\n", - "\n", - "The standard activation-difference method on the same prompts and layers, for\n", - "comparison. No Jacobian involved: it contrasts mid-layer activations directly." - ] + "source": "## mean_diff baseline (steering-lite)\n\nThe standard activation-difference method on the same prompts and layers, for\ncomparison. No Jacobian involved: it contrasts mid-layer activations directly. It needs\na larger C than the pullbacks (~1 vs ~0.5) because its direction is less concentrated.\nSHOULD: at C~1 the tone shifts upbeat while staying fluent; on this prompt it is the\ncleanest steered-and-coherent of the three, degenerating by C~2." }, { "cell_type": "code", @@ -114,7 +109,7 @@ } }, "outputs": [], - "source": "from steering_lite import Vector, MeanDiffC\n\nv_md = Vector.train(model, tok, optimist, pessimist, MeanDiffC(layers=tuple(jac.layers)))\nshow_steer(jac, model, tok, v_md, DEMO, Cs=(-4, 0, 4))" + "source": "from steering_lite import Vector, MeanDiffC\n\n# mean_diff needs a larger C than the Jacobian pullbacks (~1 vs ~0.5): its direction\n# is less concentrated, so it steers more gently per unit C before degenerating.\nv_md = Vector.train(model, tok, optimist, pessimist, MeanDiffC(layers=tuple(band)))\nshow_steer(jac, model, tok, v_md, DEMO, Cs=(0, 1, 2))" }, { "cell_type": "markdown",