Детектор нейрослопа без ИИ: как запустить и как читать результат
Автор: tchrДетектор нейрослопа целиком: как запустить и как читать результат
Черновик. Продолжение серии про нейрослоп и «белый список». Методику я разбирал на словах — теперь весь инструмент выложен под MIT: gitverse.ru/tchr/ru-ai-stylometry. Один файл на Python, вшитая калибровка, примеры. Клонируйте и гоняйте на своих текстах.
Что это
check_llm_style.py — стилометрический детектор ИИ-прозы. Внутри нет нейросети и нет обращений к чужому API, только арифметика по размеченному корпусу. Нейродетектор (тот же Yandex) выдаёт один непрозрачный процент; этот скрипт отвечает на другой вопрос — почему текст читается сгенерированным: считает конкретные обороты и цитирует сработавшие предложения. Всё офлайн и воспроизводимо.
- ноль зависимостей — только Python 3.9+, никаких
pip install; - один файл, калибровка вшита — оценивается и одиночный текст;
- MIT — берите, форкайте, перекраивайте под свой жанр.
Калибровка вшита из корпуса русской сетевой фантастики / LitRPG 2016–19 гг. (112 заведомо человеческих работ). На честной отложенной выборке (154 задекларированных ИИ-работы 2023+ против 159 до-2020, авторы разделены без пересечений — калибровка этих текстов не видела) инструмент ловит около 95% ИИ-текстов при нуле ложных из 47 контрольных.
Как работает: три слоя
Ни один слой не судит в одиночку. Улика — это согласие слоёв; гуманизация обычно чинит один слой, но не все три сразу.
- Маркеры (regex). Частота структурных калек на 100 000 знаков: «глубокий вдох»,
«уголок губ дёрнулся», «по спине пробежал холодок», «в воздухе повисла тишина». В русском ЛитРПГ/фэнтези англо-образный оборот — чужеродная калька, а не норма жанра, поэтому работает как сигнал ИИ.
- Статистика. То, что гуманизация не восстанавливает: клише переписать легко, а
человеческую плотность частиц (же/ли/бы/ведь/вот), длину предложений, разнообразие словаря — нет. Этот слой и ловит «гуманизированный ИИ», перед которым нейродетектор пасует.
- Форензика. Дословно повторённые предложения (у людей ≈0) и мешанина диалоговых тире — след склейки из нескольких генераций.
Как запустить
Ставить нечего — только Python 3.9+.
git clone https://gitverse.ru/tchr/ru-ai-stylometry.gitcd ru-ai-stylometrypython3 check_llm_style.py examples/ --min-chars 500
Вход — любой *.txt (простой текст) или *.json вида {"title": ..., "text": ...}, либо папка с такими файлами. Прогоняется рекурсивно, результат печатается таблицей (по умолчанию) или JSON-ом (--json).
# один текстовый файлpython3 check_llm_style.py chapter.txt# папка целиком — каждый .txt/.json отдельной строкой отчётаpython3 check_llm_style.py mybook/# показать до 3 цитат-срабатываний на текст — видно, ЧТО именно сработалоpython3 check_llm_style.py chapter.txt --quotes 3# сравнить несколько книг разом (удобно для внутриавторских пар «до/после ИИ»)python3 check_llm_style.py book1.txt book2.txt book3.json --quotes 2# машинный вывод со всеми признаками — для дальнейшей обработкиpython3 check_llm_style.py mybook/ --json > out.json
Основные флаги:
| флаг | назначение |
|---|---|
--quotes N | до N цитат-срабатываний на текст (видно, что именно сработало) |
--json | машинный вывод со всеми признаками вместо таблицы |
--min-chars N | пропускать тексты короче N знаков (по умолчанию 2000) |
--ai-csv PATH | приджойнить ai_percent детектора (колонки workId,ai_percent) для флага HUM? |
--calib PATH | своя калибровка вместо вшитой (выход calibrate_llm_style.py) |
Примеры в репозитории короткие (по паре сотен слов), поэтому на них вердикт будет shrt — «слишком мало текста, чтобы судить»: смотрите на них колонки slop/hot. Полноценный вердикт инструмент выносит от ~2000 слов (проза от ~30 тыс. знаков).
Как читать результат
Отчёт — таблица, по строке на текст:
vrdct hot vote syn str delta slop srep detc flag top categories / title---------------------------------------------------------------------------------------------------- AI! 8/11 3/5 2 0 1.01 264.5 0 — [gaze_chore,body_beat,rhetoric_n]+dash Серия A, книга 15 0/11 0/5 0 0 0.80 36.3 0 — [] Серия A, книга 1
Колонка за колонкой:
| колонка | что означает |
|---|---|
vrdct | вердикт: AI! / sus? / shrt (HUM? — в колонке flag). Пусто = чисто |
hot | сколько из 11 весомых маркерных категорий превышают p90-частоту до-LLM контроля. Порог абсолютный, вшит |
vote | сколько из 5 голосов статистического слоя сработало |
syn | 0–3 синтаксических голоса-подтверждения (гейт точности для пограничных случаев) |
str | 0–4 структурных голоса (повышающий лимб: str ≥ 2 поднимает sus? до AI!) |
delta | дельта Барроуза от центроида контроля — самый устойчивый одиночный признак (у людей ≲0.95, у ИИ ≳1.0) |
slop | суммарный взвешенный «слоп»-счёт маркеров (сырой контекст, не порог) |
srep | число дословно повторённых нарративных предложений (у людей ≈0) |
detc | AI% нейродетектора, если передан --ai-csv (иначе —) |
flag | HUM? — стилометрия говорит ИИ, а детектор чист; +dash — смесь диалоговых тире |
Вердикты:
AI!—hot ≥ 4из 11, или ≥4 из 5 голосов статслоя, или ровно 3 голоса с синтаксическим подтверждением (syn ≥ 2), или ярусsus?со структурным подтверждением (str ≥ 2).sus?— «присмотреться»:hot == 3, либо 2 голоса приhot ≥ 2, либо 3 голоса без синтаксического подтверждения. Сюда попадает ~10% заведомо человеческого контроля — это ярус триажа, не приговор.shrt— текст короче ~2000 слов: частоты шумят, вердикт не выносится (slop/hotчитайте как сырой контекст).HUM?— стилометрия говорит ИИ, а нейродетектор чист (<5%): кандидат в «гуманизированный ИИ, обманувший детектор». Требует--ai-csv.
С --quotes N под таблицей печатаются сами сработавшие фрагменты — по ним видно, почему вынесен вердикт:
### Серия A, книга 15 (verdict AI!, hot 8, votes 3, slop 264.5) [gaze_choreo] …перевёл взгляд на неё, и в его глазах что-то дрогнуло. Он опустил взгляд… [body_beat] …сглотнул, стиснул зубы, на скулах напряглись желваки… [rhetoric_negspace] …не было ни звука, только едва заметное движение теней…
Читать стоит согласие слоёв: горячие маркеры + голоса статслоя + само-повторы вместе почти не встречаются у людей. Один задранный маркер при hot 1–2 — скорее особенность авторского стиля. Самый чистый способ применения — внутриавторская пара: прогнать раннюю книгу автора против поздней. Если ранняя чиста, а поздняя горит по всем слоям — это переход на генерацию, а не индивидуальный стиль.
Одна картинка

