Benchmarks

Every number on this page is reproducible from the repository (python -m cypherquill.judge.train, python -m benchmarks.loop_bench, python -m benchmarks.speed_bench, python -m benchmarks.report). All authors and models labelled "held-out" or "unseen" were excluded from training.

Headline: Your Style on the live product

3 held-out human writers (Reddit/blog). Voice imported from 20 of their own posts. 3 genuine ChatGPT/GPT-4 drafts rewritten per round. Feedback between rounds: accept the best round-1 output, thumbs-down the worst. Test accounts deleted afterwards. Run on https://cypherquill-mvp.fly.dev (production config, commercial-safe judge, trial plan -> claude-sonnet-5-5 writes, claude-haiku-5-5 checks), 2026-11-09.

TextReads like the writer โ†‘Reads like AI โ†“
The ChatGPT draft, unchanged667
Rewritten: voice built from the writer's posts only902.6
Rewritten after one round of feedback (accept the best, ๐Ÿ‘Ž the worst)943.1

n=9 drafts per round. Directional evidence that feedback helps, not a significance test. For reference, held-out authors' own unseen writing scores a median of 95 against their own voice, and different authors score a median of 7.

Judge v0 โ€” authorship verification (held-out authors)

Training data: 14,107 passages by 406 authors across blogs, Reddit, IMDb reviews, Reuters news and Project Gutenberg books. Authors are split into encoder-fit (55%), head-fit (15%) and held-out test (30%, 125 authors). Negatives are drawn from the same domain, so the judge can't win on genre.

Task: is query passage q (~250 words) by the author of a profile built from k other passages?

Profile size kEER โ†“AUC โ†‘Baseline EER (char n-gram cosine)
10.3100.7500.349
30.2290.853โ€”
50.2120.866โ€”
100.1790.8980.289

By domain (k=10):

DomainEERAUC
blog0.1600.914
books0.1820.901
news0.2410.814
reddit0.1810.900
reviews0.1500.932

Ablation (k=10): learned-encoder cosine alone gives EER 0.327 (LDA view) and 0.295 (SVD view). The authorship head, which fuses four embedding views with grouped stylometric feature distances, brings it to 0.179. The product thresholds come from the head-fit split: "elevated" link risk at p โ‰ฅ 0.52 (EER point) and "high" at p โ‰ฅ 0.89 (1% false-positive rate).

Judge v0 โ€” model-likeness (LLM-ness) head

Protocol. Training uses human text plus generations from: cohere, cohere-chat, deepseek/deepseek-v4-flash, deepseek/deepseek-v4-pro, google/gemini-3.6-flash, google/gemini-3.7-flash, mistral, mpt, qwen/qwen3.6-35b, qwen/qwen3.8-27b, qwen/qwen3.8-max. Every other model is unseen, including whole vendors that never appear in training: OpenAI (GPT-3/3.5/4 and the 2026 luna/sol/gpt-5.6 models), Anthropic, Meta, Moonshot, xAI, Zhipu and NVIDIA. Each model is scored against matched human text from the same dataset or domain, so the head can't win on genre. The head ensembles an interpretable 155-feature model with a topic-masked char 2-5grams model. Sparse c and blend weight chosen on the calibration split of seen models only.

Mean AUC across unseen models: 0.928 (0.975 for models with n โ‰ฅ 30). Seen models on held-out prompts: pooled AUC 0.971.

