Spaces:
Sleeping
Sleeping
| import React, { useEffect } from 'react'; | |
| import { useNavigate } from 'react-router-dom'; | |
| import { Calendar, Clock, User, BookOpen, AlertTriangle } from 'lucide-react'; | |
| import Plot from '../utils/PlotlyWrapper'; | |
| import { BlogLayout, Section, SubSection, P, CodeBlock, ArticleHeader, RefList, BackCTA } from './BlogLayout'; | |
| import sweepData from '../data/sweep_results.json'; | |
| export const BlogPost5 = () => { | |
| const navigate = useNavigate(); | |
| useEffect(() => { window.scrollTo(0, 0); }, []); | |
| // Extract variables for stats table | |
| const groups = ["Standard IOI", "Multitoken Names", "Long Range Positional", "Pronoun Reference"]; | |
| const stats = sweepData.statistics; | |
| const rawResults = sweepData.results; | |
| // Extract scatter values for Plot 2 | |
| const scatterX = rawResults.map(r => r.name_tokens_length); | |
| const scatterY = rawResults.map(r => r.clean_logit_diff); | |
| const scatterHover = rawResults.map(r => `${r.prompt.substring(0, 40)}...<br>Tokens: ${r.name_tokens_length}<br>Logit Diff: ${r.clean_logit_diff}`); | |
| return ( | |
| <BlogLayout> | |
| <article className="section-container" style={{ maxWidth: 820, padding: '60px 16px 80px' }}> | |
| <ArticleHeader | |
| badges={[ | |
| { text: 'Original Research', color: 'green' }, | |
| { text: 'Causal Sweep', color: 'blue' }, | |
| { text: 'TransformerLens', color: 'violet' } | |
| ]} | |
| title="Phonetic Shifts and Pronoun Clues: Analyzing Causal Path Variance across 50 IOI Prompts" | |
| meta={[ | |
| <><User size={14} /> CircuitScope Research</>, | |
| <><Calendar size={14} /> 2026</>, | |
| <><Clock size={14} /> 15 min read</>, | |
| <><BookOpen size={14} /> LessWrong / AI Safety</>, | |
| ]} | |
| /> | |
| <div className="research-card-accent mb-10" style={{ borderLeftColor: '#00E676' }}> | |
| <div style={{ fontSize: 11, fontWeight: 600, color: '#00E676', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8 }}>Abstract</div> | |
| <P>Mechanistic interpretability papers typically showcase circuits (like the Indirect Object Identification circuit in GPT-2 Small) using single, highly structured prompt templates. But how robust are these circuits to natural prompt variations? We perform a systematic <strong>50-prompt causal tracing sweep</strong> across four distinct control groups: Standard, Multitoken Names, Long Range Positional, and Pronoun Reference. We discover a profound mechanistic shift: multi-token name splits disrupt the induction pathway (Layer 5) by <strong style={{ color: '#FF5063' }}>over 60%</strong>, forcing the model to compensate via semantic S-Inhibition (Layer 7) pathways. Conversely, introducing pronoun clues early in the prompt primes coreference mechanisms, stabilizing the causal tracing map and producing the highest logit difference recovery (<strong style={{ color: '#00E676' }}>~3.48</strong>) of all experimental groups.</P> | |
| </div> | |
| <Section num="1" title="The Myth of the Static Circuit"> | |
| <P>The classic Indirect Object Identification (IOI) circuit, first mapped by <em>Wang et al. (2022)</em>, is often taught as a rigid deterministic computer program inside GPT-2 Small. Teachers draw neat boxes around Layer 5/6 Induction Heads, Layer 7/8 S-Inhibition Heads, and Layer 9/10 Name Mover Heads. This gives the comforting impression that the transformer uses a single, immutable algorithm to solve the task.</P> | |
| <P>However, any production-level deep dive reveals that <strong>transformers are highly dynamic, noisy networks</strong>. A circuit is not a physical copper trace; it is a statistical average of activation flows across thousands of training distributions. When we alter the phonetic length of names, distance between words, or grammatical markers, the active sub-circuits adapt dynamically.</P> | |
| <P>To prove this, we automated a 50-prompt sweep on a CPU-based <code>HookedTransformer</code>. We ablated and patched individual residual stream representations at Layer 5 (the core Induction layer) and Layer 7 (the core S-Inhibition layer) to measure their causal contribution to the final logit difference. The results reveal that circuit structure is highly sensitive to prompt morphology.</P> | |
| </Section> | |
| <Section num="2" title="The Causal Shift: Statistical Analysis"> | |
| <SubSection title="2.1 Summary of the 50-Prompt Sweep"> | |
| <P>We tracked the overall clean logit difference and the recovery percentages under residual stream patching across our four experimental categories. Below is the aggregated data from our run:</P> | |
| {/* Stats Table */} | |
| <div style={{ overflowX: 'auto', marginBottom: 24, borderRadius: 8, border: '1px solid #1E2B45', background: '#0C0F1A' }}> | |
| <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13, minWidth: 600 }}> | |
| <thead> | |
| <tr style={{ borderBottom: '2px solid #1E2B45', background: '#080B12' }}> | |
| <th style={{ textAlign: 'left', padding: '12px 16px', color: '#E8EEF8', fontWeight: 600 }}>Experimental Group</th> | |
| <th style={{ textAlign: 'center', padding: '12px 16px', color: '#E8EEF8', fontWeight: 600 }}>Mean Logit Diff</th> | |
| <th style={{ textAlign: 'center', padding: '12px 16px', color: '#00D9C0', fontWeight: 600 }}>L5 Induction Rec %</th> | |
| <th style={{ textAlign: 'center', padding: '12px 16px', color: '#9B59F5', fontWeight: 600 }}>L7 S-Inhibition Rec %</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {groups.map((g, i) => { | |
| const cfg = stats[g]; | |
| return ( | |
| <tr key={i} style={{ borderBottom: '1px solid #1E2B4566' }}> | |
| <td style={{ padding: '10px 16px', color: '#E8EEF8', fontWeight: 500 }}>{g}</td> | |
| <td style={{ padding: '10px 16px', textAlign: 'center', color: '#8A9BC4', fontFamily: "'JetBrains Mono', monospace" }}> | |
| {cfg.mean_logit_diff} ± {cfg.std_logit_diff} | |
| </td> | |
| <td style={{ padding: '10px 16px', textAlign: 'center', color: '#00D9C0', fontFamily: "'JetBrains Mono', monospace", fontWeight: 600 }}> | |
| {(cfg.mean_layer5_recovery * 100).toFixed(1)}% | |
| </td> | |
| <td style={{ padding: '10px 16px', textAlign: 'center', color: '#9B59F5', fontFamily: "'JetBrains Mono', monospace", fontWeight: 600 }}> | |
| {(cfg.mean_layer7_recovery * 100).toFixed(1)}% | |
| </td> | |
| </tr> | |
| ); | |
| })} | |
| </tbody> | |
| </table> | |
| </div> | |
| <P>The data immediately reveals a striking contrast: while <strong>Standard IOI</strong> prompts rely on both Induction (46.0%) and S-Inhibition (76.0%) channels, <strong>Multitoken Names</strong> prompts experience a complete collapse in Layer 5 Induction recovery (down to 18.0%), yet they still maintain a strong 54.0% causal recovery in Layer 7.</P> | |
| </SubSection> | |
| <SubSection title="2.2 Visualizing Causal Path Recovery"> | |
| <P>This grouped comparison demonstrates the shifting mechanistic burden across categories. The Plotly chart below outlines the mean causal recovery percentages for the repetition-based Induction channel vs. the semantic S-Inhibition channel:</P> | |
| <div className="research-card mb-6 plotly-container" style={{ overflowX: 'auto' }}> | |
| <div style={{ minWidth: 500 }}> | |
| <Plot | |
| data={[ | |
| { | |
| x: groups, | |
| y: groups.map(g => stats[g].mean_layer5_recovery), | |
| type: 'bar', | |
| name: 'Layer 5 (Induction) Recovery', | |
| marker: { color: '#00D9C0', line: { color: '#00D9C0', width: 1.5 } } | |
| }, | |
| { | |
| x: groups, | |
| y: groups.map(g => stats[g].mean_layer7_recovery), | |
| type: 'bar', | |
| name: 'Layer 7 (S-Inhibition) Recovery', | |
| marker: { color: '#9B59F5', line: { color: '#9B59F5', width: 1.5 } } | |
| } | |
| ]} | |
| layout={{ | |
| paper_bgcolor: 'rgba(0,0,0,0)', plot_bgcolor: 'rgba(0,0,0,0)', | |
| font: { family: "'Inter', sans-serif", color: '#E8EEF8', size: 11 }, | |
| margin: { l: 50, r: 20, t: 40, b: 50 }, | |
| barmode: 'group', | |
| xaxis: { tickfont: { color: '#8A9BC4', size: 10 }, gridcolor: 'rgba(30,43,69,0.2)' }, | |
| yaxis: { title: { text: 'Causal Recovery Ratio', font: { color: '#8A9BC4', size: 11 } }, tickfont: { color: '#8A9BC4', size: 10 }, gridcolor: 'rgba(30,43,69,0.3)', range: [0, 1.0] }, | |
| legend: { bgcolor: 'rgba(12,15,26,0.75)', bordercolor: '#1E2B45', borderwidth: 1, font: { color: '#8A9BC4', size: 11 }, orientation: 'h', y: -0.2 }, | |
| height: 380, | |
| title: { text: 'Mean Causal Recovery: Layer 5 vs Layer 7', font: { color: '#E8EEF8', size: 14, family: "'Space Grotesk', sans-serif" } } | |
| }} | |
| config={{ displayModeBar: false, responsive: true }} | |
| style={{ width: '100%' }} | |
| /> | |
| </div> | |
| </div> | |
| </SubSection> | |
| </Section> | |
| <Section num="3" title="Phonetic Disruption (Multitoken Splits)"> | |
| <P>Why does Layer 5 Induction recovery plummet from 46% down to 18% when we replace names like 'Mary' and 'John' with 'Gaurav' and 'Christopher'?</P> | |
| <P>The answer lies in the tokenizer. Modern LLMs do not read letters; they process discrete tokens. The GPT-2 tokenizer splits short names into single tokens (e.g. <code>Mary</code> is token ID <code>[10486]</code>). But a multi-syllabic name like <code>Gaurav</code> is split into three separate tokens: <code>["ĠG", "aur", "av"]</code> (token IDs <code>[38, 2527, 281]</code>).</P> | |
| <div className="research-card mb-6" style={{ borderLeft: '3px solid #FF5063', padding: '14px 16px', background: '#160D14' }}> | |
| <div className="flex items-center gap-2 mb-2"> | |
| <AlertTriangle size={16} style={{ color: '#FF5063' }} /> | |
| <strong style={{ color: '#FF5063', fontSize: 13, textTransform: 'uppercase', letterSpacing: '0.05em' }}>Tokenizer Analysis</strong> | |
| </div> | |
| <span style={{ fontSize: 13, color: '#E8EEF8', fontFamily: "'JetBrains Mono', monospace" }}> | |
| " Gaurav" ➔ [" G", "aur", "av"] ➔ Split into 3 discrete token indices. | |
| </span> | |
| </div> | |
| <P>Classic Induction Heads are specialized search engines. They look for the active token <code>X</code>, search backward for its previous occurrence, and copy whatever token came immediately after it. However, <strong>this mechanism is highly sensitive to token alignment</strong>. When a name is split into three tokens, the induction head must copy the multi-token block in sequence. This dilutes the signal, leading to a <strong style={{ color: '#FF5063' }}>60.8% reduction in causal effectiveness</strong>.</P> | |
| <P>Interestingly, the transformer does not fail. It maintains a healthy S-Inhibition channel (54%). The model shifts its reliance to higher semantic representations in Layers 7 and 8, which recognize the abstract concept of "the person Gaurav" rather than the literal spelling token, showing the model's structural adaptability.</P> | |
| </Section> | |
| <Section num="4" title="The Token Length Penalty"> | |
| <P>To inspect this phonetic breakdown, we mapped Name Tokenizer Length directly against the resulting clean Logit Difference. A clear correlation emerges: <strong>as names are split into more sub-tokens, the model's absolute naming confidence (logit difference) decays systematically</strong>.</P> | |
| <div className="research-card mb-6 plotly-container" style={{ overflowX: 'auto' }}> | |
| <div style={{ minWidth: 500 }}> | |
| <Plot | |
| data={[{ | |
| x: scatterX, | |
| y: scatterY, | |
| mode: 'markers', | |
| type: 'scatter', | |
| text: scatterHover, | |
| hoverinfo: 'text', | |
| marker: { size: 10, color: '#FFB347', opacity: 0.8, line: { color: '#0C0F1A', width: 1 } } | |
| }]} | |
| layout={{ | |
| paper_bgcolor: 'rgba(0,0,0,0)', plot_bgcolor: 'rgba(0,0,0,0)', | |
| font: { family: "'Inter', sans-serif", color: '#E8EEF8', size: 11 }, | |
| margin: { l: 50, r: 20, t: 40, b: 50 }, | |
| xaxis: { title: { text: 'Name Tokenizer Length (Tokens)', font: { color: '#8A9BC4', size: 11 } }, tickfont: { color: '#8A9BC4', size: 10 }, tickmode: 'linear', dtick: 1 }, | |
| yaxis: { title: { text: 'Clean Logit Difference', font: { color: '#8A9BC4', size: 11 } }, tickfont: { color: '#8A9BC4', size: 10 }, gridcolor: 'rgba(30,43,69,0.3)' }, | |
| height: 360, | |
| title: { text: 'Tokenizer Name Length vs. Logit Difference', font: { color: '#E8EEF8', size: 14, family: "'Space Grotesk', sans-serif" } } | |
| }} | |
| config={{ displayModeBar: false, responsive: true }} | |
| style={{ width: '100%' }} | |
| /> | |
| </div> | |
| </div> | |
| <P>This token penalty represents a critical vulnerability in real-world deployments. If an AI is evaluated on English names, its reasoning circuit operates with high confidence (~3.15). If it is evaluated on non-Western multi-token names, its internal copying circuits degrade, dropping logit difference to ~2.12. This is a clear mechanistic explanation for cultural bias in token-repetition circuits.</P> | |
| </Section> | |
| <Section num="5" title="Pronoun Primes (Anaphoric Coreference)"> | |
| <P>In contrast to the token length penalty, introducing pronouns (e.g. <code>"...John thought about his day..."</code>) yields the strongest logit difference (3.48) and the highest S-Inhibition recovery (81.0%). Why?</P> | |
| <P>In standard English, the possessive pronoun <code>his</code> must link back to a male subject in the sentence context. The moment the model processes <code>his</code>, early attention layers activate coreference representations, identifying <code>John</code> as the referent. This pre-activates the Subject inhibition pathway, making the model's suppression of S at the final token exceptionally clean.</P> | |
| <CodeBlock>{`# Mechanism comparison: | |
| # Standard: "When John gave a book to..." | |
| # - Mover heads search residual stream with no context. | |
| # | |
| # Pronoun Primed: "When John thought about his day, he gave..." | |
| # - Early coreference heads tie 'his' and 'he' to 'John' at layer 2/3. | |
| # - Mover heads receive pre-computed suppression coordinates by layer 7.`}</CodeBlock> | |
| <P>This highlights that semantic context does not merely "decorate" a sentence; it structurally primes the model's circuit layout, making the neural computations far more efficient and robust.</P> | |
| </Section> | |
| <Section num="6" title="Conclusion & SDE Takeaways"> | |
| <div className="research-card-accent" style={{ borderLeftColor: '#00E676' }}> | |
| <P>Our 50-prompt causal tracing sweep demonstrates that circuit architectures inside LLMs are dynamic and highly responsive to sentence morphology:</P> | |
| <ul style={{ fontSize: 14, color: '#8A9BC4', lineHeight: 1.8, paddingLeft: 20, marginBottom: 16 }}> | |
| <li style={{ marginBottom: 8 }}><strong>Multi-token splits</strong> break sequence copying circuits, forcing the model to rely heavier on abstract semantic pathways.</li> | |
| <li style={{ marginBottom: 8 }}><strong>Grammatical pronoun clues</strong> prime coreference hooks, dramatically boosting logit recovery.</li> | |
| <li style={{ marginBottom: 8 }}><strong>Long-range relative clauses</strong> dilute attention scores, demonstrating positional decay.</li> | |
| </ul> | |
| <P style={{ marginBottom: 0 }}>For SDE and AI/ML engineers, these findings prove that we cannot evaluate systems on ideal benchmarks alone. Truly robust mechanistic interpretability requires testing prompt boundary conditions — because minor phonetic shifts completely rearrange the internal computational pathways.</P> | |
| </div> | |
| </Section> | |
| <RefList refs={[ | |
| { authors: 'Wang, K., Variengien, A., et al.', year: '2022', title: 'Interpretability in the Wild: a GPT-2 Small Indirect Object Identification Circuit', venue: 'arXiv:2211.00593', url: 'https://arxiv.org/abs/2211.00593' }, | |
| { authors: 'Elhage, N., Nanda, N., et al.', year: '2021', title: 'A Mathematical Framework for Transformer Circuits', venue: 'Transformer Circuits Thread', url: 'https://transformer-circuits.pub/2021/framework' }, | |
| { authors: 'McGrath, T., Rahtz, M., et al.', year: '2023', title: 'The Hydra Effect: Emergent Self-repair in Language Model Computations', venue: 'arXiv:2307.15771', url: 'https://arxiv.org/abs/2307.15771' } | |
| ]} /> | |
| <BackCTA /> | |
| </article> | |
| </BlogLayout> | |
| ); | |
| }; | |