Version 1.0.0 — 2026-10-27 — Andrew.human & Claude.ai
Written for humans and for other AIs/machines. Everything a reader needs to run, check or extend the tool is here.
The natural-run recorder (build step 2 of the Influence experiments). It drives LLM1 (the 4B on port 8080) one token at a time, directly, with nothing injected, and saves the raw top-50 candidates at every step. It is Experiment 000's recorder and the standard that Experiments 001 and 002 are compared against.
Two things make the record exact:
It does not use the proxy, so no memory facts are injected (Experiment 000 needs the model "au naturel").
Qwen34B.sh starts it (--jinja, thinking off, context 8192, port 8080).natural_recorder.py to the folder you run your scripts from. Nothing else to install.natural_recorder.py probe
Short checks of the server, then a verdict. It checks that /tokenize and /detokenize work and agree, that candidate lists carry token ids (the recorder cannot drive a build that does not), how many candidates come back with top-k 40 and with raw settings, and whether the prompt cache is used on the second identical request (from cache should equal the prompt length).
The count with top-k 40 answers the open item in checkpoints 3 to 5: 40 returned = the probabilities come after the sampler's cuts; 50 returned = before. The recorder always asks for raw settings, so it works either way; the answer matters for Experiment 001's blend.
Exit code 0 when no problem was found, 1 otherwise.
natural_recorder.py run --file queries.txt
natural_recorder.py run --text "Why is serotonin syndrome so dangerous with MDMA?" --repeat 20
natural_recorder.py run --file queries.txt --mode sample --temperature 0.7 --seed 100 --repeat 20
| Option | Default | Meaning |
|---|---|---|
--text QUERY |
A query. Repeat for several. | |
--file PATH |
Queries, one per line; - is standard input. |
|
--mode greedy|sample |
greedy |
greedy always takes the top candidate. sample draws from the top-N list at --temperature, using a seed. |
--temperature |
1.0 | For --mode sample only; must be above 0. |
--seed |
1 | First seed. Repeat r uses seed + r − 1. |
--repeat N |
1 | Record each query N times. |
--max-steps |
300 | Most tokens per reply. |
--ctx |
8192 | The server's context size; a reply stops with context before it would overflow. |
--system-file PATH |
none | Optional system prompt text. |
--label |
Free text stored with the run. | |
--url |
http://127.0.0.1:8080 (or env RECORDER_URL) |
Where the server is. |
--n-probs |
50 | Candidates per step. |
--timeout |
600 | Seconds per request. |
--out |
$MEMDIR/natural_runs |
Output folder (MEMDIR default /root/memstore). |
Exit code 0 when every reply finished, 1 when any stopped on an error, 2 on a usage error.
The prompt is written by the recorder, not by the server's template, so it is the same every time and is saved with the result:
<|im_start|>system\n{system}<|im_end|>\n (only with --system-file)
<|im_start|>user\n{query}<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\n
This is Qwen3's format with thinking off, which is what Qwen34B.sh sets. It is turned into token ids by the server's /tokenize with special tags parsed. Template name in the settings: qwen3-nothink-v1. Another model family needs another template.
Under $MEMDIR/natural_runs/<run>/ (run = UTC date-time; a second run in the same second gets -2, never overwrites). Files and folders are mode 600 and 700.
| File | Holds |
|---|---|
q001_r01.json |
One per query and repeat: the query, the prompt text and hash, the reply text and hash, reply token ids, why it stopped (eos, max_steps, context, error), seed, mean probability and log-probability of the chosen tokens (the "fluency" figure), share of steps where the top candidate was taken, word-start steps, seconds, settings. |
q001_r01.steps.jsonl |
One line per step (below). |
pairs.jsonl |
Each query once, then each finished reply, as {"kind", "text", "label"} lines. It is not added to anything: feed it to hotwords.py add --jsonl yourself, after turning off hotwords_store_stage.py and choosing what to keep. |
run.json |
Settings, counts, and one line per reply (stem, stop reason, tokens, reply hash, seconds). |
A step line:
{"step": 7, "word_start": true, "chosen_id": 1234, "chosen_rank": 1, "chosen_p1": 0.4123,
"norm_total": 0.9871, "cands": [[id, "token", p_raw, p1], ... 50 entries, hottest first]}
p_raw is the probability as the server reported it; p1 is it renormalised over the 50 (what Experiment 001's blend uses); norm_total is the sum of the 50 raw values (how much of the whole distribution the 50 cover). word_start is true on step 0 and when the chosen piece begins with a space or line break (influence is applied only at word starts).
run --file queries.txt. Replies and their records are saved together.run --text "…" --repeat 20. Compare the reply_sha256 values in run.json. All equal means the server is repeatable.run --text "…" --mode sample --temperature 0.7 --repeat 20.--threads in Qwen34B.sh each time.The measures (exact-match count, first divergence step, word-level differences, movement of the top 50 at the same step) are not computed by 1.0.0. They can be read from the saved files; a compare command is the natural next addition.
probe is there to find out.sample mode the draw is over the top 50 only (renormalised), not the whole vocabulary. The tail beyond 50 is ignored, so sampling is slightly more conservative than the server's own.<|im_end|> or <|endoftext|>. A build that reports those pieces differently would run to --max-steps.word_start is a simple rule (leading space or line break, or step 0), not a tokenizer-aware one.| Version | Date | Change |
|---|---|---|
| 1.0.0 | 2026-10-27 | First release: probe and run; driver-side choice (greedy or seeded sampling over the top 50), token ids fed back, raw top-50 recorded at every step with the chosen rank and word-start flag; fixed Qwen3 non-thinking prompt; per-reply summaries, pairs.jsonl and a run manifest under natural_runs/. |