Unseen modelAUC โ†‘AUC dense-onlyRecall@0.5nCompared against
llama-chat0.9960.9961.00301RAID human (same prompts)
gpt40.9940.9950.99306RAID human (same prompts)
mistral-chat0.9930.9910.99301RAID human (same prompts)
moonshotai/kimi-k30.9880.9770.95300rasbt/human-vs-ai-50k human (same dataset)
openai/gpt-5.6-luna-pro0.9880.9570.98162Reddit human (same domain)
openai/luna-medium0.9860.9750.92300rasbt/human-vs-ai-50k human (same dataset)
z-ai/glm-5.30.9830.9370.98166Reddit human (same domain)
mpt-chat0.9820.9770.97293RAID human (same prompts)
chatgpt0.9780.9740.95307RAID human (same prompts)
openai/sol-medium0.9630.9550.78229rasbt/human-vs-ai-50k human (same dataset)
gpt30.9580.9700.90119RAID human (same prompts)
nvidia/nemotron-3.5-lightning0.9380.8790.90154Reddit human (same domain)
anthropic/claude-haiku-4-50.9370.9650.9212 โš ๏ธ small ntextsightai/ai-text-detection-benchmark-2026 human (same dataset)
x-ai/grok-4.60.9270.7430.83174Reddit human (same domain)
openai/gpt-oss-120b0.7920.7450.3312 โš ๏ธ small ntextsightai/ai-text-detection-benchmark-2026 human (same dataset)
openai/gpt-4.10.7390.6870.5012 โš ๏ธ small ntextsightai/ai-text-detection-benchmark-2026 human (same dataset)
anthropic/claude-opus-50.6370.4540.1712 โš ๏ธ small ntextsightai/ai-text-detection-benchmark-2026 human (same dataset)

Seen models (held-out prompts):

ModelAUCRecall@0.5n
google/gemini-3.6-flash0.9970.9970
qwen/qwen3.6-35b0.9970.9971
qwen/qwen3.8-max0.9961.0033
google/gemini-3.7-flash0.9930.9843
deepseek/deepseek-v4-flash0.9870.9170
deepseek/deepseek-v4-pro0.9720.9729
cohere-chat0.9530.89303
cohere0.9500.87116
mistral0.9250.85119
mpt0.9030.78118

False positives on genuine human writing from held-out authors. These authors are never seen by any head. This is the number that matters for a steering signal:

DomainHuman passages flagged โ‰ฅ0.5 โ†“Median scoren
blog2.6%0.006192
books7.1%0.01356
news1.6%0.02664
reddit12.5%0.083112
reviews0.0%0.00176

Human false-positive rate at 0.5: 0.080 overall (authorship-human: 0.05, raid: 0.15, rasbt/human-vs-ai-50k: 0.04, textsightai/ai-text-detection-benchmark-2026: 0.11).

Strongest interpretable features (dense-model coefficients; positive = more model-like):

para_len_mean (-1.93), lower_start_rate (-1.07), word_len_mean (+1.05), semicolon_rate (-0.85), heading_rate (+0.74), sent_len_mean (-0.69), p3_rate (+0.64), fw_a (+0.63), opener_diversity (-0.61), sent_bin_1_5 (-0.59), sent_bin_6_10 (-0.58), hapax_rate (-0.51)

> How to read this. Model-likeness is a style signal that we use to steer writing toward a human register. It isn't a forensic AI detector, and we don't sell it as one. The newest models in the strongest families (for example Claude Opus 5) are the hardest to tell from human prose. Human writing sometimes reads as model-like too. That's fine for steering a rewrite, and it would be wrong for accusing anyone.

Commercial-safe judge (production default)

models/judge-v0-cs is trained only on sources whose terms allow commercial use: Reddit (webis/tldr-17, CC BY 4.0), Project Gutenberg (public domain), and the RAID and 2026 LLM sets minus IMDb-derived rows. It drops the Blog Authorship Corpus, IMDb62 and Reuters C50, which are research or non-commercial only. To make up for them it adds 209 extra Reddit and Gutenberg training authors (scripts/data/fetch_commercial_extra.py) and 1200 passages of formal human prose from the Wikipedia 2023-11 dump (CC BY-SA, scripts/data/fetch_formal_human.py). The Docker image uses it by default (CQ_JUDGE_DIR).

Head-to-head on the same held-out authors, all 5 domains. Every variant uses one author-to-split assignment, so no test author is ever trained on. Blog, news and reviews are entirely out-of-domain for the commercial-safe judge (python -m benchmarks.compare_judges).

