<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-06-17T07:39:00+00:00</updated><id>/feed.xml</id><title type="html">Nan Li</title><subtitle>PhD candidate in CS and philosophy. Thinking about AI, language, and moral judgment.</subtitle><author><name>Nan Li</name></author><entry><title type="html">Surreal</title><link href="/2026/06/09/surreal/" rel="alternate" type="text/html" title="Surreal" /><published>2026-06-09T00:00:00+00:00</published><updated>2026-06-09T00:00:00+00:00</updated><id>/2026/06/09/surreal</id><content type="html" xml:base="/2026/06/09/surreal/"><![CDATA[<p>Defended my PhD yesterday. Got the diploma. It still doesn’t feel real.</p>

<p>Preparing the presentation and the defense, even knowing you’re not going to fail, was still daunting and nerve-racking. It feels a bit unfair when you realize the world already rewards the loud ones, for whom such events are just another opportunity to shine. My proposal: let introverts use an AI voice-over. You should be able to just stand there and nod while a confident voice explains your thesis.</p>

<p>I decided not to ask my mom to watch online. It would have been 10:30pm her time. She should be deep asleep by then, and even if not, my presentation would surely put her there.</p>]]></content><author><name>Nan Li</name></author><summary type="html"><![CDATA[Defended my PhD yesterday. Got the diploma. It still doesn’t feel real.]]></summary></entry><entry><title type="html">AI sycophancy: what the new Science paper shares with our cross-lingual study</title><link href="/2026/04/07/ai-sycophancy-science-paper/" rel="alternate" type="text/html" title="AI sycophancy: what the new Science paper shares with our cross-lingual study" /><published>2026-04-07T00:00:00+00:00</published><updated>2026-04-07T00:00:00+00:00</updated><id>/2026/04/07/ai-sycophancy-science-paper</id><content type="html" xml:base="/2026/04/07/ai-sycophancy-science-paper/"><![CDATA[<p>Cheng et al. published a <a href="https://www.science.org/doi/10.1126/science.aec8352">study in <em>Science</em></a> last week on AI sycophancy. They fed 11 LLMs posts from Reddit’s r/AmITheAsshole and found models affirm user behavior 49% more often than the human crowd consensus. A follow-up with 2,400 participants showed that interacting with sycophantic AI made people more entrenched and less willing to apologize, while rating the AI as trustworthy and objective.</p>

<p>We’ve been working on a related problem. <a href="https://arxiv.org/abs/2601.10257">Our paper</a> (January 2026, under review at ACL) also uses AITA data and finds the same leniency: 12 of 13 models judge more leniently than the Reddit baseline (Cohen’s <em>d</em> &gt; 1.6), all 13 on a Chinese moral dilemma dataset. Two independent groups, same data, same finding.</p>

<p>The studies go in different directions from there.</p>

<hr />

<h2 id="what-happens-to-the-user-vs-what-happens-in-the-model">What happens to the user vs. what happens in the model</h2>

<p>Cheng et al. ask what happens to the <em>user</em>. Sycophancy measurably shifts how people reason about their own conflicts. We didn’t study that.</p>

<p>We ask what’s going on inside the <em>model</em>. Standard evaluation tells you a model behaves differently in English vs. Chinese, but not whether the gap comes from how it reads the input or how it reasons. We tested mismatched conditions (English story + Chinese chain-of-thought, and vice versa) to pull these apart. Reasoning language drives about 2x the behavioral shift that input language does (7.2 pp vs. 3.5 pp, <em>p</em> &lt; 0.001).</p>

<p>Through Moral Foundations Theory analysis, the main pattern is calibration drift: models change how harshly they judge, but moral priority rankings stay mostly stable (mean Spearman rho = 0.88). But “mostly” is doing work there. Some models shift which moral dimensions they weigh, and models that look stable on Western data shift on Chinese data.</p>

<p>44% of the models we tested appear stable under English-only evaluation but show hidden context-dependency cross-lingually. Monolingual benchmarking misses this.</p>

<hr />

<h2 id="two-halves-of-one-problem">Two halves of one problem</h2>

<p>The two papers split the problem down the middle. Stanford treats the model as a black box: sycophantic, yes, but that’s where their model-side analysis ends. They focus on what that sycophancy does to the person on the other end, and with 2,400 participants they nail it. People who interact with sycophantic AI become more entrenched and less willing to repair relationships.</p>

<p>We open the box. We decompose the sources of leniency, characterize per-model variation, identify which models fail silently across languages. But we stop at the model boundary. No user study (due to resource constraints).</p>

<p>Read together, you get both halves. We show that models aren’t just generically lenient – they reason with specific moral patterns that vary by language and shift in ways monolingual benchmarks can’t detect. Stanford shows that whatever the model produces, it sticks.</p>

<hr />

<h2 id="the-gap-between-them">The gap between them</h2>

<p>Cheng et al. show sycophantic AI makes users more self-serving in their <em>conclusions</em>. But does it also reshape <em>how</em> they reason? We find that LLMs weigh moral dimensions differently from humans, not just in severity but in which considerations matter most. If the model’s moral fingerprint transfers to the user, that’s a different problem than generic leniency.</p>

<p>The experiment to close the loop: have participants discuss moral dilemmas with chatbots, then evaluate new dilemmas on their own. Measure whether their moral foundation profiles drift toward the chatbot’s pattern. The fingerprinting method from our paper works on human judgments too, so this is directly testable.</p>

<hr />

<p><a href="https://arxiv.org/abs/2601.10257">Our paper: arXiv:2601.10257</a> (Li, Kang, De Bie), code and datasets included.</p>

<p><a href="https://www.science.org/doi/10.1126/science.aec8352">Stanford study: Cheng et al., <em>Science</em> 2026</a></p>]]></content><author><name>Nan Li</name></author><summary type="html"><![CDATA[Cheng et al. published a study in Science last week on AI sycophancy. They fed 11 LLMs posts from Reddit’s r/AmITheAsshole and found models affirm user behavior 49% more often than the human crowd consensus. A follow-up with 2,400 participants showed that interacting with sycophantic AI made people more entrenched and less willing to apologize, while rating the AI as trustworthy and objective.]]></summary></entry><entry><title type="html">Five heads in layer 12: what a learned KB encoder actually learns</title><link href="/2026/04/02/five-heads-in-layer-12/" rel="alternate" type="text/html" title="Five heads in layer 12: what a learned KB encoder actually learns" /><published>2026-04-02T00:00:00+00:00</published><updated>2026-04-02T00:00:00+00:00</updated><id>/2026/04/02/five-heads-in-layer-12</id><content type="html" xml:base="/2026/04/02/five-heads-in-layer-12/"><![CDATA[<p><a href="/2026/04/01/right-zip-code-wrong-address/">Part 1</a> showed that adding KG vectors to an LLM’s hidden state fails regardless of alignment. What works: train a small encoder to project KB entries into the model’s <em>attention key-value space</em> as extra tokens, as in <a href="https://arxiv.org/abs/2410.10450">KBLAM</a> (Feng et al., ICLR 2025). The LLM stays frozen; the encoder learns which directions actually change the output.</p>

<p>We reproduced this on <a href="https://arxiv.org/abs/2304.01373">Pythia-1.4B</a> and then asked where the signal goes.</p>

<hr />

<h2 id="the-encoder-works-and-the-shuffled-kb-test-proves-it">The encoder works, and the shuffled-KB test proves it</h2>

<p>Pythia gets 14% on factual probes by itself. With the encoder providing correct KB: <strong>96%</strong>.</p>

<p>The convincing number is the shuffled-KB result: 5%, below the 14% clean baseline. When given the wrong entity’s fact in the right format, the model follows it. The injection is live, not decorative.</p>

<p><img src="/assets/figures/fig5_kblam_effect.png" alt="Encoder accuracy" />
<em>Left: factual encoder, 14% baseline jumps to 96% with correct KB, drops to 5% with shuffled KB (below clean). Right: counterfactual encoder on facts Pythia has never seen, 0% baseline rises to 98%. Both show the model actively reads and follows the injected signal.</em></p>

<p>The counterfactual result is the stronger test: these are facts Pythia’s parametric memory assigns near-zero probability. The encoder writes new facts into a frozen model.</p>

<hr />

<h2 id="the-signal-concentrates-in-layer-12-head-identity-doesnt-matter">The signal concentrates in layer 12; head identity doesn’t matter</h2>

<p>The encoder injects into 64 head-layer slots (4 layers × 16 heads). We added a learnable on/off gate per head with a sparsity penalty (<a href="https://arxiv.org/abs/1712.01312">Hard Concrete L0</a>; Louizos et al., 2018) and trained two encoders with different penalty strengths.</p>

<p>Both converged to the same answer: zero out layers 0, 6, 18. Keep only layer 12.</p>

<p><img src="/assets/figures/fig6_head_gate_heatmap.png" alt="Head gate heatmap" />
<em>Two independently trained sparse encoders both concentrate all signal in layer 12. The active heads are completely disjoint, {0,1,5,7,14} vs {10,12}, yet achieve comparable accuracy. Layer identity is consistent across solutions; head identity is arbitrary.</em></p>

<p>Layer 12 is where Pythia’s relation-probing accuracy peaks and roughly where causal tracing methods (<a href="https://arxiv.org/abs/2202.05262">ROME</a>, <a href="https://arxiv.org/abs/2104.08696">Knowledge Neurons</a>) localize factual recall. The encoder discovered this on its own.</p>

<hr />

<h2 id="sparse-vs-all-heads-no-difference">Sparse vs all-heads: no difference</h2>

<p>You might expect fewer heads to mean less interference. Each head independently attends to all KB triples including distractors, so inactive heads import noise into the residual stream. The math predicts an optimal head count well below 64 (cross-head interference scales as H^2 while signal scales as H, via a <a href="https://link.springer.com/chapter/10.1007/978-3-319-92420-5_9">Hanson-Wright</a>-style argument).</p>

<p>We tested this by training an all-heads encoder from scratch (penalty disabled, all 64 heads free) and sweeping KB size. No difference. All three configurations (64, 5, 2 heads) overlap within bootstrap CIs at every KB size. Restrict the encoder to 5 heads and it routes the signal more strongly through those 5. Give it 64 and it spreads out. The bottleneck is the encoder’s mapping quality, not head count.</p>

<p>Practical takeaway: train end-to-end, inject into the right layer, and don’t bother optimizing over head selection.</p>]]></content><author><name>Nan Li</name></author><summary type="html"><![CDATA[Part 1 showed that adding KG vectors to an LLM’s hidden state fails regardless of alignment. What works: train a small encoder to project KB entries into the model’s attention key-value space as extra tokens, as in KBLAM (Feng et al., ICLR 2025). The LLM stays frozen; the encoder learns which directions actually change the output.]]></summary></entry><entry><title type="html">Right zip code, wrong address: why you can’t just add knowledge to an LLM</title><link href="/2026/04/01/right-zip-code-wrong-address/" rel="alternate" type="text/html" title="Right zip code, wrong address: why you can’t just add knowledge to an LLM" /><published>2026-04-01T00:00:00+00:00</published><updated>2026-04-01T00:00:00+00:00</updated><id>/2026/04/01/right-zip-code-wrong-address</id><content type="html" xml:base="/2026/04/01/right-zip-code-wrong-address/"><![CDATA[<p>I spent the last couple of weeks reading into how people combine knowledge graphs with LLMs. Knowledge graphs store facts as triples like (France, capital, Paris), structured and updatable. LLMs know a lot but hallucinate and go stale. Plenty of work tries to bridge the two: you can convert triples to text and put them in the prompt (<a href="https://arxiv.org/abs/2306.04136">KAPING</a>), fine-tune with projected KG embeddings (<a href="https://arxiv.org/abs/2504.07624">ConceptFormer</a>, <a href="https://arxiv.org/abs/2408.14512">TEA-GLM</a>), inject KG entries as extra attention key-value pairs (<a href="https://arxiv.org/abs/2410.10450">KBLAM</a>), or just edit the model’s weights (<a href="https://arxiv.org/abs/2202.05262">ROME</a>, <a href="https://arxiv.org/abs/2210.07229">MEMIT</a>).</p>

<p>I kept coming back to a simpler question: what if you just take a KG vector for “France,” project it into the LLM’s activation space, and add it to the hidden state? No fine-tuning, no weight editing, just vector addition on a frozen model.</p>

<p>It doesn’t work. We tried 300 configurations on <a href="https://arxiv.org/abs/2304.01373">Pythia-1.4B</a> with factual fill-in-the-blank questions from <a href="https://arxiv.org/abs/1909.01066">LAMA T-REx</a> (baseline: 20% Hit@1). Five injection methods, five layers, four strengths, three positions. Every one degraded performance. Best result: ~14%. The KG vectors performed no better than random noise of the same magnitude.</p>

<p><img src="/assets/figures/fig1_injection_pipeline.png" alt="Injection pipeline" /></p>

<hr />

<h2 id="kg-embeddings-are-noise-to-the-llm-but-the-llm-knows-the-facts-anyway">KG embeddings are noise to the LLM, but the LLM knows the facts anyway</h2>

<p>We measured representational similarity (<a href="https://arxiv.org/abs/1905.00414">CKA</a>) between KG embeddings and Pythia’s hidden states. <a href="https://papers.nips.cc/paper/2013/hash/1cecc7a77928ca8133fa24680a88d2f9-Abstract.html">TransE</a>, <a href="https://arxiv.org/abs/1902.10197">RotatE</a>, and sentence embeddings all look identical to random noise at every layer. Three fundamentally different external representations, same result.</p>

<p><img src="/assets/figures/fig2_cka_comparison.png" alt="CKA comparison" />
<em>Left: all external embeddings overlap with the random baseline; the lines are inseparable. Right: Pythia’s inter-layer CKA exceeds 0.95 through layers 4–22, confirming the metric can detect real similarity. KG embeddings aren’t slightly misaligned. They’re orthogonal.</em></p>

<p>The interesting part: the LLM <em>does</em> encode relational structure internally. A linear probe on Pythia’s hidden states classifies relation type (capital of? native language of?) at 65% on a 15-way task (chance: 6.7%). The facts are there. The geometry is completely different.</p>

<hr />

<h2 id="alignment-is-easy-to-learn-and-useless">Alignment is easy to learn, and useless</h2>

<p>We trained an MLP projector: KG vector → Pythia activation space. With 10 examples we hit 0.93 cosine similarity to Pythia’s own representations. The alignment problem is trivially solvable. Injecting these aligned vectors still doesn’t improve accuracy.</p>

<p>We tracked why. An injected perturbation, whether carefully aligned or random noise, gets amplified (~1.85×) and rotated until its direction is essentially random by the final layer.</p>

<p><img src="/assets/figures/fig4_perturbation_tracking.png" alt="Perturbation tracking" />
<em>Perturbation magnitude grows (left) and direction randomizes (right) through the network. The aligned vector (blue) and random noise (orange) reach nearly the same endpoint by layer 23. The transformer treats them identically; alignment washes out.</em></p>

<p>Alignment buys tolerance, not benefit. The model can handle an aligned perturbation at higher strength before collapsing, but accuracy never rises above the clean baseline. Both aligned and random perturbations end up in the same place by the output layer.</p>

<p>A static KG vector, the same “France” whether you’re asking about its capital or its language, can’t target the specific internal features the model reads for each prediction. Right zip code, wrong address.</p>

<hr />

<p><em><a href="/2026/04/02/five-heads-in-layer-12/">Part 2</a>: a learned encoder gets 96% on a frozen LLM, and we trace where in the model the signal goes.</em></p>]]></content><author><name>Nan Li</name></author><summary type="html"><![CDATA[I spent the last couple of weeks reading into how people combine knowledge graphs with LLMs. Knowledge graphs store facts as triples like (France, capital, Paris), structured and updatable. LLMs know a lot but hallucinate and go stale. Plenty of work tries to bridge the two: you can convert triples to text and put them in the prompt (KAPING), fine-tune with projected KG embeddings (ConceptFormer, TEA-GLM), inject KG entries as extra attention key-value pairs (KBLAM), or just edit the model’s weights (ROME, MEMIT).]]></summary></entry><entry><title type="html">It’s done</title><link href="/2026/03/21/its-done/" rel="alternate" type="text/html" title="It’s done" /><published>2026-03-21T00:00:00+00:00</published><updated>2026-03-21T00:00:00+00:00</updated><id>/2026/03/21/its-done</id><content type="html" xml:base="/2026/03/21/its-done/"><![CDATA[<p>Submitted my PhD thesis three days ago. For the first time in years, I’m enjoying some guilt-free time off. It feels unreal.</p>]]></content><author><name>Nan Li</name></author><summary type="html"><![CDATA[Submitted my PhD thesis three days ago. For the first time in years, I’m enjoying some guilt-free time off. It feels unreal.]]></summary></entry></feed>