Слева живые авторы до эпохи генерации — балл низкий (медиана 32). Справа книги, на которых сработал сам Яндекс, — вчетверо выше (129). А середина — топы, которых нейродетектор пропустил как «чистые»: по стилю они сидят почти вдвое выше живого контроля (59).
Чего картинка не доказывает: средняя группа задана лишь по «Яндекс <5%» — это смесь живых авторов и, вероятно, гуманизированного ИИ; высокий балл у отдельной книги может быть и просто плотным жанровым стилем. К тому же контроль — это другие авторы другой эпохи (2016–19), так что часть разрыва — эффект выборки. Отсюда и правило: вердикт нельзя ставить по одному баллу — это распределения, группы перекрываются, работает только согласие слоёв. Балл считает тот же check_llm_style.py из репозитория (v3.3); сам корпус текстов не выкладывается — он под копирайтом, поэтому свой график стройте на своих текстах.
Честные границы
- Это сигнал, а не приговор. На отложенном контроле было 0 ложных из 47; на широкой живой выборке оценка честнее — около 5% ложных
AI!. Поэтому всегда смотрите цитаты-срабатывания, а не только ярлык. - Граница применимости измерена. Инструмент откалиброван на сетевой фантастике/ЛитРПГ. Вне домена (детектив, романтика, нон-фикшн, перевод) ложные срабатывания растут до 23–30% против 2.5–3.6% в своём домене — там пользуйтесь только со своей калибровкой. Переводная проза почти наверняка даст ложный
AI!— кальки там настоящие. - Один задранный маркер — это стиль, а не улика. Стилометрия может «заметить суслика там, где его нет». Потому в одиночку и не работает.
Перекалибровка под свой корпус
Не верите вшитым порогам — соберите свой корпус заведомо человеческих текстов (проще всего опубликованных до 2022 года) и перекалибруйте под себя:
python3 calibrate_llm_style.py my-known-human-texts/ -o calib.jsonpython3 check_llm_style.py suspect.txt --calib calib.json
Откуда что взято
- Репозиторий: gitverse.ru/tchr/ru-ai-stylometry (MIT) · файлы
check_llm_style.py,calibrate_llm_style.py,examples/ - Разбор методики (Q&A): author.today/post/886544
- Предыдущие части: 872837, 874585, 876688