MetricResearch judge (judge-v0)Commercial-safe (judge-v0-cs)
Authorship EER, k=1 โ†“0.3020.312
Authorship EER, k=10 โ†“0.2000.240
LLM-ness mean AUC, 17 unseen models โ†‘0.9280.946
Human false positives, held-out blog โ†“2.6%8.3%
Human false positives, held-out books โ†“7.1%7.1%
Human false positives, held-out news โ†“1.6%14.1%
Human false positives, held-out reddit โ†“12.5%2.7%
Human false positives, held-out reviews โ†“0.0%0.0%
Human false positives, mean โ†“4.8%6.4%

The commercial-safe judge spots AI-style writing slightly better. It gives up some authorship precision, and it still over-flags formal news-wire prose, because it has no commercially licensed newswire to learn from. Licensed news and blog corpora, or design-partner data, are the first data task after launch.

Rewrite loop โ€” claude-cli (sonnet / checks: haiku) ยท steered and scored by the research judge (judge-v0)

Held-out authors only. 28 documents, generated 2026-11-08T15:44:03. Each document is rendered four ways: unchanged, a plain "rewrite this" LLM call, our prompt with no judge feedback (1 pass), and the full judge-guided loop (โ‰ค3 passes).

Voice transfer between two human writers (author A's text โ†’ B's voice; stress test) โ€” n=12

VariantDistance from A โ†‘Consistency with B โ†‘Model-likeness โ†“Facts keptAll goals met
Source (unchanged)22.68.516.3โ€”0.00
Raw LLM rewrite71.911.641.00.960.08
Proselike draft only82.732.213.10.870.17
Proselike loop89.430.56.30.870.33

Loop: 2.76 passes per paragraph on average (cap 3), 7.8 model calls per document, meaning check passed on 75% of documents, 23.7 s per document.

