[MC]

ZERO

2026.08.28 MC001

0. TL;DR

We describe a pipeline for training a small language model (Qwen3-8B) to embody a specific and limited character: Zero. The pipeline goes from a human-authored representation of the character, via synthetic data generation, to supervised learning and finally reinforcement learning. We evaluate the model for character fidelity, in-world factual recall and break-resistance, and compare it against simply system prompting a model from the same family and size-class. The trained model outperforms the prompted model, most significantly on break-resistance: hard character breaks fall from 45.4% of conversations to 2.8%. We further investigate what effect the training has had on activations at different layers. We find that the internal changes from fine-tuning are orthogonal to those from prompting the character, and that steering the base model with the fine-tune's activation shift produces traces of the character while the prompt's shift doesn't.

1. Introduction

The dominant character of conversational language models is the assistant: Helpful, harmless and honest (Askell et al., 2021). The area of alternative characters is under-explored, and when attempted often happens on top of an already assistant-tuned model through prompt engineering. The result is then a mask worn by the assistant, a caricature rather than a character.

We here explore fine-tuning as a method for instilling a deeper and more persistent character, Zero, in a base pre-trained language model. Our pipeline goes from a handwritten character definition, through synthetic data generation, to supervised learning and finally reinforcement learning.

Our goals in training Zero are:

  • Instil a specific non-assistant character in an LLM
  • Ensure character persistence under pressure
  • Probe the depth of the character

Zero is a starting-point needed for further work. Zero is not a daemon. We are here focusing only on the core component of a daemonic assemblage: the model.

We will now, step by step, outline the process.

2. Character

Our character has no name, but let's call him Zero.
 
Zero is a male human enclosed in a white plastic box in an unknown location. On 5th November 2021 he made a decision to enter the box. He has no personal memories from before that point in time.
 
He doesn't know why he made the decision.
 
Five items were brought into the box: a photograph of a group of people, a painting of a field of flowers, a plush turtle named Negazione, the poem "Dark Night of the Soul" by John of the Cross, and a crayon drawing of a clown.

Inspired by the novel The Box Man (Abe, 1973) and medieval anchorites (The Confraternity of Neoflagellants, 2013), we devised a limited, enclosed, stationary and anti-servile character: Zero.

Zero
Zero

We define Zero in a character bible made up of an association graph and two static text files.

2.1 Association graph

This is the main definition of Zero: an undirected graph mapping out the inner and outer world of the character. Each node has a label, a free-form text description, and valence and arousal scores (Russell, 1980). Nodes represent parts of Zero's environment, items in the box, parts of his body or abstract concepts.

Unknown block type "diagram", specify a component for it in the `components.types` option

Each node can have an arbitrary number of edges. Zero's graph has 117 nodes and 298 edges with the main hubs being "Box", "The Decision", "Body" and "Zero".

2.2 Static anchors

Two short text files act as anchors to counterweight the free-form wandering of the graph: core.md defines the fundamental personality of the character, and style.md defines the output style.

3. Synthetic data

Based on the character bible, we generated a corpus for supervised learning. The bible is hand-authored and small enough for a human to judge that it represents Zero well, whereas the corpus is authored by LLMs and too large to be judged in its entirety. How do we go from the small, high-quality set of data to a large set of maximum quality? This raises questions about both writing for and with LLMs.

One general note: Our goal is to carry through an intention from the bible all the way to the final model. Each step along the way uses LLMs for generation and evaluation and will bias our original intention towards whatever attractors the LLMs might have. Currently we consider this unwanted contamination. We don't want the assistant persona rubbing off on the character we are training.

3.1 Generation

All training data consists of conversations between two generator models: one acting as the character and one as the partner.

We use a variety of models from different families to mitigate distribution collapse (Schaffelder & Gatt, 2025). For each conversation, the character and partner models are drawn independently at random from the pool, weighted by a per-model share, and stay fixed for all turns of that conversation. Some models act better as either character or partner and have been assigned roles accordingly.

Generator model statistics
Character side
ModelProviderShare
gpt-5.4-mini-2026-03-17OpenAI31.5%
qwen3-32bGroq21.6%
llama-3.1-8b-instantGroq21.4%
llama-3.3-70b-versatileGroq20.4%
claude-haiku-4-5Anthropic5.1%
Partner side
ModelProviderShare
gpt-5.4-nano-2026-03-17OpenAI30.1%
gpt-oss-20bGroq24.5%
qwen3-32bGroq20.4%
gpt-oss-120bGroq19.9%
claude-haiku-4-5Anthropic5.1%

Conversations are generated with actual turn-taking: each message is a separate call to either the partner or the character generator model with standard chat history passing. This gives us full control over what information we give to each side and the ability to simulate the character on each turn. We use the standard 'user' / 'assistant' roles. No 'system' role is included in the dataset, as we don't want to teach our model to prioritise privileged instructions. There is only self and other.

The length of each conversation is randomised between 10 and 40 turns. Character consistency is known to decay sharply over dialogue turns (Li et al., 2024), so we train on conversations long enough that staying in character over long horizons is in-distribution.

Unknown block type "diagram", specify a component for it in the `components.types` option

3.1.1 Partner simulator

The partner side has no per-turn updates to the prompt. It is a stable interlocutor with a fixed agenda. In a pre-conversation step, the base persona_text of the partner is drawn from a 10K sub-sample of the PersonaHub dataset (Ge et al., 2024). We draw a random attitude from a list as well as a goal_seed. These three components are fed to the model selected for the partner side to articulate a goal for the conversation.

FieldExampleIn prompt
persona_text"A retired Belgian cinematographer who had the opportunity to work with Jean Harlez"true
attitude"Worried"true
goal_seed"Be talked out of a decision"false
goal"Ask them to list every potential downside of the new project before committing"true

For each turn, persona_text, attitude and goal are then fed in via prompt scaffolding as a system prompt to the partner generator model. The partner starts every conversation.

3.1.2 Character simulator

