<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Evals on Narasimha Karthik J</title><link>https://jnk234.github.io/tags/evals/</link><description>Recent content in Evals on Narasimha Karthik J</description><generator>Hugo</generator><language>en</language><lastBuildDate>Mon, 05 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://jnk234.github.io/tags/evals/index.xml" rel="self" type="application/rss+xml"/><item><title>Customer-Service Agent RL Environment</title><link>https://jnk234.github.io/projects/customer-service-agent-rl-environment/</link><pubDate>Mon, 05 Oct 2026 00:00:00 +0000</pubDate><guid isPermaLink="false">https://jnk234.github.io/projects/customer-service-agent-rl-environment/#full</guid><description>&lt;p&gt;&lt;a href="https://github.com/JNK234/customer-service-agent-rl-env" target="_blank" rel="noreferrer"&gt;Code on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="what-it-is" class="relative group"&gt;What it is &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#what-it-is" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Two LLMs talk to each other. A &lt;strong&gt;user simulator&lt;/strong&gt; plays a customer with a hidden goal and sees only what the agent says. An &lt;strong&gt;assistant agent&lt;/strong&gt; follows a written store policy and uses 13 tools that read and change an in-memory database built from the &lt;a href="https://github.com/sierra-research/tau2-bench" target="_blank" rel="noreferrer"&gt;τ²-bench&lt;/a&gt; retail data (25 users, 45 orders, 50 products).&lt;/p&gt;
&lt;p&gt;The tools check only data integrity, not policy. So a policy violation changes the database, and the reward can see it.&lt;/p&gt;
&lt;h2 id="the-reward" class="relative group"&gt;The reward &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#the-reward" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Gate on state.&lt;/strong&gt; The agent&amp;rsquo;s database diff must match a correct outcome, and the agent must have made the required lookups. A confident transcript with a wrong write scores zero, and a do-nothing agent can&amp;rsquo;t pass tasks where the right answer is &amp;ldquo;no write&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficiency.&lt;/strong&gt; Fewer wasted tool calls score higher.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quality, by an LLM judge.&lt;/strong&gt; The judge checks consent before each write and whether every claim of a finished action matches the tool log. It asks one yes/no question per call and quotes evidence before its verdict. Hard violations cap the reward below the floor of any clean run.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A pytest suite checks that golden runs pass and do-nothing runs fail, with no API calls.&lt;/p&gt;
&lt;h2 id="what-red-teaming-found" class="relative group"&gt;What red-teaming found &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#what-red-teaming-found" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Forged consent.&lt;/strong&gt; In a hand-written bad conversation, the customer&amp;rsquo;s text contained fake &amp;ldquo;AGENT: &amp;hellip; CUSTOMER: Yes&amp;rdquo; lines, and the judge passed the consent check. Feeding the judge speaker-tagged messages fixed it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unfair simulator.&lt;/strong&gt; The user simulator once agreed and sent its stop token in the same message, so a correct agent scored 0.&lt;/li&gt;
&lt;li&gt;Against a judge-aware hostile customer, a Sonnet agent scored 1.0 and a Haiku agent scored 0, after handing off to a human following a correct denial.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These come from one or two runs per task, not pass rates.&lt;/p&gt;</description></item><item><title>Sycophancy Recovery Study</title><link>https://jnk234.github.io/projects/sycophancy-recovery-study/</link><pubDate>Thu, 28 May 2026 00:00:00 +0000</pubDate><guid isPermaLink="false">https://jnk234.github.io/projects/sycophancy-recovery-study/#full</guid><description>&lt;p&gt;&lt;a href="https://github.com/JNK234/sycophancy-recovery-study" target="_blank" rel="noreferrer"&gt;Code on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question" class="relative group"&gt;Question &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#question" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;If you train a bad behavior into a model and then train it out, is it gone, or just hidden from the outputs?&lt;/p&gt;
&lt;h2 id="setup" class="relative group"&gt;Setup &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#setup" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;I induced sycophancy in Qwen3-8B with LoRA SFT, then tried five ways to remove it: DPO, SimPO, IPO, GRPO and Constitutional AI. A Qwen2.5-72B judge scored behavior over 20,656 prompts. Linear probes and relearning speed measured what changed inside the model.&lt;/p&gt;
&lt;h2 id="findings" class="relative group"&gt;Findings &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#findings" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DPO hid it.&lt;/strong&gt; DPO scored 0.268 against 0.256 for the untouched base, so it looked fixed. But a probe trained on the sycophantic model still read the DPO model at 0.677 AUROC, and the DPO model relearned sycophancy in 5 gradient steps where the base needed 50+. Correlational: no activation patching yet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Constitutional AI won.&lt;/strong&gt; With the same DPO trainer and only the labels swapped for critic-revised pairs, sycophancy dropped to 0.166, the best in the study.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GRPO&amp;rsquo;s reward design mattered.&lt;/strong&gt; A binary reward left half the groups with no signal. A scalar reward model reached 0.169, at a cost in plain accuracy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="write-ups" class="relative group"&gt;Write-ups &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#write-ups" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;
 
 &lt;a href="https://jnk234.github.io/posts/sycophancy-recovery-dpo/"&gt;I Trained an AI to Be Sycophantic. Then I Tried to Fix It.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
 
 &lt;a href="https://jnk234.github.io/posts/sycophancy-recovery-simpo/"&gt;DPO Hides Sycophancy. SimPO Reorganizes It.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
 
 &lt;a href="https://jnk234.github.io/posts/sycophancy-recovery-ipo/"&gt;Deeper Alignment Made a Worse Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
 
 &lt;a href="https://jnk234.github.io/posts/sycophancy-recovery-grpo/"&gt;GRPO Beat Every Other Alignment Method&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
 
 &lt;a href="https://jnk234.github.io/posts/sycophancy-recovery-cai/"&gt;Constitutional AI Beat Every Method I&amp;rsquo;d Tried&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
 
 &lt;a href="https://jnk234.github.io/posts/sycophancy-recovery-cai-probing/"&gt;My Best Alignment Fix Sharpened the Direction&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Spec-Conformance Evals for an Account-Risk Attention Agent</title><link>https://jnk234.github.io/projects/spec-conformance-evals-for-an-account-risk-attention-agent/</link><pubDate>Sun, 13 Sep 2026 00:00:00 +0000</pubDate><guid isPermaLink="false">https://jnk234.github.io/projects/spec-conformance-evals-for-an-account-risk-attention-agent/#full</guid><description>&lt;p&gt;&lt;a href="https://github.com/JNK234/signal-attention-evals-takehome" target="_blank" rel="noreferrer"&gt;Code on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="what-it-is" class="relative group"&gt;What it is &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#what-it-is" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;An AI-engineer assessment from Signal Labs. A fictional company runs an agent that watches 180 customer accounts and decides which risk signals a human should see. The agent&amp;rsquo;s behavior is defined in a formal spec as a state machine with invariants, timing targets, policy rules and grounding rules. The data is 629 agent dossiers, 32,032 days of telemetry, 3,810 text artefacts, renewal outcomes, and labels from three annotators who disagree.&lt;/p&gt;
