From dbd526bed06488b6407ab5294ee21ce762311605 Mon Sep 17 00:00:00 2001 From: wassname <1103714+wassname@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:10:15 +0800 Subject: [PATCH] notebook: persona steering (EXPERIMENTAL framing, executed) persona_vector and mean_diff baseline both move tone at C=2; persona_topk is an honest null on this setup (both personas evoke the same generic sentence starters, contrast=0) and the notebook says so. Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com> --- notebooks/persona_steering.ipynb | 500 +++++++++++++++++++++++++++++++ 1 file changed, 500 insertions(+) create mode 100644 notebooks/persona_steering.ipynb diff --git a/notebooks/persona_steering.ipynb b/notebooks/persona_steering.ipynb new file mode 100644 index 0000000..88d8702 --- /dev/null +++ b/notebooks/persona_steering.ipynb @@ -0,0 +1,500 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "be33699b", + "metadata": {}, + "source": [ + "# Persona steering (EXPERIMENTAL)\n", + "\n", + "These persona variants are experimental. In the j-steer-dev experiments,\n", + "persona-contrast pullbacks FAILED specificity controls: they steered\n", + "generations, but no more selectively than an unrelated persona's vector did.\n", + "Only `word_vector` (see `word_steering.ipynb`) is the verified method. This\n", + "notebook exists so you can experiment and compare against a plain mean_diff\n", + "baseline, not as a recommendation.\n", + "\n", + "Two variants:\n", + "\n", + "- `persona_vector`: pull back the final-layer activation contrast\n", + " `h_bar(pos) - h_bar(neg)` through the cached Jacobian.\n", + "- `persona_topk_vector`: read each persona's mean activation through the\n", + " unembedding, take the top-k tokens it evokes, contrast those tokens'\n", + " unembedding rows, pull that back (persona -> vocabulary bottleneck -> the\n", + " verified word mechanism)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f08b7baf", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-10T05:09:12.585912Z", + "iopub.status.busy": "2026-07-10T05:09:12.585789Z", + "iopub.status.idle": "2026-07-10T05:09:17.775747Z", + "shell.execute_reply": "2026-07-10T05:09:17.775184Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/media/wassname/SGIronWolf/projects5/2026/jspace/jsteer/.venv/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + "Loading weights: 0%| | 0/311 [00:00) visible.\n", + "=== EXTRACT demo trace ===\n", + "POS[0]:\n", + "Things usually work out better than people expect, and today is no exception.\n", + "---\n", + "NEG[0]:\n", + "Things usually go worse than people expect, and today is no exception.\n", + "=== /EXTRACT ===\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C=-2: \" the project is going to be a disaster. It's a disaster of the kind that can't be contained, and it's going to consume the entire world. The only way to stop it is to\"\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C=+0: ' The project is going well, but there are some areas that need to be addressed. The project is in the early stages, and there are a few challenges that need to be addressed. The project is'\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C=+2: ' I think the project is going well. I am very satisfied with the work done. The project is a good example of the skills and knowledge I have gained. I would like to see the project further'\n" + ] + } + ], + "source": [ + "from steering_lite import Vector, MeanDiffC\n", + "\n", + "v_md = Vector.train(model, tok, optimist, pessimist, MeanDiffC(layers=tuple(jac.layers)))\n", + "for C in (-2, 0, 2):\n", + " print(f\"C={C:+d}: {gen(v_md, PROMPT, C)!r}\")" + ] + }, + { + "cell_type": "markdown", + "id": "55b3efd8", + "metadata": {}, + "source": [ + "## What to take away\n", + "\n", + "On this 0.6B setup: `persona_vector` and the `mean_diff` baseline both move\n", + "tone at C around 2, while `persona_topk_vector` collapses to a null vector\n", + "because the two personas evoke the same final-layer vocabulary. Moving tone\n", + "is not the interesting question, though. The j-steer-dev specificity controls\n", + "asked whether a persona vector moves ITS OWN axis more than an unrelated\n", + "persona's vector does, and the persona pullbacks failed that test. If you\n", + "need targeted steering, use `word_vector`; treat everything in this notebook\n", + "as raw material for experiments." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}