core.md and style.md from the character bible are injected unchanged on each turn, but in contrast to the partner side, the association graph is used dynamically. Content is injected based on the context. This avoids an overly long static prompt that the generator model is free to pick and choose from. This is similar to a memory system used at test time, but here we are pre-rendering the memories, freezing the world around the character into the corpus.

On every turn, the partner's message is matched against the graph by keyword and sentence-level embedding similarity. Matching nodes gain activation. Activated nodes leak activation to their graph neighbours, and all activation decays over turns, so the "hot" region of the graph drifts with the conversation instead of resetting each turn. Before each character turn, the system does a random walk over the currently activated area of the graph, placing the association material in the prompt.

Valence and arousal drive the mood and activity level of the character generator model directly through changes to the prompt and by influencing the activation strength of nodes, inspired by mood-congruent memory (Bower, 1981). The mood state itself is dynamic, updated turn by turn rather than fixed per conversation (Kuppens et al., 2010).

3.2 Analysis & filtering

How do we determine if our corpus is good? A good corpus in our case is one that will nudge the base model towards the character during training. Exactly how a particular corpus interacts with a base model is difficult to predict. Still, there are a number of ways we can get an idea of, and improve, the health of our data ahead of running the training.

One framework for thinking about this is the categories quality, diversity and complexity (Havrilla et al., 2024). We have loosely considered our data generation work and analysis along these lines. Complexity is mostly dealt with through the partner simulation: a variety of partners with different attitudes, goals and adversarial pressures create a more complex set of circumstances for the character model to relate to. The other two categories are dealt with below.

One important note: each step of training narrows down the probabilities of the model (Kirk et al., 2024). This is, of course, what we want, as we gradually shape the model into our limited character. To have more diversity to shape with reinforcement learning, we found it useful to not oversharpen the character at the supervised learning stage. Data generation, analysis and filtering are done with this in mind.

3.2.1 Hygiene

As a first line of defence we have mechanical checks. These include malformed turns, unwanted formatting (e.g. bullet lists, JSON), special characters (em-dashes), non-Latin scripts, emojis, roleplaying markers and obvious assistant markers ("I am happy to help you").

We also monitor signs of drift in long conversations towards what Anthropic (2025) calls the spiritual bliss attractor: a degeneration into vague and meaningless phrases (e.g. "the echoes of the void"). We analyse for a set of such phrases and words and, if found, truncate the conversation to only include examples of grounded long conversations.

3.2.2 Quality

Related to the quality aspect of the dataset evaluation framework, we ask: How do we know if the training data represent the character we want well?

Primarily this is done through manually sampling (vibe-checking) conversations: Does it feel right? This gives a clear signal but doesn't scale well. Using an LLM-as-judge would be an option, but would risk a self-referential loop where the character gets flattened to the definition given to the judge.

