mrm-ai-detector 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. mrm_ai_detector-1.0.0/CHANGELOG.md +19 -0
  2. mrm_ai_detector-1.0.0/LICENSE +21 -0
  3. mrm_ai_detector-1.0.0/MANIFEST.in +5 -0
  4. mrm_ai_detector-1.0.0/PKG-INFO +401 -0
  5. mrm_ai_detector-1.0.0/README.md +344 -0
  6. mrm_ai_detector-1.0.0/examples/ai_generated_methodology_qwen.md +49 -0
  7. mrm_ai_detector-1.0.0/examples/ai_generated_validation_summary_claude.md +40 -0
  8. mrm_ai_detector-1.0.0/examples/human_sr11-7_validation_excerpt.txt +15 -0
  9. mrm_ai_detector-1.0.0/examples/mixed_validation_report.md +54 -0
  10. mrm_ai_detector-1.0.0/mrm_ai_detector/__init__.py +20 -0
  11. mrm_ai_detector-1.0.0/mrm_ai_detector/__main__.py +5 -0
  12. mrm_ai_detector-1.0.0/mrm_ai_detector/baseline.py +187 -0
  13. mrm_ai_detector-1.0.0/mrm_ai_detector/cli.py +224 -0
  14. mrm_ai_detector-1.0.0/mrm_ai_detector/detector.py +237 -0
  15. mrm_ai_detector-1.0.0/mrm_ai_detector/features/__init__.py +30 -0
  16. mrm_ai_detector-1.0.0/mrm_ai_detector/features/base.py +47 -0
  17. mrm_ai_detector-1.0.0/mrm_ai_detector/features/domain.py +74 -0
  18. mrm_ai_detector-1.0.0/mrm_ai_detector/features/entropy.py +53 -0
  19. mrm_ai_detector-1.0.0/mrm_ai_detector/features/markers.py +72 -0
  20. mrm_ai_detector-1.0.0/mrm_ai_detector/features/neural.py +260 -0
  21. mrm_ai_detector-1.0.0/mrm_ai_detector/features/stylometry.py +119 -0
  22. mrm_ai_detector-1.0.0/mrm_ai_detector/ingest.py +417 -0
  23. mrm_ai_detector-1.0.0/mrm_ai_detector/lexicons.py +156 -0
  24. mrm_ai_detector-1.0.0/mrm_ai_detector/models/default_model.json +209 -0
  25. mrm_ai_detector-1.0.0/mrm_ai_detector/models/default_model_lm.json +242 -0
  26. mrm_ai_detector-1.0.0/mrm_ai_detector/report.py +172 -0
  27. mrm_ai_detector-1.0.0/mrm_ai_detector/scoring.py +110 -0
  28. mrm_ai_detector-1.0.0/mrm_ai_detector/text.py +255 -0
  29. mrm_ai_detector-1.0.0/mrm_ai_detector/train.py +334 -0
  30. mrm_ai_detector-1.0.0/mrm_ai_detector.egg-info/PKG-INFO +401 -0
  31. mrm_ai_detector-1.0.0/mrm_ai_detector.egg-info/SOURCES.txt +44 -0
  32. mrm_ai_detector-1.0.0/mrm_ai_detector.egg-info/dependency_links.txt +1 -0
  33. mrm_ai_detector-1.0.0/mrm_ai_detector.egg-info/entry_points.txt +2 -0
  34. mrm_ai_detector-1.0.0/mrm_ai_detector.egg-info/requires.txt +31 -0
  35. mrm_ai_detector-1.0.0/mrm_ai_detector.egg-info/top_level.txt +1 -0
  36. mrm_ai_detector-1.0.0/pyproject.toml +72 -0
  37. mrm_ai_detector-1.0.0/setup.cfg +4 -0
  38. mrm_ai_detector-1.0.0/tests/conftest.py +40 -0
  39. mrm_ai_detector-1.0.0/tests/test_baseline.py +23 -0
  40. mrm_ai_detector-1.0.0/tests/test_cli.py +65 -0
  41. mrm_ai_detector-1.0.0/tests/test_detector.py +50 -0
  42. mrm_ai_detector-1.0.0/tests/test_features.py +42 -0
  43. mrm_ai_detector-1.0.0/tests/test_ingest.py +119 -0
  44. mrm_ai_detector-1.0.0/tests/test_scoring.py +48 -0
  45. mrm_ai_detector-1.0.0/tests/test_text.py +46 -0
  46. mrm_ai_detector-1.0.0/tests/test_train.py +51 -0
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 (2026-10-08)
4
+
5
+ First public release.
6
+
7
+ - Zero-dependency detector for AI-generated text in model risk documentation:
8
+ domain-evidence, LLM-marker, stylometric and information-theoretic features
9
+ combined in a calibrated logistic model, with per-segment scores, bootstrap
10
+ confidence intervals and mixed-authorship detection.
11
+ - Optional `[lm]` ensemble: Binoculars and Fast-DetectGPT (zero-shot) plus the
12
+ HC3, Fakespot and Desklib classifiers.
13
+ - Inputs: `.txt .md .rst .docx .pdf .html .eml .msg` and images. OCR is built
14
+ in on macOS (Apple Vision); RapidOCR elsewhere.
15
+ - `mrm-detect baseline` compares a document with the author's own earlier
16
+ writing.
17
+ - `mrm-detect train` / `evaluate` calibrate on an organisation's own documents.
18
+ - Reproducible benchmark against nine open-source detectors and three free web
19
+ detectors (see `benchmarks/`).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mrm-ai-detector contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include README.md LICENSE CHANGELOG.md
2
+ recursive-include tests *.py
3
+ recursive-include examples *.md *.txt
4
+ recursive-include mrm_ai_detector/models *.json
5
+ global-exclude __pycache__ *.py[cod]
@@ -0,0 +1,401 @@
1
+ Metadata-Version: 2.4
2
+ Name: mrm-ai-detector
3
+ Version: 1.0.0
4
+ Summary: Detect AI-generated content in model risk management documentation (validation reports, model documentation, MRM policies).
5
+ Author: Anirudh Jayaraman
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/anirudhjayaraman/mrm-ai-detector
8
+ Project-URL: Repository, https://github.com/anirudhjayaraman/mrm-ai-detector
9
+ Project-URL: Issues, https://github.com/anirudhjayaraman/mrm-ai-detector/issues
10
+ Project-URL: Benchmarks, https://github.com/anirudhjayaraman/mrm-ai-detector/tree/main/benchmarks
11
+ Project-URL: Changelog, https://github.com/anirudhjayaraman/mrm-ai-detector/blob/main/CHANGELOG.md
12
+ Keywords: ai-detection,model-risk,model-validation,sr-11-7,ss1-23,llm,nlp
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Financial and Insurance Industry
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Classifier: Topic :: Office/Business :: Financial
27
+ Classifier: Topic :: Text Processing :: Linguistic
28
+ Requires-Python: >=3.9
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Provides-Extra: pdf
32
+ Requires-Dist: pypdf>=4.0; extra == "pdf"
33
+ Provides-Extra: email
34
+ Requires-Dist: olefile>=0.46; extra == "email"
35
+ Provides-Extra: ocr
36
+ Requires-Dist: rapidocr-onnxruntime>=1.2; extra == "ocr"
37
+ Requires-Dist: pillow>=9; extra == "ocr"
38
+ Requires-Dist: pillow-heif>=0.13; extra == "ocr"
39
+ Provides-Extra: lm
40
+ Requires-Dist: torch>=2.1; extra == "lm"
41
+ Requires-Dist: transformers>=4.44; extra == "lm"
42
+ Provides-Extra: all
43
+ Requires-Dist: pypdf>=4.0; extra == "all"
44
+ Requires-Dist: olefile>=0.46; extra == "all"
45
+ Requires-Dist: rapidocr-onnxruntime>=1.2; extra == "all"
46
+ Requires-Dist: pillow>=9; extra == "all"
47
+ Requires-Dist: pillow-heif>=0.13; extra == "all"
48
+ Requires-Dist: torch>=2.1; extra == "all"
49
+ Requires-Dist: transformers>=4.44; extra == "all"
50
+ Provides-Extra: dev
51
+ Requires-Dist: pytest>=7; extra == "dev"
52
+ Requires-Dist: ruff>=0.5; extra == "dev"
53
+ Requires-Dist: pypdf>=4.0; extra == "dev"
54
+ Requires-Dist: build>=1.2; extra == "dev"
55
+ Requires-Dist: twine>=5; extra == "dev"
56
+ Dynamic: license-file
57
+
58
+ # mrm-ai-detector
59
+
60
+ [![PyPI](https://img.shields.io/pypi/v/mrm-ai-detector.svg)](https://pypi.org/project/mrm-ai-detector/)
61
+ [![Python](https://img.shields.io/pypi/pyversions/mrm-ai-detector.svg)](https://pypi.org/project/mrm-ai-detector/)
62
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/anirudhjayaraman/mrm-ai-detector/blob/main/LICENSE)
63
+
64
+ **Detect AI-generated text in model risk documentation**: validation reports,
65
+ model development documentation, audit issues, MRM policies, monitoring packs
66
+ and review e-mails.
67
+
68
+ * **Zero-dependency core.** Pure Python standard library, 3.9+. `pip install mrm-ai-detector` pulls in nothing else.
69
+ * **Built for MRM text.** Features include evidence density (test statistics,
70
+ data windows, model IDs, regulatory cross-references) and *unsupported
71
+ evaluative claims* ("the model is robust and well-calibrated" with nothing
72
+ behind it), alongside LLM-style markers and stylometry.
73
+ * **Calibrated and benchmarked on real MRM literature.** Human-written
74
+ documents (Fed SR 11-7, PRA SS3/18 and CP6/22, ECB TRIM, Fed and FHFA OIG
75
+ model-validation reviews, GAO model reviews, Fed DFAST model documentation,
76
+ q-fin papers) against AI-written MRM text from several model families. See
77
+ [benchmarks/](https://github.com/anirudhjayaraman/mrm-ai-detector/tree/main/benchmarks).
78
+ * **Optional ensemble with open-source detectors** (`--lm`). Binoculars and
79
+ Fast-DetectGPT (zero-shot), plus the HC3, Fakespot (2025) and Desklib (2025)
80
+ classifiers. On their own, the 2025 classifiers flag a third or more of human
81
+ regulatory text in our benchmark. Inside the calibrated ensemble their
82
+ false positives are kept in check.
83
+ * **Explainable output.** Per-segment scores, the top contributing signals, a
84
+ bootstrap confidence interval, and *mixed-authorship* detection that flags
85
+ which sections look AI-written.
86
+ * **Reads what colleagues actually send.** `.docx`, `.pdf`, `.md`, `.txt`,
87
+ `.html`, e-mails (`.eml`, Outlook `.msg`; quoted thread history is stripped),
88
+ and photos or screenshots via OCR (built in on macOS).
89
+
90
+ > **Read [Responsible use](#responsible-use) before applying this to colleagues' work.**
91
+ > Every AI-text detector, this one included, produces false positives. A score
92
+ > is a reason to look more closely, never evidence on its own.
93
+
94
+ ---
95
+
96
+ ## Install
97
+
98
+ ```bash
99
+ pip install mrm-ai-detector
100
+ ```
101
+
102
+ That's the whole core: no dependencies. It reads `.txt`, `.md`, `.docx`,
103
+ `.html` and `.eml` files and, on a Mac, photos and screenshots (`.heic`,
104
+ `.jpg`, `.png` …) through Apple's built-in Live Text OCR engine. Optional
105
+ extras:
106
+
107
+ ```bash
108
+ pip install "mrm-ai-detector[pdf]" # PDF support (pypdf)
109
+ pip install "mrm-ai-detector[email]" # Outlook .msg support (olefile)
110
+ pip install "mrm-ai-detector[ocr]" # photos/screenshots on Windows/Linux (RapidOCR); macOS needs nothing
111
+ pip install "mrm-ai-detector[lm]" # language-model ensemble (torch + transformers; ~3.5 GB of models downloaded on first use)
112
+ pip install "mrm-ai-detector[all]" # everything
113
+ ```
114
+
115
+ To try it without installing anything permanently, use
116
+ [`uv`](https://docs.astral.sh/uv/) or [`pipx`](https://pipx.pypa.io/):
117
+
118
+ ```bash
119
+ uvx --from mrm-ai-detector mrm-detect scan report.docx
120
+ ```
121
+
122
+ To install the latest development version straight from GitHub:
123
+
124
+ ```bash
125
+ pip install "git+https://github.com/anirudhjayaraman/mrm-ai-detector"
126
+ ```
127
+
128
+ ## Quick start
129
+
130
+ ```bash
131
+ mrm-detect scan report.docx # one document
132
+ mrm-detect scan ~/Downloads/IMG_1234.HEIC # a photo or screenshot (macOS: built-in OCR)
133
+ mrm-detect scan reports/ --summary # a whole folder
134
+ ```
135
+
136
+ The repository's `examples/` folder shows what to expect. After cloning, it
137
+ also runs without installing: `python -m mrm_ai_detector scan examples/`.
138
+
139
+ ```
140
+ Document Words AI prob AI share Verdict
141
+ ----------------------------------------------------------------------------------------------------
142
+ examples/ai_generated_methodology_qwen.md 561 90% 65% Likely AI-generated
143
+ examples/ai_generated_validation_summary_claude.md 364 11% 0% Likely human-written
144
+ examples/human_sr11-7_validation_excerpt.txt 723 52% 0% Inconclusive
145
+ examples/mixed_validation_report.md 1284 26% 0% Likely human-written
146
+ ```
147
+
148
+ The examples were chosen to show the limits honestly. Text from a small open
149
+ model is caught, but the Claude-written summary passes as human, and so does
150
+ the report with an inserted Claude-written section. SR 11-7, a human text,
151
+ sits in the inconclusive band. See [Benchmark summary](#benchmark-summary).
152
+
153
+ ## Usage
154
+
155
+ ```bash
156
+ mrm-detect scan report.docx # detailed text report
157
+ mrm-detect scan reports/ --summary # one line per document
158
+ mrm-detect scan reports/ -f html -o report.html # self-contained HTML report with highlighted segments
159
+ mrm-detect scan issue.msg -f json # machine-readable
160
+ mrm-detect scan report.pdf --lm # add Binoculars / Fast-DetectGPT / HC3 / Fakespot / Desklib features
161
+ cat draft.txt | mrm-detect scan - # stdin
162
+ mrm-detect scan submissions/ --fail-on-ai # exit code 3 if anything is flagged (CI / workflow gate)
163
+ mrm-detect features report.docx # raw feature values, for analysts
164
+ ```
165
+
166
+ Python API:
167
+
168
+ ```python
169
+ from mrm_ai_detector import Detector
170
+
171
+ result = Detector().analyze_file("validation_report.docx")
172
+ print(result.verdict, f"{result.probability:.0%}", f"(90% CI {result.ci_low:.0%}–{result.ci_high:.0%})")
173
+ for seg in result.segments:
174
+ if seg.flagged:
175
+ print(seg.section, f"{seg.probability:.0%}", [s.feature for s in seg.signals])
176
+ ```
177
+
178
+ ### Verdicts
179
+
180
+ | Verdict | Meaning |
181
+ |---|---|
182
+ | Likely AI-generated | Document probability ≥ the model's AI threshold (calibrated for ≤ 2% false positives on human MRM documents) |
183
+ | Mixed: partially AI-generated | Not flagged overall, but ≥ 15% of the text sits in segments that individually exceed the threshold |
184
+ | Likely human-written | Probability ≤ 30% and no material flagged sections |
185
+ | Inconclusive | Anything in between |
186
+ | Insufficient text | Fewer than 150 words of prose. Detection is unreliable on short text |
187
+
188
+ ## How it works
189
+
190
+ 1. **Ingest and normalise.** Text is extracted, PDF line breaks reflowed,
191
+ running headers and footers removed, and e-mail threads cut to the newest
192
+ message. Prose inside table cells is kept, since audit issues are often
193
+ written in tables.
194
+ 2. **Segment.** The text is split into roughly 180-word chunks. Headings are
195
+ treated as soft boundaries, so heading-dense validation reports still give
196
+ scorable chunks.
197
+ 3. **Features** (`mrm-detect features` lists them all):
198
+ * *Domain evidence.* Numeric density, metric statements with values (Gini
199
+ 0.61, PSI = 0.08), specific references (model IDs, dates, SR 11-7,
200
+ "Section 4.2"), the ratio of unsupported evaluative claims, governance
201
+ boilerplate, hedging.
202
+ * *LLM markers.* Weighted lexicon ("delve", "it is important to note",
203
+ "plays a pivotal role" …) with MRM vocabulary such as "robust" and
204
+ "comprehensive" down-weighted. Also stock sentence openers, ", ensuring
205
+ …" participle tails, "not only … but", and triplets.
206
+ * *Stylometry.* Sentence-length burstiness, lexical diversity, word length,
207
+ function words, punctuation habits.
208
+ * *Information theory.* Windowed compression ratio, character-trigram
209
+ entropy, phrase repetition.
210
+ * *Optional language-model features* (`--lm`). Binoculars (Hans et al.,
211
+ ICML 2024) and Fast-DetectGPT (Bao et al., ICLR 2024) with a
212
+ Qwen2.5-0.5B observer/performer pair, plus the logits of three
213
+ open-source classifiers: HC3 RoBERTa (Guo et al., 2023), Fakespot RoBERTa
214
+ (2025) and Desklib DeBERTa-v3 (2025).
215
+ 4. **Score.** Features are standardised against the calibration corpus and
216
+ combined by an L2-regularised logistic model. Logits on short texts are
217
+ shrunk towards 50% ("no evidence"). A sentence bootstrap gives a 90%
218
+ confidence interval.
219
+ 5. **Explain.** Every score comes with the features that pushed it up or down.
220
+
221
+ ## Benchmark summary
222
+
223
+ Held-out documents never used in training are split by document, and every
224
+ human document predates ChatGPT. Full tables are in
225
+ [`benchmarks/results/`](https://github.com/anirudhjayaraman/mrm-ai-detector/tree/main/benchmarks/results). Reproduce them with the
226
+ commands in [benchmarks/README.md](https://github.com/anirudhjayaraman/mrm-ai-detector/blob/main/benchmarks/README.md).
227
+
228
+ ### Head-to-head on 331 held-out documents (102 in-domain MRM documents)
229
+
230
+ | Detector | In-domain doc AUC | In-domain TPR @ 5% FPR | All-doc AUC | Doc TPR / FPR at its own threshold |
231
+ |---|---:|---:|---:|---|
232
+ | **mrm-detector `--lm`** (this package, ensemble) | **0.962** | **0.891** | **0.985** | 0.906 / **0.000** |
233
+ | Fakespot RoBERTa (2025) | 0.929 | 0.848 | 0.965 | 0.947 / 0.163 |
234
+ | Desklib DeBERTa-v3 (2025) | 0.924 | 0.870 | 0.961 | 0.930 / 0.144 |
235
+ | **mrm-detector** (stdlib only, zero install) | 0.899 | 0.783 | 0.933 | 0.515 / 0.006 |
236
+ | HC3 ChatGPT RoBERTa (2023) | 0.755 | 0.217 | 0.923 | 0.620 / 0.019 |
237
+ | RADAR (2023) | 0.641 | 0.130 | 0.825 | 0.655 / 0.169 |
238
+ | Binoculars (Qwen2.5-0.5B pair) | 0.505 | 0.109 | 0.787 | n/a |
239
+ | Fast-DetectGPT (Qwen2.5-0.5B) | 0.408 | 0.087 | 0.741 | n/a |
240
+ | OpenAI GPT-2 output detector (2019) | 0.407 | 0.022 | 0.801 | 0.550 / 0.037 |
241
+
242
+ Fakespot and Desklib, used on their own, flag a third or more of human
243
+ regulatory, supervisory and academic MRM documents (Fakespot: half of the
244
+ academic papers and comment letters). They are, however, the only standalone
245
+ detectors that recognised some Claude-written MRM text (56% and 44%). Inside the
246
+ ensemble, false positives were zero across every human document family.
247
+
248
+ **Detection rate by generator (ensemble, held-out documents):** Qwen2.5 100%,
249
+ SmolLM2 100%, Phi-3.5 100%, gpt-3.5-turbo / ChatGPT 100%, Cohere 100%,
250
+ Flan-T5 87%, **text-davinci-003 20%, Claude 33%**.
251
+
252
+ ### Free web detectors on 8 short samples (held out for this package too)
253
+
254
+ Four human samples are pre-2023 US federal texts (SR 11-7, Fed OIG, GAO, FHFA
255
+ OIG). Three AI samples are Claude-written MRM text and one is Qwen2.5-written.
256
+
257
+ | Detector | AI samples caught | Human samples falsely flagged |
258
+ |---|---|---|
259
+ | GPTZero (free tier) | 4 / 4 | 1 / 4 (FHFA OIG 2020 report: 100% AI) |
260
+ | mrm-detector `--lm` | 2 / 4 | 1 / 4 (SR 11-7 excerpt: 63%) |
261
+ | ZeroGPT | 1 / 4 | 0 / 4 |
262
+ | mrm-detector (stdlib) | 1 / 4 | 0 / 4 |
263
+ | Sapling | 1 / 4 | 2 / 4 (SR 11-7: 95.5%, FHFA OIG: 71.9%) |
264
+
265
+ Per-sample numbers are in [`benchmarks/results/web_comparison.md`](https://github.com/anirudhjayaraman/mrm-ai-detector/blob/main/benchmarks/results/web_comparison.md).
266
+
267
+ ### What this means in practice
268
+
269
+ * Text from small and mid-sized open models, and from ChatGPT-3.5-era models,
270
+ is detected reliably, with a very low false-positive rate on genuine MRM
271
+ documents.
272
+ * **Polished frontier-model text (Claude-class) is the hard case.** Only about
273
+ a third is caught on a full document. On short excerpts, GPTZero, a commercial
274
+ detector trained on current models, did better. But it means sending
275
+ documents to a third party, and it falsely flagged a 2020 FHFA OIG report.
276
+ * For colleague reviews, combine the document score with the
277
+ [author-baseline comparison](#comparing-against-an-authors-own-earlier-work-recommended-for-colleague-reviews)
278
+ and with a substantive review of the evidence (numbers, tests,
279
+ references). The domain-evidence signals in every report support that review.
280
+
281
+ ## Comparing against an author's own earlier work (recommended for colleague reviews)
282
+
283
+ Generic detectors judge everyone against one population, so writers whose
284
+ natural style is formal, template-driven or non-native get flagged more often.
285
+ The **baseline** mode asks a fairer question: *is this document unusual for
286
+ this person?*
287
+
288
+ ```bash
289
+ mrm-detect baseline new_issue_writeup.docx --reference colleague_2019_2022_docs/
290
+ ```
291
+
292
+ ```text
293
+ # illustrative output
294
+ Style distance: 1.84 (author's own documents: median 0.71, 90th pct 1.02)
295
+ Empirical p-value: 0.08 Shift towards AI-typical features: +0.62
296
+ Unusual for this author, and the shift is towards LLM-typical writing. Worth a closer look.
297
+ Largest shifts (z vs author's own writing):
298
+ +2.91 AI-ward ai_marker_rate ...
299
+ ```
300
+
301
+ Use at least 5 reference documents, ideally 10 or more, of the same genre
302
+ (issue write-ups against issue write-ups) from before 2023. A low p-value with
303
+ an AI-ward shift is a reason to talk to the author, not a conclusion.
304
+
305
+ ## Calibrating on your organisation's documents
306
+
307
+ The shipped calibration uses public documents. Your organisation's house style
308
+ will differ, so **calibrate locally before relying on scores**:
309
+
310
+ 1. **Human set.** Collect documents written before December 2022: validation
311
+ reports, audit issues, e-mails. Their authorship isn't in doubt.
312
+ 2. **AI set.** Ask your approved LLM(s) to write comparable documents (same
313
+ templates, same models), including prompts like "make it sound like a
314
+ human validator wrote it".
315
+ 3. Train and evaluate. Everything stays on your machine:
316
+
317
+ ```bash
318
+ mrm-detect train --human corpus/human --ai corpus/ai -o our_model.json --save-dataset features.jsonl
319
+ mrm-detect evaluate --human holdout/human --ai holdout/ai --model our_model.json
320
+ mrm-detect scan new_reports/ --model our_model.json
321
+ ```
322
+
323
+ `train` reports document-grouped cross-validated AUC and TPR at 1% and 5%
324
+ FPR. Choose `--threshold` from your own false-positive tolerance.
325
+
326
+ ## Responsible use
327
+
328
+ * **False positives are unavoidable.** In our tests the free web detectors
329
+ rated a 2011 Federal Reserve guidance text 95.5% AI (Sapling) and a 2020
330
+ FHFA OIG report 100% AI (GPTZero). This tool is calibrated to keep human
331
+ MRM documents below a 2% false-positive rate on the benchmark, but your
332
+ documents aren't the benchmark.
333
+ * **Non-native English writers are flagged more often** by perplexity- and
334
+ style-based detectors (Liang et al., 2023, *GPT detectors are biased against
335
+ non-native English writers*). Formulaic, template-driven writing such as
336
+ audit-issue templates also looks "low-perplexity". Weigh scores
337
+ accordingly.
338
+ * **AI assistance isn't misconduct.** Translation, grammar fixes and
339
+ structured drafting may be permitted under your firm's AI policy. Ask what
340
+ your policy actually prohibits, and whether the *content* (evidence, numbers,
341
+ conclusions) is sound. The domain-evidence signals in the report help with
342
+ that question whoever wrote the text.
343
+ * **Use scores for triage, never as the sole basis** for any decision about a
344
+ person. Keep a human in the loop, and give authors the opportunity to
345
+ explain.
346
+ * **Confidentiality.** Everything runs locally. Nothing is sent anywhere,
347
+ including with `--lm`, whose models are downloaded once from Hugging Face
348
+ and run on your machine. Don't paste internal documents into web detectors.
349
+ * **OCR input is noisy.** Scan the original document rather than a photo when
350
+ you can. Reports from OCR'd input carry a warning.
351
+
352
+ ## Troubleshooting
353
+
354
+ * **`--lm` is slow the first time.** About 3.5 GB of models are downloaded
355
+ once, then cached. Scoring runs at about 1–2 s per 180-word segment on a
356
+ laptop.
357
+ * **Model download hangs.** Set `HF_HUB_DISABLE_XET=1`. Behind a corporate
358
+ proxy, pre-download the models listed in
359
+ `mrm_ai_detector/features/neural.py` and set `HF_HUB_OFFLINE=1`.
360
+ * **Memory.** `--lm` needs about 4 GB of RAM. Use
361
+ `MRM_DETECTOR_CLASSIFIERS=hc3,fakespot` to drop the large Desklib model,
362
+ then recalibrate.
363
+ * **Scanned PDFs.** Text-less PDFs raise an error; convert pages to images
364
+ and scan those (OCR), or run OCR first.
365
+
366
+ ## Project layout
367
+
368
+ ```
369
+ mrm_ai_detector/ the package (stdlib core; neural/OCR/PDF features optional)
370
+ text.py normalisation, sentence splitting, segmentation
371
+ ingest.py .txt .md .docx .pdf .html .eml .msg, images (OCR)
372
+ features/ domain, markers, stylometry, entropy, neural (optional)
373
+ scoring.py standardised logistic scoring model (JSON)
374
+ detector.py orchestration, bootstrap CI, verdicts
375
+ train.py calibration: IRLS ridge logistic, grouped CV, metrics
376
+ report.py text / JSON / Markdown / HTML reports
377
+ models/ shipped calibrated models
378
+ benchmarks/ corpus manifest, fetch/generate/calibrate/compare scripts, results
379
+ tests/ pytest suite
380
+ examples/ public-domain human text, AI-written and mixed examples
381
+ ```
382
+
383
+ ## Development
384
+
385
+ ```bash
386
+ git clone https://github.com/anirudhjayaraman/mrm-ai-detector
387
+ cd mrm-ai-detector
388
+ pip install -e ".[dev]"
389
+ pytest
390
+ ruff check mrm_ai_detector tests
391
+ ```
392
+
393
+ ## Licence and attribution
394
+
395
+ MIT. Method attributions: Binoculars (Hans et al., 2024, BSD-3), Fast-DetectGPT
396
+ (Bao et al., 2024, MIT), HC3 / chatgpt-detector-roberta (Guo et al., 2023),
397
+ fakespot-ai/roberta-base-ai-text-detection-v1 (Apache-2.0),
398
+ desklib/ai-text-detector-v1.01 (MIT), M4
399
+ (Wang et al., 2024), RapidOCR (Apache-2.0). Human corpus texts are downloaded
400
+ from their publishers at benchmark time and aren't redistributed. The examples
401
+ use US federal government works, which are in the public domain.