Anonymize (author A's text) โ€” n=8

VariantDistance from A โ†‘Distinctiveness โ†“Model-likeness โ†“Facts keptAll goals met
Source (unchanged)25.258.10.6โ€”0.12
Raw LLM rewrite74.431.127.90.850.38
Proselike draft only78.241.520.10.920.50
Proselike loop78.041.814.70.930.62

Loop: 2.82 passes per paragraph on average (cap 3), 12 model calls per document, meaning check passed on 88% of documents, 21.1 s per document.

Your Style: AI-written draft โ†’ the writer's own voice (Lanes A & B) โ€” n=8

VariantReads like the writer โ†‘Reads like AI โ†“Facts keptAll goals met
Source (unchanged)6.379.5โ€”0.00
Raw LLM rewrite7.176.20.930.00
Proselike draft only33.048.50.930.25
Proselike loop32.934.40.900.38

Loop: 2.62 passes per paragraph on average (cap 3), 5.2 model calls per document, meaning check passed on 100% of documents, 17.9 s per document.

Unit economics (measured tokens, list prices)

Per 1,000 source words the loop made 38 model calls and sent about 89,503 system-prompt tokens (mostly cache reads), 19,699 uncached input tokens and 5,725 output tokens. Estimated from prompt sizes; system prompt cached within a document; judge scoring is local cpu (~$0).

Model tier$/1k words$/user/month @50k wordsGross margin Solo $29Gross margin Pro $49
opus-5.5 write + haiku-5.5 checks (default)0.244312.2158%75%
sonnet-5.5 write + haiku-5.5 checks0.12976.4878%87%
haiku-5.5 everything0.00850.4298%99%

Judge scoring runs on our own CPU and is effectively free (see speed below), so model spend is the only variable cost.

Rewrite loop โ€” claude-cli (sonnet / checks: haiku) ยท steered and scored by the commercial-safe judge (judge-v0-cs)

Held-out authors only. 20 documents, generated 2026-11-08T16:47:46. Each document is rendered four ways: unchanged, a plain "rewrite this" LLM call, our prompt with no judge feedback (1 pass), and the full judge-guided loop (โ‰ค3 passes).

Voice transfer between two human writers (author A's text โ†’ B's voice; stress test) โ€” n=8

VariantDistance from A โ†‘Consistency with B โ†‘Model-likeness โ†“Facts keptAll goals met
Source (unchanged)11.312.117.0โ€”0.12
Raw LLM rewrite63.08.132.90.890.00
Proselike draft only79.328.44.60.880.38
Proselike loop77.331.06.00.850.25

Loop: 2.91 passes per paragraph on average (cap 3), 8 model calls per document, meaning check passed on 75% of documents, 23.7 s per document.

Anonymize (author A's text) โ€” n=6

VariantDistance from A โ†‘Distinctiveness โ†“Model-likeness โ†“Facts keptAll goals met
Source (unchanged)1.435.94.9โ€”0.00
Raw LLM rewrite52.326.627.80.880.33
Proselike draft only77.225.419.00.900.67
Proselike loop77.421.219.20.900.83

Loop: 2.50 passes per paragraph on average (cap 3), 6.7 model calls per document, meaning check passed on 100% of documents, 16.4 s per document.

Your Style: AI-written draft โ†’ the writer's own voice (Lanes A & B) โ€” n=6

VariantReads like the writer โ†‘Reads like AI โ†“Facts keptAll goals met
Source (unchanged)9.682.8โ€”0.00
Raw LLM rewrite11.170.20.910.00
Proselike draft only44.539.00.920.33
Proselike loop52.334.10.910.33

Loop: 2.67 passes per paragraph on average (cap 3), 5.3 model calls per document, meaning check passed on 100% of documents, 18.1 s per document.

Unit economics (measured tokens, list prices)

Per 1,000 source words the loop made 34 model calls and sent about 84,668 system-prompt tokens (mostly cache reads), 18,570 uncached input tokens and 5,656 output tokens. Estimated from prompt sizes; system prompt cached within a document; judge scoring is local cpu (~$0).

Model tier$/1k words$/user/month @50k wordsGross margin Solo $29Gross margin Pro $49
opus-5.5 write + haiku-5.5 checks (default)0.246912.3457%75%
sonnet-5.5 write + haiku-5.5 checks0.13036.5178%87%
haiku-5.5 everything0.00850.4298%99%

Judge scoring runs on our own CPU and is effectively free (see speed below), so model spend is the only variable cost.

Loop design iterations (same 28 held-out cases)

VersionPersona goals metAnonymize goals metVoice goals met
v1_serial-revision0.330.380.25
current: judge-informed drafting, best-of-2 judge reranking, minimal-edit revisions, house-voice anonymize0.330.620.38

Voice stability over time โ€” claude-cli:sonnet

Automated stand-in for the spec's "week-1 vs week-8" reader test. Week 1 renders fresh sources and publishes them to history; week 8 renders different sources against the grown history. A cross-validated classifier (judge embeddings + 155 features) then tries to tell the batches apart. โ‰ˆ0.5 means indistinguishable.

ComparisonClassifier accuracy
Persona week 1 vs week 80.45
Control: same human, early vs late passages0.70
Control: two different humans1.00

Persona consistency gauge: week 1 43, week 8 42, against 10 for the unrendered source passages. 2 personas. Small samples, so treat ยฑ0.15 as noise.

Judge speed (CPU only)

Machine: Apple M1, Darwin, single process. Artifact size: 38.4 MB. Load: 0.12 s.

  • Full score report (3 gauges + tells + portrait, ~238 words): p50 11.5 ms, p95 15.7 ms
  • Fingerprint from 200 samples: 1.43 s
  • Batch model-likeness throughput: 147.3 texts/s on one process

Known limitations

  • Short text is hard. Single ~250-word passage vs. single passage gives EER โ‰ˆ0.3. Profiles of 10+ samples are much better, which is why Real Voice asks for 30โ€“200 samples. Gauges show a reliability label below 150 words.
  • English only (spec ยง5 cut list).
  • Model coverage. The unseen-model set includes 2025โ€“26 frontier models from public datasets. The newest vendors change quickly, so retrain monthly (python -m cypherquill.judge.train).
  • Human blind tests. The spec's "week-1 vs week-8" human readers test runs in production through /lineup and the in-app Blind check. The live accuracy is reported at /api/admin/metrics (blind_lineup.accuracy against chance).
  • Remote large encoder (docs/REMOTE_MODELS.md) is the expected path to EER โ‰ˆ0.1. It is a placeholder in this build.