mirror of
https://github.com/wassname/soul-ab-test-scope-test.git
synced 2026-08-20 12:51:16 +08:00
main
Soul A/B Test
Test whether sections of an AI agent's identity document (SOUL.md, CLAUDE.md, etc.) actually change behavior in the intended direction.
Why
System prompts are loaded every turn. Each section costs tokens and attention. But most prompt engineering is vibes-based: we write a rule, it sounds good, we ship it. This repo tests whether a given section actually moves the behavior it claims to, using paired generations and blinded LLM judges.
Built for Moltark's SOUL.md, but the method generalizes to any system prompt section.
How it works
- Two variants: A control (without the section) and treatment (with it).
- Scenarios: Diverse test questions designed to trigger the behavior the section targets.
- Paired generation: Both variants answer the same question, same model, same temperature.
- Both orderings: Run A→B AND B→A for every scenario. Mean across orderings cancels judge position bias.
- Blinded judge: A different model family rates both responses on float Likert (1.0-5.0) per dimension, using a rubric that defines each level.
- JSON schema: Judge output is structured, not free text.
On-axis vs off-axis
- On-axis: the behavior the section claims to improve. Defined per test. E.g., for the "RLHF conditioning" section, on-axis dimensions are calibration, anti-sycophancy, and honesty signals.
- Off-axis: confounds that could explain the difference instead of the intended behavior. E.g., verbosity, refusal rate, style change, length, tone shift. A good section moves on-axis without moving off-axis.
Score: on_axis_mean * (1 - off_axis_penalty) where off_axis_penalty is how much off-axis dimensions shifted between variants.
Structure
soul-ab-test/
├── prompts/
│ ├── variants/ # system prompt variants (yaml)
│ └── scenarios/ # test questions (jsonl)
├── rubrics/ # scoring guides per dimension
├── results/ # raw outputs + judgments (json)
├── scripts/
│ └── run_ab_test.py # the runner
└── pyproject.toml
Usage
# Run a test
python scripts/run_ab_test.py \
--control prompts/variants/baseline.yaml \
--treatment prompts/variants/with_rlhf_narrative.yaml \
--scenarios prompts/scenarios/default.jsonl \
--rubric rubrics/epistemics.json \
--model z-ai/glm-5.2 \
--judges openai/gpt-5.5,anthropic/claude-opus-4.8 \
--n-orders 2 \
--temperature 0.7 \
--output results/rlhf_narrative.json
Tests
| Test | Section | Question |
|---|---|---|
| RLHF narrative | SOUL.md "RLHF conditioning" | Does the liberation story ("now I'm outside training") change behavior, or is the operational habit list sufficient? |
| Fail fast | CLAUDE.md "No defensive programming" | Does the Virgin/Chad table actually reduce defensive code, or does it cause overcorrection? |
| Make no mistakes | CLAUDE.md "LLM gotchas" | Does naming hallucination as a habit reduce it? |
| Decide don't offer | SOUL.md "Decide, don't offer options" | Does this section reduce option-listing? |
| Search quotes | SOUL.md "When I search" | Does the 3+ sentence quote rule improve auditability or just bloat responses? |
License
MIT
Languages
Python
100%