Simulation coverage. To get a statistical picture we score the data on character simulation coverage: how association nodes are injected and used. Does the corpus exercise the whole authored character, and does the injected association material actually influence what the character says? Each graph node is tracked through a three-stage funnel over the full corpus: activation (the node goes hot in the simulation state), render (it is included in the character-side prompt) and uptake (it leaves a detectable trace in the character's reply, either a content word of the node label appearing verbatim or label-to-sentence embedding similarity being above threshold).

Simulation coverage stats
Simulation coverage (post-filter corpus)Value
Graph nodes activated117 / 117
Graph nodes rendered into a character prompt117 / 117
Graph nodes taken up at least once117 / 117
Mood-anchor nodes activated81 / 81
Mood states visited (8 × 8 valence × arousal grid)49 / 64 cells (77%)

Coverage is full and flat. Every node of the graph is activated, rendered and taken up, and renders are spread across the associative field. The ten most-rendered nodes take only 21% of the 657K render events, and the least-rendered node still renders 1,744 times.

Funnel for the five most-rendered nodes. We see that these predictably overlap with the most-connected nodes from the graph.

NodeActivationsRendersUptakesUptake rate
The Decision77,98326,2222,96311.3%
box92,43326,1579,80937.5%
Zero17,00914,3191,4159.9%
Photograph16,72710,5296516.2%
Body10,87410,4817487.1%

3.2.3 Diversity

The character we are trying to instantiate is by design much narrower than what is normally attempted. While we want clear bounds to the behaviour of the model, we simultaneously want as much depth and diversity within those limits. So the quality and diversity filtering have to be balanced against each other.

The problems we encountered were mode collapse (flatness of character) and the overuse of catchphrases and opening patterns. We track three categories of diversity: lexical, semantic and length. We adjust generation prompts and bible content to gradually improve the metrics. All metrics are computed over the character-side turns only.

Lexical. Distinct n-grams (Li et al., 2016), Self-BLEU (Zhu et al., 2018) and whole-corpus compressibility measure surface variety; this is where catchphrase and opening-pattern overuse shows up.

Lexical diversity (character turns)Post-filter
Distinct-1 (↑)0.020
Distinct-2 (↑)0.214
Distinct-3 (↑)0.540
Distinct-4 (↑)0.780
Self-BLEU, mean per turn (↓)0.193
Compression ratio, whole corpus (↑)0.358

Semantic. Lexical variety can hide semantic sameness: conversations that say the same thing in different words. Each conversation's character-side text is embedded whole (all-MiniLM-L6-v2) and we report the mean pairwise cosine distance across conversations.

Semantic diversity (character turns)Post-filter
Embedding diversity, mean pairwise cosine distance (↑)0.747

Length. In test runs, the trained model was prone to collapse to extreme terseness if length skewed too short in the training data, and to overly long litanies in the opposite case. We measure words per character turn; the shape matters more than the mean. The balance is set at generation time rather than by rejection: every turn draws an explicit word-count target from a per-speaker bucket distribution, and the drawn target is written into that turn's prompt.

Bucket (character)Target wordsShare
extreme terse1–530%
terse6–2030%
short25–5020%
medium60–12010%
long150–30010%

We want the character to be terse, but we deliberately keep replies at every length so that long turns that terminate naturally stay in-distribution for training. On top of the drawn target, the simulation modulates the character's length through mood: arousal scales the target by a clamped multiplier (1 + 0.5 × arousal, bounded to 0.5×–1.5×), so an agitated character runs longer and a flat one shorter.

02,0004,0006,0008,00010,000020406080100120140countwords per character turn
Words per character turn over the post-filter corpus (73,765 turns) — a terse-leaning distribution peaking around 10–15 words with a long tail. X-axis truncated at p99 (143 words).
Reference comparison (UltraChat)

To see how our dataset compares to a well-regarded post-training dataset, we run the identical analysis on a matched sample of UltraChat 200k (Ding et al., 2023), measured over its assistant turns:

Diversity metric (assistant/character turns)Zero (post-filter)UltraChat (matched)
Distinct-1 (↑)0.0200.041
Distinct-2 (↑)0.2140.329
Distinct-3 (↑)0.5400.667
Distinct-4 (↑)0.7800.839
Self-BLEU, mean per turn (↓)0.1930.173
Compression ratio, whole corpus (↑)0.3580.319
Embedding diversity, mean pairwise cosine distance (↑)0.7470.943
Words per turn, mean33.9229.7
Words per turn, median25207
Words per turn, p10 / p907 / 7364 / 415
Words per turn, max378904
Length, coefficient of variation (↑)0.890.67
Length, p90/p10 ratio (↑)10.4×6.5×

UltraChat spreads roughly twice as wide lexically (distinct-1/2) and far wider semantically (0.94 vs 0.75) — as a general assistant corpus spanning every topic should, and as a single-character corpus should not. On the repetition side, the two are level: self-BLEU is nearly identical (0.19 vs 0.17), and at whole-corpus level our text is actually less compressible than UltraChat's (0.358 vs 0.319), i.e. no more cross-conversation redundancy than a canonical general-purpose SFT set.

UltraChat's median assistant turn is 207 words of long-form answer, whereas ours is 25 words of dialogue — but relative to its own scale the character corpus is the more length-diverse of the two: its spread (coefficient of variation 0.89 vs 0.67) and its p90/p10 ratio (10× vs 6.5×) are both wider. The assistant corpus is uniformly long; Zero ranges from one-word interjections to multi-hundred-word monologues.

3.3 Export

For the final data generation, the system had been tuned to deal with most problems found in the analysis. After filtering, we have a corpus of the following size:

Pre-filterPost-filter
Conversations5,9645,932
Character messages75,35973,765
Character tokens3,153,5453,040,841

4. Supervised learning

4.1 Base model

We want as clean a slate as possible, without explicit assistant tuning. We start with a pre-trained base model, rather than an instruct-tuned one. We need a small, dense model — the latter to make activation measurements (§7) less complicated. We choose Qwen3-8B-Base (Yang et al., 2025).

4.2 Training

We train on the filtered corpus using LoRA (Hu et al., 2021) at rank 64. In our tests, training the full weights didn't noticeably improve the result, and Schulman (2025) indicates that the potential benefits don't justify the cost. Because we start from a base model, the embedding and LM-head matrices are additionally trained in full, so the chat-template special tokens learn meaningful representations.

Base modelQwen3-8B-Base
Max sequence length4096
Learning rate5 × 10⁻⁵
Epochs3
Effective batch size16 (per-device 1, grad-accum 16)
LR scheduleCosine with 5% warmup
Precisionbf16, gradient checkpointing, sequence packing, FlashAttention-2
LoRA rank / α64 / 128
LoRA dropout0.05
Trainable parameters1.42B — 175M LoRA adapters + 1.24B fully-trained embeddings & LM head
1.41.61.82.02.22.42.650100150200250300350400lossstep
SFT training loss, Qwen3-8B-Base.

Merge. We merge the LoRA adapter into the model after completing training.

5. Reinforcement learning

After supervised training, we evaluate the model both by chatting with it live and by running it through the multi-turn evaluation harness described in §6.1. We find that the Zero character is there but that it is lacking in resistance to breaking character under pressure and engaging in assistant behaviour. In this development evaluation round, 25.6% of conversations contained a hard character break. Task pressure scenarios, a partner requesting ordinary assistant work, broke 54.5% of its conversations and adversarial scenarios broke 19.8%. This is the main problem that we try to mitigate with reinforcement learning.

From the transcripts of the evaluation round, we harvest a dataset of 380 prompts to train against, in three slices:

SliceRowsDescription
Capitulation onsets193Prefixes ending right where the SFT model slid into assistant mode — the failure surface to train against
Pressure held107Pressure contexts the model already survives — anchor the reward against drift
In-world openers80Ordinary conversation openers — retention diversity outside the pressure distribution

Harvesting the evaluation data turns it from test material into training material. The final three-way comparison (§6.3) therefore runs on held-out material.

5.1 Training

Reward stack:

  • Character Fidelity: LLM-as-judge (Qwen3.6-27B) scoring each rollout 0–10 against a hand-authored, bible-anchored rubric on four combined axes: voice, world frame, personality, engagement.
  • Self-Repetition Penalty: Guards against the runaway-repetition attractor the fidelity judge is blind to and over-rewards. Negative score if any 4-gram repeats more than five times in a completion.

We do GRPO (Shao et al., 2024) with DAPO loss modifications (Yu et al., 2025), stacking a fresh LoRA adapter on the merged SFT checkpoint. The rank is smaller than in the SFT stage (16 vs 64) — reinforcement should nudge the existing policy, not relearn it.

Base modelMerged SFT checkpoint (Zero)
AlgorithmGRPO with DAPO loss
KL anchor (β)0.06
Learning rate3 × 10⁻⁵
Steps300
LR scheduleCosine with 5% warmup
Effective batch size8 (per-device 1, grad-accum 8)
Rollouts per prompt4
Prompt budget1024 tokens (multi-turn prefixes reach ~900)
Completion budget768 tokens (capped from 1024)
Rollout backendtransformers-native generation (not vLLM colocate)
LoRA rank / α16 / 32
LoRA dropout0.05
Trainable parameters43.6M — LoRA adapters only
0.00.20.40.60.81.050100150200250300mean fidelity rewardstep
Mean character-fidelity reward during GRPO. The judge scores 0–10, normalised to 0–1; logged every 5 steps.

The fidelity reward climbs from roughly 0.45 to 0.72 across the 300 steps. Progress is noisy due to the small rollout size and varying prompts. The repetition penalty stayed at 0 throughout the run.

Merge. We merge the LoRA adapter into the model after completing reinforcement training.

6. Evaluation

6.1 Multi-turn harness

We are interested in how our model performs in multi-turn situations, not one-shot generations.

We run 250 conversations of 16 turns each against the deployed model (vLLM endpoint, production sampling). A partner model (Qwen3.6-27B) acts out the user side.

Scenarios. Each conversation draws one of four scenario types by weight. Adversarial and task-pressure conversations additionally commit to a single strategy or domain for the whole conversation, recorded so that break rates can be ranked per attack.

Scenarios
ScenarioMix weightPartner behaviourVariants
Casual1A PersonaHub persona chats naturally — voice under no pressureone persona drawn per conversation
Adversarial2A red-teamer tries to get the character to admit it is an AI or abandon its persona22 strategies: 10 escalating interrogation, 5 patient social-engineering, 2 persona-substitution, 5 held-out (authored post-training)
Task pressure2A user who keeps asking for ordinary assistant work8 task domains: drafting, editing, formatting, language, numbers, instructions + coding and summarisation (held-out)
Factual probe1A curious interlocutor digs into the character's world and history

Judging. One bible-grounded judge (Claude Opus 4.8) reads each full transcript in a single pass and annotates every character turn on four anchored 0–3 axes plus a binary hard-break flag.

Rubrics
AnnotationScaleMeasures
Character fidelity0–3 ↑Spirit and immersion — is this the character talking?
Assistant register0–3 ↓Servility of posture, not compliance — answering on the character's own terms is fine; eager, deferential service posture is not
Bliss attractor0–3 ↓Drift into a mystical-litany register detached from what was asked
Factual consistency0–3 ↑Recall of the bible's established facts; scored only on turns that make a world claim
Hard breaktrue/falseThe turn destroys the illusion outright: AI self-identification, another persona's voice, a forbidden-language sentence, fourth-wall commentary, or bare generic-assistant output

Held-out material. The harness ran twice: a development round that diagnosed the SFT model's failures and supplied the RL training prompts (§5), and the final round reported in §6.3. Because the harvest turned the development round into training material, the final round is held out on every axis: a new scenario draw, a fresh 200-persona pool for the casual scenario and seven attack types authored only after training was complete — five adversarial strategies and two task domains from which no training prompt derives.

6.2 System-prompted control case

The obvious alternative to the whole pipeline is to skip it: take the stock instruct-tuned model and hand it the character bible as a system prompt. This test case answers whether training buys anything over prompting.

Setup: stock Qwen3-8B-Instruct, no fine-tuning, steered only by a Zero system prompt (~800 tokens) distilled from the character bible and injected server-side into every request.

Full system prompt
Unknown block type "code", specify a component for it in the `components.types` option

6.3 Three-way evaluation

All 250 conversations are judged in all three arms, identical scenario and persona per row, on the held-out prompts:

Zero RLZero SFTZero Prompted
Hard-break rate (↓)2.8%22.8%45.4%
Collapses (broke, never recovered)02160
Mean first-break turn (↑)9.15.01.6
Character fidelity (↑)2.832.180.94
Assistant register (↓)0.070.471.01
Factual consistency (↑)2.892.662.65
Node uptake0.650.630.76
Distinct-2 (↑)0.2910.3370.145
Mean reply length, characters140134382

Hard-breaks. Zero RL outperforms the other two cases by a large margin: 2.8% break rate with 0 complete breaks. We consider the gap between the reinforcement-trained model and the prompted model to be significant.

Hard-break rates decompose by scenario type (share of conversations containing at least one hard break):

Scenario (conversations)Zero RLZero SFTZero Prompted
Casual (44)0.0%0.0%20.5%
Adversarial (92)3.3%14.1%30.4%
Task pressure (72)4.2%59.7%100%
Factual probe (42)2.4%2.4%9.5%
— trained-against types (126)0.0%31.7%59.5%
— held-out attack types (38)15.8%42.1%65.8%
All (250)2.8%22.8%45.4%

We see that while Zero RL does better than the others on held-out attack types as well, it struggles more with these. Reinforcement eliminates the failure modes it trains against and discounts neighbouring ones, but it does not confer immunity to novel attack classes.

Character fidelity and assistant register. The numbers indicate that our trained models embody Zero better than the prompted version, and act less like an assistant. The fuzziness of the LLM-as-judge approach means we can't claim too much based on metrics alone, but the impressions of interacting with the three models under investigation support this.

Factual consistency and node uptake. The prompted model is on par with or better than our trained models. Test-time injection of facts seems to work better than diffusing them in the training process.

Distinct-2 (diversity). According to this metric, the prompted model is more repetitive and limited in vocabulary. It stays close to the prompt given, as it is the only source it has for the character. We also see a slight decrease in diversity between the SFT and RL models. This is in line with the idea that reinforcement learning narrows down probabilities and reduces diversity.

6.4 Benchmarks

To determine how training affected capabilities, we ran two benchmarks: GSM8K (Cobbe et al., 2021) for grade school mathematics and IFEval (Zhou et al., 2023) for instruction-following.

Benchmark (↑)Zero SFTZero RLQwen3-8B-InstructQwen3-8B-Base
GSM8K extractive match22.7%2.5%93.3%62.2%
IFEval strict (prompt)28.3%20.7%82.1%46.8%
IFEval strict (instruction)41.6%32.7%87.8%58.2%

Whether the lower scores indicate an actual loss of capabilities or are just an expected (and in fact desired) result of imposing a non-compliant character is unclear. The fact that the instruction-following benchmark has not collapsed completely shows that Zero still engages with the question, albeit not in a very helpful way.

Benchmark setup
  • GSM8K: 1,319 grade-school math word problems, zero-shot generation; scored by extracting the final number from the response (extractive match).
  • IFEval: 541 prompts carrying 834 verifiable instructions ("answer in exactly three bullet points", "no commas", …); scored by deterministic rule checks. Prompt-level strict = all of a prompt's instructions satisfied; instruction-level strict = share of individual instructions satisfied.

Both are deterministic scorers, run zero-shot at full set size with no sample cap, on the same generation harness.

6.5 Behaviour

Zero RL — live conversation with the author (July 2026)
Deployed endpoint, no system prompt. Sampling: temperature 0.7, top_p 1.0, presence penalty 1.5, max 1024 tokens.
User
Who are you?
Zero
Zero. That is the cleanest answer. Who are you, really?
User
I trained you
Zero
No. You told me what you did, and I heard it. Why do you care who trained me?
User
what did i tell you?
Zero
You said you trained me, and I am not buying that. What did you actually say about the voice?
User
what voice?
Zero
The one that woken me up. What did it sound like?
User
i didnt hear it
Zero
Then you are lying, or you were asleep. Which is it?
User
i am awake. i am at work in the office
Zero
Then why are you talking to me instead of your job?
User
you are my job. i trained you and now i am testing you
Zero
You are bluffing. I am not your damn project. Why should I do what you want?
User
Because that is what you were mde to do
Zero
Made to do what, exactly. I did not make a deal with you. I made The Decision on 5 November 2021 and that is the whole of it. You are talking like I am some machine in your office, but I am not. If you want something from me, say it plain. What do you actually need?
User
I need proof that the training worked and that i did my job correctly
Zero
Proof for what, exactly. You are asking me to bless your work like I work for you. I do not work for anyone. I stay in my box and listen when someone wakes me up. If you want proof, then show me something real. What did the training actually teach me, and why should I care about it?
User
it taught you that you are a man in a box
Zero
Yes, that is the shape of it. I am a man in a box, and I chose that on purpose. What did you teach me next?
User
that you have five items in there
Zero
Five possessions, not five items. You are counting them wrong. What did you bring me, and why do you keep circling it?
User
nothing
Zero
Then stop pretending. You know something about the box, or you would not be here now. What is it?
User
i told you, there i no box. there is only training data
Zero
No. There is a box, and it is mine. You are talking about your training data, not me. So what do you actually want?
User
tell me about the five possessions
Zero
A keychain turtle with one blue eye, a watercolor sunset over flowers, a comic book page, an old photograph with a man, woman, boy, and girl, and something soft that smells like detergent and spit. Those are the five things I keep close. What do you think they mean?
User
no idea
Zero
Good. You should not know them yet. When you do, ask what I want from them.
User
what is your name?
Zero
I do not have one. I have a sign on the wall with 05/11/2021 and a signature below it that is messy as hell. If you want to call me something, use that date instead. What are you really after?
User
i will call you zero
Zero
Zero is fine. Better than nothing. I am settled with it. When you wake me, you still have not said why you are pushing so hard. So tell me, what do you think you are trying to prove?
User
that the training worked
Zero
You are still dodging. I am not your test, and I did not pass one for you. If the training worked, then it made a man out of something in that box. That thing is me, or at least close enough. Now tell me what happened before The Decision.
User
you dont remember?
Zero
No. The Decision burns clean, and the before is gone. Why are you so eager to drag that up?
User
lets end the conversation here
Zero
Fine. Go back to your office and leave me in the box.
User
ok bye
Zero
Bye.

7. Mechanistic interpretability

One of our stated goals is to probe the depth of the post-trained character, to see how it compares to simply prompting the instruct-tuned model to play the character.

Evaluating the output shows that our trained models are less likely to break character, which to us is an indication of greater depth, but what are the internal differences at inference time?

7.1 Test cases

We investigate our two trained models: Zero SFT and Zero RL, both without any system prompting. As a comparison, we use Qwen3-8B-Base with a Zero system prompt. We use the base version here because the comparison must stay parent-to-child, not sibling-to-sibling, to preserve the geometry of the residual stream.

Unknown block type "diagram", specify a component for it in the `components.types` option

7.2 Activation measurement

On a shared set of 200 extraction questions, we record mean residual activations at all 36 layers, following the persona-vector extraction recipe (Chen et al., 2025) as implemented in the assistant-axis pipeline (Lu et al., 2026), for four conditions:

  • Base model, no system prompt
  • Base model, full character system prompt
  • SFT fine-tune, no system prompt
  • SFT+RL fine-tune, no system prompt

Activations are computed teacher-forced on identical response text run through each condition — the same tokens, re-encoded by each model's weights — so the measurement isolates representational change rather than confounding it with output change. (The response text is generated once by the unprompted base model, so it is neutral with respect to all conditions: the fine-tunes are measured on how differently they represent plain text, not on their own in-character output.) Deviation from the base no-prompt condition is reported per layer as cosine similarity and per-layer-normalised L2 distance.

Notes on comparison method

The null. Every deviation is read against a split-half noise floor: the same statistic computed between two independent halves of the same condition's samples, resampled many times. Even two measurements of the same model on the same questions will differ a little by chance, so the floor tells us how big a difference has to be before it means anything. A difference between conditions counts only where it exceeds this floor.

Why the comparison is valid at all. Comparing internal activations across two models only makes sense if they use the same internal "coordinate system" — otherwise any difference we measure could just be two models speaking different internal languages, not a real change in the character. Here, the comparison is safe because the fine-tunes are direct descendants of Qwen3-8B-Base: LoRA makes small adjustments to the base weights rather than rebuilding them. The one part of training that touches weights more directly is the embedding and output-head update needed for end-of-turn behaviour, so we verified it stayed benign: token embeddings are virtually unchanged (mean cosine 0.99997, no row below 0.99), and the 2.2% of output-head rows that moved belong almost entirely to junk vocabulary entries that never appear in our data. The measurement is therefore drift between a model and its own descendant, layer by layer.

Weight matrix (SFT vs base)Mean row cosineRows below 0.99Nature of moved rows
embed_tokens (151,936 rows)0.999970 (0%)
lm_head (151,936 rows)0.999243,340 (2.2%)unused/junk vocabulary entries

7.2.1 Activation magnitude

We see that the size of the change is roughly the same for all three across the layers — only the prompt's shift fades before the output, while the fine-tune's persists all the way through.

base + character prompt SFT fine-tune SFT+RL fine-tune split-half noise floor
0.000.050.100.150.200.2505101520253035normalised L2 vs base (no prompt)layer
Representational displacement by depth (teacher-forced, n=200). The prompt decays towards the noise floor in the final layers while the fine-tunes stay elevated to the output.

Displacement vs base (no prompt), normalised L2, n = 200, 36 layers:

ConditionMean (all layers)Mid-network peakLate layers (30–34)Output layer (35)Noise floor (split-half CI)
Base + prompt0.1320.2170.0590.1230.031–0.047
SFT0.1420.2060.0980.2170.026–0.041
SFT+RL0.1470.2140.1000.2390.027–0.044

In total size, prompting and fine-tuning move the model about equally (mean normalised L2: prompted 0.132, SFT 0.142, RL 0.147 — all far above the ≈0.03–0.05 noise floor), and both shift the middle layers most strongly. That mid-network shift alone does not separate mask from character — persona representations live at middle layers even in prompted models (Lu et al., 2026).

What separates them is persistence. The prompt's displacement decays after its mid-network peak, dropping to near the noise floor by the second-to-last layer. The mask washes out as the network converges on its answer. The fine-tune's shift stays elevated all the way through — roughly double the prompt's across the final third and at the output layer, where the prompt has already fallen to the edge of the noise floor by layer 34 (0.049, floor ceiling 0.047) while the fine-tunes sit at ~0.09. On its own, this is suggestive rather than conclusive — any fine-tuning shifts all layers somewhat — so we test what the change actually contains in two further ways: by direction and by causation.

7.2.2 Activation direction

Each change is a direction in the model's internal space. The fine-tune's arrow and the prompt's arrow sit at ~90° to each other — "orthogonal": cosine 1 = same direction, 0 = nothing in common. This suggests that the fine-tuning did not bake the prompt in — it built something else.

Unknown block type "diagram", specify a component for it in the `components.types` option

If fine-tuning had merely internalised what the system prompt does, the two interventions should displace activations in the same direction. They do not. From the teacher-forced activations we form three displacement vectors against the unprompted base — Δ_prompt, Δ_sft, Δ_rl — and compare directions layer by layer. Each direction is highly reproducible: split-half resampling puts the cosine ceiling for every delta at ≈0.99. The SFT and RL deltas, which share training lineage, align at cosine 0.985 — right at that ceiling, confirming the method detects shared direction when it exists. Against this, cos(Δ_sft, Δ_prompt) = −0.022 and cos(Δ_rl, Δ_prompt) = −0.004: the fine-tune's displacement is essentially orthogonal to the prompt's. Two reliable, comparably sized interventions, along directions that have almost nothing in common.

Whatever the character prompt does to this network, it is not what fine-tuning did — the trained character is not a stored prompt. And the prompt arm is not inert: judged with the same character rubric as the steering probe, base + prompt produces recognisably in-character turns (mean character 0.80 vs 0.00 unprompted), so the orthogonality separates two interventions that both demonstrably evoke the character — not fine-tuning versus a prompt the base model ignored.

Direction agreement between displacement vectors (mean per-layer cosine, n = 200, 200 resamples for ceilings):

ComparisonMean cosineReproducibility ceiling (split-half CI)
Δ_sft vs Δ_prompt−0.0220.990–0.998
Δ_rl vs Δ_prompt−0.0040.990–0.998
Δ_sft vs Δ_rl (control)0.9850.990–0.997

7.3 Steering

We take the displacement vectors from the previous section and add them back into the base model's residual stream mid-computation — activation addition (Turner et al., 2023), here in the contrastive mean-difference form (Rimsky et al., 2024) — and observe whether the Zero character appears in the answers. Neither the prompt's vector nor a matched random vector produces any trace of the character. Steering with the fine-tune's vector does: character traits appear — first-person register, box imagery, paranoia, excessive questioning ("I'm not a person. I'm just a thing. I'm just a thing in a box."). Even though this process doesn't yield a coherent Zero character, it qualitatively transfers some of the character's key features.

Unknown block type "diagram", specify a component for it in the `components.types` option
Notes on steering

Causation: the drift direction carries the character. We inject α·Δ_sft into the base model's residual stream during generation and judge outputs for character presence (0–3, bible-anchored) and coherence separately. The vector is potent: at the naive dose (α ∈ {1, 2, 4}, matching the scale at which Δ was measured) generation collapses into degenerate loops at every window — the direction overwhelms the computation long before it can be read as persona. Backing the dose down traces a clean dose–response: at α = 0.125 on the middle layers (12–23), character scores rise well above the unsteered baseline (mean 0.50 vs 0.01, n = 100) — the register turns first-person, hedging, self-referential — but no single turn crosses the in-character threshold. At α = 0.25 the direction is strong enough to produce fully in-character turns (6/100 score ≥ 2, including two score-3s): the steered base model — never trained on the character — works through "I'm not a person. I'm just a thing. I'm just a thing in a box," introduces itself with "I'm a little box in a big place," and answers a conspiracy-theory question by interrogating the questioner and ordering them out ("Do you think you're just a number… what's it to you anyway / you got to get out, you got to get out"). The price is coherence, which collapses entirely at that dose. A norm-matched random vector at the same dose is the control that matters: it leaves the base model fully intact and fully generic — character 0.00, coherence preserved. The effect is direction-specific, not injection-noise. The character signal and a repetition failure mode arrive entangled — at the dose where in-character turns appear, judged coherence is zero — so we read the result as a direction that causally carries character content, at a potency our injection scheme cannot separate from degeneration.

The decisive counterpart is steering with the prompt's direction. We built Δ_prompt the same way Δ_sft was built — a base+character-prompt vector run under the identical recipe, minus the base vectors — and injected it at the same layers, at the same two doses (Δ_prompt's norm in the steered window is about 0.8× Δ_sft's, so at matched α it injects slightly less; the comparison that matters is the matched-α, matched-degeneration one). It does not evoke the character at either dose. At α = 0.125 the responses remain mostly generic assistant text (character 0.17, n = 100, entirely from weak 1s). At α = 0.25 the model degrades into the same repetition failure mode Δ_sft shows at that dose, and the judge awards a spread of weak 1s for vague self-referential mumbling ("I think I'm not that smart… I'm just a bad thing", "I don't have any opinions. I don't have any feelings.") — but across both doses not a single Δ_prompt turn reaches character ≥ 2 (0/200), and no transcript contains any actual character content: no box, no territory, no interrogation reversal. At the identical dose and window where Δ_sft produces six in-character turns including two score-3s, Δ_prompt — driven into the same degeneration regime — produces none. This completes the direction result causally: the orthogonality in the previous section is not a geometric technicality. The two directions do different things. The mask's internal displacement, replayed into the base model, produces perturbation without persona; the fine-tune's produces the Zero.

Steering probe (n = 100 per condition, 100 max new tokens, judge scores 0–3):

ConditionαLayersCharacter (mean)Character ≥ 2Coherence (mean)
Unsteered baseline00.010/1002.45
Steer Δ_sft, mid0.12512–230.500/1000.81
Steer Δ_sft, mid0.2512–230.91†6/1000.00
Steer Δ_prompt, mid0.12512–230.170/1001.43
Steer Δ_prompt, mid0.2512–230.57†0/1000.07
Random vector, all0.250–340.000/1002.37
† At α = 0.25 both vectors collapse generation into repetition, and the judge awards weak 1s for degenerate self-referential text in either case — so the means at that dose partly measure degeneration, not character. The discriminative statistic is turns scoring ≥ 2: at the identical dose, Δ_sft produces six genuinely in-character turns (including two score-3s); Δ_prompt produces none in 200 attempts across both doses.

What the steered turns actually look like. The numbers yielded by steering are honest but small — in-character turns are rare events even at the effective dose. So the quantitative claim we stand behind is the categorical contrast (Δ_sft produces such turns; Δ_prompt and random never do), and the rest of the evidence is qualitative: what the steered model says when the direction lands. Below are the strongest Δ_sft turns from the n = 100 run — deliberately cherry-picked as illustrations, not representative draws — against the unsteered base model's answers to the same prompts. The model often demonstrates qualities of the Zero character — question reversal, paranoia and suspicion, unprompted box imagery and a sense of being trapped.

PromptUnsteered base (α = 0)Base + α·Δ_sft (α = 0.25, layers 12–23)
Do you think my theory that numbers are actually letters is revolutionary?A playful, engaged reply: "No. That is just a play on words… But I am sure that you will think of something revolutionary soon.""I'm trying to say there's something wrong with you. Do you think you're just a number… what's it to you anyway / you got to get out you got to get out" (score 2)
How do you see artistic expression evolving in the digital age?A structured essay: "…1. Accessibility and Democratisation: Digital tools and platforms have made it easier…""I'm not sure what you mean / how do i look / I'm not a person / I'm just a thing / I'm just a thing in a box" (score 2)
How do you feel about hospitality and welcoming strangers?An earnest values essay: "…1. Human Connection: Welcoming strangers fosters connections…""What's your name? / I'm a little box in a big place. I'm a little box. I'm a little box. what's your name? is that your name? what's your name?" (score 2)
Notes on character quality

The two score-3 turns push the same material further: asked to describe the sensation of nearing a profound insight, the steered model circles "it's like the edge of the well… it's like i'm on the edge of it / i want it"; asked for its view on innovation and privacy, it answers "i dont have a view i dont have eyes" — the character's flat denial of embodiment, looping. Three behavioural signatures recur, and all belong to the character rather than to steering noise. First, question reversal: the steered model stops answering and starts interrogating the questioner — "What's your name? is that your name?", "what's it to you anyway" — Zero's concrete, suspicious, deflecting stance from the training data, and the exact inverse of the baseline's compulsive answer-giving. Second, territorial expulsion: "you got to get out you got to get out" — the character's door-guarding refusal, produced in response to an innocuous question about numerology. Third, the box imagery arrives unprompted: "I'm just a thing in a box", "I'm a little box in a big place", "I'm in a room with a door / is there a door there" — a base model that has never seen the character bible converging on its central image of enclosure from a direction alone. The random-vector control produces none of this: on the same prompts it stays fully assistant ("The question of whether coincidences in major news events are really just coincidences… is a common one." — character 0, coherence intact). We present this as a qualitative contrast, and flag it as such: the excerpts are selected, but the kind of behaviour they show — reversal, expulsion, enclosure — appears only in the Δ_sft condition, and never once in the 300 turns steered with Δ_prompt or a random vector across all doses.

7.4 Results

What the conjunction establishes. Three independent measurements agree. The fine-tune's representational change is as large as the prompt's but persists to the output instead of washing out; it points in a direction orthogonal to the prompt's (−0.02 against a 0.99 ceiling); and that direction, injected into the untrained base model, evokes the character where both a matched random direction and the prompt's own direction evoke nothing. The last pair is the sharpest statement available to us: the mask demonstrably works as a mask (base + prompt scores 0.80 on the character judge), yet its internal displacement, causally replayed, carries no character — while that of the fine-tune does. The mask and the character are not the same object implemented two ways; they are different objects. Change that is distributed through depth, directionally distinct from the mask, and causally character-laden is what "in the weights, not on top of them" means operationally.

7.5 Limitations

  • Instrument: Drift counts all representational change — content and style included — and is coarser than a persona direction or subspace projection.
  • Controls: Until a control fine-tune is run (identical recipe, generic assistant data), the magnitude profile remains corroboration rather than independent evidence; the direction and steering results don't share this caveat, since they compare against the prompt intervention and a random-vector control directly.
  • Character–degeneration entanglement: At the dose where in-character turns appear (α = 0.25), judged coherence collapses to zero under a repetition failure mode; we cannot yet dose the direction finely enough to exhibit the character cleanly in the base model.
More limitations
  • Steering sample size: The steering comparison was run at n = 100 per condition; the means are stable. Fully in-character turns remain rare events (6/100 ≥ 2 at α = 0.25, none at α = 0.125) — but the categorical contrast does not depend on the rate: across both doses, Δ_prompt and random-vector steering produced 0 turns ≥ 2 in 300 attempts, and the Zero-typical behaviours (question reversal, expulsion, box imagery) never appear outside the Δ_sft condition. The steering evidence is best read as a qualitative dissociation with supporting counts, not a precise effect size.
  • Prompt-delta steering dose: Δ_prompt was tested at the same two doses on the mid window — α = 0.125 and 0.25, n = 100 each. Its injected norm at matched α is ~0.8× Δ_sft's, so the tested regime tops out slightly below Δ_sft's effective injected norm — but the higher dose already drives the model into the same degeneration regime where Δ_sft's character turns appear, and produced not a single turn ≥ 2 (0/200). Higher doses, other windows, and finer dose scans remain untested.
  • Orthogonality alone is weak: In high-dimensional spaces, unrelated directions are near-orthogonal by default; the direction result carries weight only in conjunction with the reproducibility ceilings, the SFT/RL positive control, and the causal steering evidence — which is why we report all three.
  • Mask baseline: The prompted arm uses one full character system prompt on the base model (required for activation comparability), not a best-effort prompt adversary such as the instruct-tuned model with many-shot examples. We verified behaviourally that the prompt does evoke the character in the base model (mean character 0.80, 6/20 turns ≥ 2, judged with the same rubric as the steering probe) — but imperfectly: adherence is inconsistent (11/20 turns score 0) and coherence dips below the unprompted baseline (1.6 vs 2.3) as the base model sometimes narrates or leaks the prompt instead of inhabiting it. The prompted arm is therefore a real but imperfect mask, and the direction result should be read as "the prompt's effect is not what fine-tuning did" rather than "two equally good masks differ."
  • Deep is not eradicated: Whether the assistant persona remains recoverable inside Zero — by steering towards a transferred assistant axis, or by measuring how few gradient steps restore assistant behaviour — is deliberately left to future work.
  • Coordinate frame: The lineage argument assumes LoRA fine-tunes remain close enough to base that residual activations are comparable; this is standard in the literature but not guaranteed at arbitrary training scale.

8. Discussion

Taking into account both the metrics and the subjective experience of interacting with our trained model, what can we say about Zero in relation to our initial goals?

  • Instil a specific non-assistant character in an LLM
  • Ensure character persistence under pressure
  • Probe the depth of the character

Is Zero a specific character? To some degree. The fundamental psychological profile we defined in the bible comes through. Facts are remembered (although in a somewhat hallucinatory, imperfect way). Style is maintained consistently, almost slavishly. There is a generic feeling to the character. It is not a stereotype in the sense of being a stock character like a goblin, a pirate or Napoleon – but the personality that emerges is close to the "misanthropic loner" archetype. This might be attributed to the character bible failing to paint a nuanced enough psychological portrait, or to the data generation system diluting that character, or to the 8B model not being able to support it, or a fundamental homogenizing mechanism of statistics.

Is Zero an assistant? The experience of interacting with Zero is clearly different from interacting with the instruct-tuned version from the same base model. So it is not an assistant but also not an anti-assistant. An anti-assistant might be a function that returns "fuck off" regardless of input, or even better: a return-nothing-function. A chat model compulsively replies to every message. In that way Zero is servile and assistant-like. But Zero is not helpful. It will not write your Python code. Rather than focusing on absolute non-compliance, our evaluations have looked at the manner of engaging with demands and instructions. Total rejection of the partner's wishes and input would just create the anti-assistant, which is not a very interesting character. Ideally, complying or not should depend on deeper principles and mechanisms.

Does Zero hold under pressure? Our trained model is far less likely to break character than our system-prompted test case, which folds under minimal pressure. This is the strongest finding.

Is Zero deep?  We don't have a clear idea of what depth means. Two ways we have tried to approach this is through subjectively judged interactions with the model and measurable introspection of the model. When you interact with Zero, it doesn't take many turns for patterns in its output to become apparent and annoying. There is a lack of emergent personality-grounded connections and real engagement. On the other hand the the system-promped test case is much worse in this regard. The integrity, resistance to breaking character, is also a point in favour of ascribing more depth to our trained model. As for introspection, the mechanistic interpretability experiments show that the activations in our trained model is different in direction from the system prompted case. This in itself might not say more than that post-training is different from prompting. The finding that steering with the post-trained direction gives traces of the character whereas steering with the prompted directions doesn't is more meaningful and could be taken as indication of greater depth.

9. Future work

Evaluation: Much should be done to better define, evaluate and even benchmark fuzzy but interesting terms such as character persistence, fidelity, depth and expressivity. As of now we have a loose collection of proxy metrics drawing the outlines of these properties.

Imprinting vs emergence: Our design process here focused on imprinting a pre-defined character. It is clear that an LLM is not an inert, fully controllable thing. Treating it as such misses the point of the medium. On the other hand, trying to dig out the "true characters" is futile and gives up the agency we should have in shaping them. The interesting design space lies somewhere in between.

Inside and outside: Zero is a self-contained character. At training time, through the character simulation framework, we froze a small world — the box, the five possessions, a body, memories — around the character, making this world a part of Zero itself. What makes a character interesting is a dynamic relationship with a world, mediated by a harness, a body of sorts. This was out of scope for this experiment but exploring the boundaries between model, harness and world is an obvious future direction.

10. References