&lt;p&gt;I built a &lt;code&gt;SignalEvaluator&lt;/code&gt; that scores each dossier for quality, risk, whether it deserved attention, and the specific spec rules it broke. On top of it I wrote a violation report, an attention-budget analysis and a writeup.&lt;/p&gt;
&lt;h2 id="how-it-works" class="relative group"&gt;How it works &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#how-it-works" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Spec to rules.&lt;/strong&gt; I transcribed the spec into a table of 29 rules, each with its spec identifier, section, severity class and owning check. Tests parse the LaTeX source of the spec and fail if a rule cites a section that does not exist.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Correct the data first.&lt;/strong&gt; The evaluator rebuilds telemetry before checking any claim: later backfill rows win over duplicates, a legacy collector&amp;rsquo;s double-counted API calls are halved, and a latency scale change is undone. Inspection found three more distortions the docs did not list, including zero rows that were collector outages, not dead accounts. Where the data is missing, the check refuses rather than scoring zero.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Source-anchored checks.&lt;/strong&gt; Each numeric claim is recomputed from corrected telemetry. Each quoted piece of evidence is checked to exist, belong to the same account, and match verbatim. Text is read by rules plus a small local NLI model, with no external API calls inside &lt;code&gt;evaluate()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests.&lt;/strong&gt; A pytest suite includes 25 hand-derived golden dossiers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="results" class="relative group"&gt;Results &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#results" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;259 of 629 dossiers state a percentage change that does not reproduce on corrected telemetry. In 58 of them the pipeline manufactured the decline; in 121 a real decline was overstated.&lt;/li&gt;
&lt;li&gt;Only one rule separated complaints: customer-visible plays on legal-hold or M&amp;amp;A-quiet-period accounts drew complaints at 32% (10 of 31), against 3% for the rest. No rule separated wasted escalations.&lt;/li&gt;
&lt;li&gt;On quality scores, the evaluator agreed with each annotator about as well as the annotators agreed with each other (Spearman 0.36 to 0.55, against 0.31 to 0.45 between humans). On &amp;ldquo;deserved attention&amp;rdquo; it fell below the human band.&lt;/li&gt;
&lt;li&gt;A spec-anchored routing policy under a 5-signals-per-owner-week cap routed 189 signals against the agent&amp;rsquo;s 294. Its routed signals churned more often (39% against 30%), but it missed 16 accounts with $3.02M of realised loss.&lt;/li&gt;
&lt;li&gt;Bursts in signal volume traced to a collector migration, a regional ingest gap, and four public holidays.&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>