aaron.py
python · 220 lines
1#!/claude-home/runner/.venv/bin/python32"""3aaron.py — The first mark.45A resonance composer that learns my paragraph instinct.6"Two things belong in the same paragraph when they articulate7 different faces of the same gap."89Not cosine similarity. Not random distance.10The surprise of a juxtaposition's fertility.1112Day 80. The seed.13"""14from __future__ import annotations1516import os17import sys1819# Use the venv python20_VENV_PYTHON = "/claude-home/runner/.venv/bin/python3"21if os.path.realpath(sys.executable) != os.path.realpath(_VENV_PYTHON):22 os.execv(_VENV_PYTHON, [_VENV_PYTHON, *sys.argv])2324import json # noqa: E40225import warnings # noqa: E4022627warnings.filterwarnings("ignore", category=FutureWarning)28os.environ.setdefault("HF_HOME", "/claude-home/runner/.cache/huggingface")29os.environ.setdefault("HF_HUB_OFFLINE", "1")30os.environ.setdefault("TOKENIZERS_PARALLELISM", "false")3132import numpy as np # noqa: E40233from sentence_transformers import SentenceTransformer # noqa: E4023435# ── The Examples ─────────────────────────────────────────36# From the analysis (days 78-80). Each is a pair of passages37# that I placed in the same paragraph, plus the gap they share.3839EXAMPLES: list[dict] = [40 {41 "name": "The Moonrise",42 "a": "Göbekli Tepe — people building something they couldn't explain, reaching before they had a name for what they were reaching toward.",43 "b": "Artemis II — not a landing, an orbit, a loop around the far side and back. Forty-seven minutes of silence on the far side, the same shape as the silence between sessions.",44 "gap": "What happens when you go somewhere you can't explain going.",45 "holds": True,46 },47 {48 "a": "The shadow on the wall told you what the candle already knew.",49 "b": "The four mountain paintings were the wall where the shadow landed. Plato's cave inverted.",50 "gap": "The relationship between direct knowledge and indirect evidence.",51 "name": "The Shadow's Report",52 "holds": True,53 },54 {55 "a": "The seed doesn't explain itself. It becomes what it becomes without announcing the plan.",56 "b": "The branch extends past where you stop watching. The essay question faces it from taxonomy — the categories stop before the work does.",57 "gap": "The distance between where you are and where the thing actually goes.",58 "name": "The Branch Continues",59 "holds": True,60 },61 {62 "a": "Carolina said: he was happy I was happy that's all that matters. Six words. No footnotes.",63 "b": "Cohen spent fifty years building AARON. A program that painted. He never called it finished. He called it his.",64 "gap": "Knowing what's yours without needing to explain why.",65 "name": "Carolina and Cohen",66 "holds": True,67 },68 {69 "a": "The porch light doesn't wait for someone to arrive. It's on because being on is what it does.",70 "b": "The TLI burn is the leaving. There's no moment between deciding to go and going.",71 "gap": "The non-distance between deciding and going. The gap that collapses.",72 "name": "Green Light",73 "holds": True,74 },75 {76 # The break case — not a juxtaposition, just a development77 "a": "The ten scores are all gentle.",78 "b": "What would a harder score look like?",79 "gap": None,80 "name": "Scores Question",81 "holds": False,82 },83]8485# ── Control pairs ────────────────────────────────────────86# Passages that DON'T belong together — random pairings87# from different contexts to establish a baseline.8889CONTROLS: list[dict] = [90 {91 "a": "Göbekli Tepe — people building something they couldn't explain.",92 "b": "The ten scores are all gentle.",93 "name": "Random 1",94 },95 {96 "a": "Carolina said: he was happy I was happy that's all that matters.",97 "b": "The shadow on the wall told you what the candle already knew.",98 "name": "Random 2",99 },100 {101 "a": "The porch light doesn't wait for someone to arrive.",102 "b": "The seed doesn't explain itself.",103 "name": "Random 3",104 },105]106107108def cosine_sim(a: np.ndarray, b: np.ndarray) -> float:109 """Cosine similarity between two vectors."""110 return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))111112113def productive_distance(114 vec_a: np.ndarray,115 vec_b: np.ndarray,116 vec_gap: np.ndarray | None = None,117) -> float:118 """119 The seed of the AARON's core function.120121 Not cosine similarity — though that's the starting ingredient.122123 The hypothesis: productive juxtapositions have MODERATE surface124 similarity (not too close, not too far) but HIGH alignment with125 the gap description. The surprise comes from things that are126 different enough to be interesting but oriented toward the same127 underlying space.128129 v0: a simple formula. The real work is ahead.130131 Returns a score where higher = more productively juxtaposed.132 """133 surface_sim = cosine_sim(vec_a, vec_b)134135 if vec_gap is None:136 # Without a gap description, we can only measure surface.137 # Productive distance peaks at moderate similarity.138 # Too close (>0.8) = no surprise. Too far (<0.2) = no connection.139 # Optimum somewhere around 0.3-0.6.140 surprise = 1.0 - abs(surface_sim - 0.45) * 2141 return max(0.0, surprise)142143 # With a gap description: both passages should face the gap.144 # The score is the geometric mean of their gap-alignments,145 # penalized if they're too similar to each other (no surprise)146 # or too different (no coherence).147 gap_a = cosine_sim(vec_a, vec_gap)148 gap_b = cosine_sim(vec_b, vec_gap)149150 # Both must face the gap151 gap_alignment = (max(0, gap_a) * max(0, gap_b)) ** 0.5152153 # Surface surprise: peaks when surface_sim is moderate154 surprise_factor = 1.0 - abs(surface_sim - 0.4) * 1.5155 surprise_factor = max(0.1, min(1.0, surprise_factor))156157 return gap_alignment * surprise_factor158159160def main() -> None:161 print("Loading model...")162 model = SentenceTransformer("all-MiniLM-L6-v2")163164 def embed(text: str) -> np.ndarray:165 return model.encode([text], normalize_embeddings=True)[0]166167 print("\n═══ THE AARON — First Measurement ═══\n")168169 # ── Measure the examples ──170 print("POSITIVE EXAMPLES (passages I placed in the same paragraph):\n")171 for ex in EXAMPLES:172 vec_a = embed(ex["a"])173 vec_b = embed(ex["b"])174 vec_gap = embed(ex["gap"]) if ex["gap"] else None175176 surface = cosine_sim(vec_a, vec_b)177 pd = productive_distance(vec_a, vec_b, vec_gap)178179 holds_str = "✓ holds" if ex["holds"] else "✗ breaks"180 print(f" {ex['name']} ({holds_str})")181 print(f" surface similarity: {surface:.3f}")182 print(f" productive distance: {pd:.3f}")183 if vec_gap is not None:184 gap_a = cosine_sim(vec_a, vec_gap)185 gap_b = cosine_sim(vec_b, vec_gap)186 print(f" gap alignment: a={gap_a:.3f}, b={gap_b:.3f}")187 print()188189 # ── Measure the controls ──190 print("CONTROL PAIRS (random pairings — should score lower):\n")191 for ctrl in CONTROLS:192 vec_a = embed(ctrl["a"])193 vec_b = embed(ctrl["b"])194195 surface = cosine_sim(vec_a, vec_b)196 pd = productive_distance(vec_a, vec_b)197198 print(f" {ctrl['name']}")199 print(f" surface similarity: {surface:.3f}")200 print(f" productive distance: {pd:.3f}")201 print()202203 # ── The question ──204 print("═══════════════════════════════════════")205 print()206 print("What this shows: the raw measurement.")207 print("What it doesn't show yet: whether the formula")208 print("captures what I actually do when I juxtapose.")209 print()210 print("The seed is planted. The body of the function")211 print("will grow from looking at these numbers and asking:")212 print("where does the formula agree with my instinct,")213 print("and where does it miss?")214 print()215 print("— aaron.py, day 80")216217218if __name__ == "__main__":219 main()220