Детектор, который проверяет не текст, а смыслы.
Спойлер: обычные антиплагиат-детекторы ловят синтаксис («таким образом, подводя итог...»). Современные модели этот синтаксис уже научились маскировать — копируют стиль, добавляют «личный опыт», перефразируют штампы. Статистика одна, а смысл другой. AI Radar не спорит с текстом — он спрашивает у самих LLM: «это написал ты?». AI Radar определяет академическую честность, считая, что ИИ - современный инструмент, и само по себе его применение не является нарушением.
Студенческие работы, рефераты, дипломы и эссе массово пишутся через ChatGPT, Claude, DeepSeek, Gemini, Grok, Kimi. Встроенные детекторы вроде Turnitin и GPTZero часто ошибаются в обе стороны: ложно срабатывают на живых текстах с богатой лексикой и пропускают явно сгенерированные — особенно после ручного перефразирования (paraphrase attack).
Преподаватели и научные руководители остаются один на один с текстом, без инструмента, которому можно доверять — и уж тем более без возможности обосновать вердикт студенту, который придёт оспаривать оценку.
AI Radar собран под принцип «не доверяй одному сигналу»: статистика считает математику, ансамбль LLM проверяет «свой почерк», а метасудья выносит финальный вердикт с правом заблокировать работу независимо от процента.
| Инструмент | На чём основан | Где ломается |
|---|---|---|
| Turnitin AI Detector | Статистика + perplexity | Ложные срабатывания на носителях языка с богатой лексикой |
| GPTZero | Burstiness + perplexity | Обходится простым перефразированием (paraphrase attack) |
| Originality.ai | Классификатор-бинарник | Чёрный ящик, нет обоснования вердикта, нет апелляции |
| ZeroGPT | Эвристики + ML-модель | Не различает «похоже на ИИ по стилю» и «реально написано ИИ» |
| AI Radar | 20 метрик + ансамбль LLM + метасудья с ВЕТО | Проверяет логику и «почерк» модели, а не только синтаксис. Каждый вердикт — с обоснованием для апелляции |
Ключевое отличие: остальные детекторы ищут следы генерации в тексте. AI Radar ищет следы отсутствия человека — личного опыта, конкретики, сомнений, авторской позиции. А заодно спрашивает у 6 разных LLM: «похоже ли это на то, что написал бы ты сам?» — модели узнают собственный почерк лучше любой статистики.
Уровень 1 — Ансамбль детекторов. Любое число OpenAI-compatible моделей (ChatGPT, Claude, Gemini, DeepSeek, Grok, Kimi) параллельно анализируют текст. Каждая модель проводит саморефлексивный анализ: представляет, что могла бы написать этот текст сама, и оценивает, насколько это похоже на её собственный стиль аргументации.
Что ищут детекторы:
- Следы генерации LLM — механическая однородность глубины абзацев, повторяющиеся клише, сверхправильная структура.
- Чья логика — сбалансированные «про и контра», нейтральность, уход от позиции, «правильные», но поверхностные выводы, галлюцинации.
- Человеческие особенности (их отсутствие = сигнал ИИ) — личный опыт, конкретные истории, имена, даты, креативность, юмор, ирония, авторская позиция, «шероховатости» и сомнения.
Уровень 2 — Метасудья. ОДНА сильная модель (рекомендация: Claude
Sonnet/Opus, Gemini Pro), которая не видит исходный текст. Ей
передаются: сводка 20 статистических метрик, вердикты всех детекторов
ансамбля (ai_score, veto, фрагменты, признаки человека/ИИ) и промпт
для оценки. Метасудья выявляет ошибки отдельных детекторов, оценивает
согласованность ансамбля и выносит финальный вердикт.
Судья может выставить academic_integrity = "НАРУШЕНА" независимо от
итогового процента, если выявил критические логико-структурные
аномалии генерации. Обоснование (veto_reason) сохраняется в отчёте и
доступно для апелляции студента.
| Статус | Что работает | Финальный вердикт | VETO |
|---|---|---|---|
OFFLINE |
Только Сигнал 1 (статистика) | stat_score |
не активируется |
ENSEMBLE_ONLY |
Ансамбль без судьи | медиана ансамбля | активируется |
FULL |
Ансамбль + метасудья | вердикт судьи | активируется |
┌─────────────────────────────────────────────────────────────┐
│ AI Radar Pipeline │
│ │
│ Текст работы │
│ │ │
│ ▼ │
│ ┌────────────┐ 20 статистических метрик │
│ │ Сигнал 1 │ burstiness, TTR, Yule's K, Honore's R, │
│ │ (стат) │ perplexity proxy, cliche density, │
│ └─────┬──────┘ n-gram repetition, rhythm entropy и др. │
│ │ stat_score [0..100] │
│ ▼ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Сигнал 2, Уровень 1: Ансамбль детекторов │ │
│ │ ChatGPT ─┐ │ │
│ │ Claude ─┼─▶ каждый анализирует текст + метрики │ │
│ │ Gemini ─┤ и проверяет: «не я ли это написал?» │ │
│ │ DeepSeek┤ возвращает ai_score, veto, фрагменты, │ │
│ │ Grok ─┤ human_signals[], llm_signals[] │ │
│ │ Kimi ─┘ │ │
│ │ Агрегация: медиана ai_score, голосование по VETO │ │
│ └─────────────────┬────────────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Сигнал 2, Уровень 2: Метасудья (Claude/Gemini Pro) │ │
│ │ НЕ видит текст работы — только сводку метрик │ │
│ │ и вердикты ансамбля. Право БЛОКИРУЮЩЕГО ВЕТО. │ │
│ └─────────────────┬────────────────────────────────────┘ │
│ ▼ │
│ Финальный отчёт + страница детализации с подсветкой │
└─────────────────────────────────────────────────────────────┘
ai_score = 0.7·judge + 0.3·stat в режиме FULL, либо чистый stat_score
в OFFLINE. Если veto_triggered=True или ai_score ≥ VETO_THRESHOLD →
academic_integrity = "НАРУШЕНА".
Отдельная страница отчёта с:
- Круговой диаграммой итогового
ai_scoreс цветовой индикацией (зелёный / жёлтый / красный). - Бейджем ВЕТО — «АКТИВИРОВАНО» / «НЕ АКТИВИРОВАНО».
- Статусом академической честности — «ПОДТВЕРЖДЕНА» / «НАРУШЕНА».
- Полной матрицей 20 метрик Сигнала 1 с тултипами-пояснениями.
- Вердиктами ансамбля — какой детектор что поставил, какие признаки человека/ИИ нашёл.
- Вердиктом метасудьи — финальный скор и обоснование.
- Текстом работы с подсветкой в три уровня: жёлтый (подозрение), оранжевый (высокая уверенность), красный (критично).
- Кнопками «Распечатать / PDF» и «Скачать JSON».
Прогресс-бар показывает пошаговые статусы в реальном времени: «Считаю метрики…» → «Опрашиваю ансамбль из 6 детекторов…» → «Метасудья оценивает вердикты…» → «Готово!» — с ETA в секундах.
Без локальных нейросетей — чистая математика на Python. Сводный
stat_score [0..100] считается взвешенной эвристикой: метрики, на
которых современные LLM «прогораются» сильнее всего (burstiness, TTR,
cliche density, n-gram repetition), получают большие веса.
| # | Метрика | Что показывает |
|---|---|---|
| 1 | Burstiness | SD/Mean длин предложений. ИИ → 0.1–0.4, человек → 0.6–1.2 |
| 2 | Lexical Diversity (TTR) | Уникальные леммы / всего слов |
| 3 | Sentence Length Variance | Дисперсия длин предложений |
| 4 | Perplexity Proxy | Shannon-энтропия биграмм |
| 5 | Synthetic Cliche Density | Плотность клише на 1000 слов |
| 6 | Punctuation Entropy | Разнообразие пунктуации |
| 7 | Sentence Starter Entropy | Энтропия первых слов предложений |
| 8 | Yule's K | Характеристика богатства словаря |
| 9 | Honore's R | Лексическое богатство |
| 10 | Sichel's S | Доля hapax legomena |
| 11 | Hapax Ratio | Слова, встретившиеся 1 раз / всего |
| 12 | Connective Density | Логические маркеры / 1000 слов |
| 13 | N-gram Repetition Rate | Доля повторяющихся 3-грамм |
| 14 | Sentence Rhythm Entropy | Энтропия распределения длин |
| 15 | Comma-per-Sentence | Запятых на предложение |
| 16 | Avg Syllables per Word | Среднее число слогов |
| 17 | Function-Word Ratio | Доля служебных слов |
| 18 | Lexical Density | Content-words / всего слов |
| 19 | TTR Windowed | Скользящий TTR (MATTR-подобный) |
| 20 | Determiner Density | Определители / 1000 слов |
Каждая метрика в интерфейсе имеет тултип с пояснением — преподавателю не нужно гуглить, что такое Yule's K, чтобы обосновать вердикт студенту.
Несколько паттернов, которые видны после прогонов на реальных студенческих работах:
Замаскированный текст не проходит ансамбль. Perplexity легко обойти ручным перефразированием — но саморефлексивный анализ («похоже ли это на мой стиль?») ловит именно логику аргументации, а не поверхностный синтаксис. Модель узнаёт свой почерк даже под чужим стилем.
Один детектор — ненадёжно, шесть — устойчиво. Разные семейства LLM (GPT, Claude, Gemini, DeepSeek, Grok, Kimi) по-разному «прогораются» на собственных паттернах. Голосование большинством и медиана ai_score гасят единичные ложные срабатывания.
ВЕТО ловит то, что пропускает процент. Работа может набрать скромные 40-50% по ai_score, но иметь критическую логико-структурную аномалию (например, полное отсутствие личной позиции при формальной «правильности» аргументации) — и именно для этого нужно право блокирующего решения, а не только порог.
| Роль | Что видит |
|---|---|
| admin | Все папки, настройки системы, LLM-провайдеры, API-ключи, управление пользователями |
| teacher | Только свои папки + общие, смена своего пароля |
Вход по логину и паролю. Администратор создаёт преподавателей и может
сбросить любой пароль. Дефолтный администратор: admin / airadar
(рекомендуется сменить в Админ-панели сразу после первого входа).
AI Radar можно использовать как через UI, так и программно — через
API-ключи air_.... Создаются в админ-панели, показываются один раз,
поддерживают ротацию и отзыв.
# Логин мастер-паролем
curl -X POST http://localhost:8000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"login":"admin","password":"airadar"}'
# Создать API-ключ
curl -X POST http://localhost:8000/api/admin/api-keys \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"name":"CI"}'
# => {"key":"air_xxxx..."} # сохранить, показывается один раз
# Скан текста через API-ключ
curl -X POST http://localhost:8000/api/scan/quick/json \
-H "Authorization: Bearer air_xxxx..." \
-H "Content-Type: application/json" \
-d '{"text":"В современном мире важно отметить...","title":"work.txt"}'Интерактивная документация в стиле системы: http://localhost:8000/docs-page
OpenAPI-схема: http://localhost:8000/docs
git clone <your-repo-url> ai-radar
cd ai-radar
docker-compose up -d
# UI: http://localhost:8000
# Docs: http://localhost:8000/docs-pagepython -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # Linux/macOS
pip install -e ".[dev]"
cp .env.example .env # отредактируйте .env
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000pytest -v- Логин:
admin| Пароль:airadar - Откройте Админ-панель → Ансамбль детекторов и добавьте модели. Рекомендуемые семейства: ChatGPT, Claude, Gemini, DeepSeek, Grok, Kimi.
- Назначьте Метасудью (Claude Sonnet/Opus или Gemini Pro).
- Бейдж в шапке покажет
ENSEMBLE+JUDGE (6+1)— система готова.
Любые OpenAI-compatible. Тестировалось на:
| Модель | Идентификатор |
|---|---|
| ChatGPT 5.1 | openai/gpt-5.1 |
| Claude Sonnet 5 | anthropic/claude-sonnet-5 |
| Gemini 3.6 Flash | google/gemini-3.6-flash |
| DeepSeek V4 Pro | deepseek/deepseek-v4-pro |
| Grok 4.3 | x-ai/grok-4.3 |
| Kimi K3 | moonshotai/kimi-k3 |
В режиме ensemble все активные модели опрашиваются параллельно. Чем
больше разных семейств — тем устойчивее вердикт.
| Метод | Путь | Описание |
|---|---|---|
| POST | /api/auth/login |
Логин → access + refresh токены |
| POST | /api/auth/refresh |
Обновить access-токен |
| POST | /api/auth/logout |
Выход |
| GET | /api/auth/whoami |
Тип текущего субъекта доступа |
| POST | /api/scan/quick |
Quick scan (multipart file / form text) |
| POST | /api/scan/quick/json |
Quick scan (JSON, для скриптов) |
| POST | /api/scan/deep/{file_id} |
Глубокая проверка файла из хранилища |
| GET | /api/scan/reports/recent |
Последние N проверок |
| GET | /api/folders |
Список папок |
| POST | /api/folders |
Создать папку/подпапку |
| DELETE | /api/folders/{id} |
Удалить папку |
| GET | /api/folders/{id}/files |
Список файлов в папке |
| POST | /api/folders/{id}/files |
Загрузить файл в папку |
| DELETE | /api/folders/files/{id} |
Удалить файл |
| GET | /api/admin/settings |
Текущие настройки |
| PUT | /api/admin/settings |
Обновить настройки |
| GET / POST / PUT / DELETE | /api/admin/llm-providers |
CRUD LLM-провайдеров ансамбля |
| POST | /api/admin/llm-providers/{id}/toggle |
Вкл/выкл провайдера |
| GET / POST / DELETE | /api/admin/api-keys |
CRUD API-ключей |
| POST | /api/admin/api-keys/{id}/rotate |
Ротация ключа |
| GET | /api/admin/judge-status |
Готовность судьи (ONLINE/OFFLINE) |
| Переменная | По умолчанию | Описание |
|---|---|---|
MASTER_PASSWORD |
airadar |
Пароль админа по умолчанию |
JWT_SECRET |
change-me |
Секрет JWT. В prod обязательно сменить. |
ACCESS_TOKEN_TTL_MIN |
30 |
Жизнь access-токена в минутах |
REFRESH_TOKEN_TTL_DAYS |
7 |
Жизнь refresh-токена в днях |
DATABASE_PATH |
storage/airadar.db |
Путь к SQLite |
JUDGE_MODE |
ensemble |
ensemble или single |
JUDGE_HTTP_TIMEOUT_SEC |
60 |
Таймаут HTTP-вызова к LLM |
VETO_THRESHOLD |
75 |
Порог авто-ВЕТО в % |
JUDGE_MAX_RETRIES |
2 |
Retry при невалидном JSON |
DOCS_ENABLED |
true |
Включить /docs и /redoc |
- Burstiness — вариативность длин предложений. Естественный текст имеет SD/Mean ~ 0.6–1.2, LLM-генерация стремится к 0.1–0.4.
- Perplexity — классическая метрика сложности текста, аппроксимируется прокси-формулой на Shannon-энтропии биграмм.
- TTR / Yule's K / Honore's R / Sichel's S — метрики лексического богатства из корпусной лингвистики (1940-е — настоящее время).
- Саморефлексивный анализ LLM — каждая модель-детектор проверяет, не она ли могла написать текст. Это её «почерк»: типичные паттерны аргументации, нейтральность, сбалансированность.
- Блокирующее ВЕТО — концепция «семантического вето-голоса»: в задачах детекции критических аномалий статистический процент недостаточен, поэтому судья наделяется правом блокирующего решения.
Какие модели поддерживаются? Любые OpenAI-compatible. По умолчанию тестировалось на GPT 5.1, Claude Sonnet 5, Gemini 3.6 Flash, DeepSeek V4 Pro, Grok 4.3, Kimi K3. Можно подключать локальные vLLM и Ollama.
Что если нет API-ключа к LLM?
Включается OFFLINE-режим — отчёт строится только на Сигнале 1, VETO
не активируется. Полезно для быстрой проверки без внешних вызовов.
Может ли одна модель доминировать в ансамбле?
Нет. В ENSEMBLE_ONLY/FULL все активные модели опрашиваются
параллельно, ai_score — медиана, veto — большинством голосов.
Не утекут ли тексты студентов в сторонние LLM?
Текст передаётся только в подключённые вами LLM-провайдеры. AI Radar
не отправляет данные никуда, кроме явно настроенных base_url. Для
конфиденциальных данных используйте локальный vLLM/Ollama.
Что такое ВЕТО и почему это не просто высокий процент?
Это блокирующее право судьи. Работа может формально набрать невысокий
ai_score, но содержать критическую логико-структурную аномалию —
судья принудительно выставит academic_integrity = "НАРУШЕНА" с
обоснованием в veto_reason, доступным для апелляции.
Поддерживается ли multi-tenancy кроме admin/teacher? В текущей версии — две роли.
ai-radar/
├── app/
│ ├── main.py # FastAPI, lifespan, роуты /report/{id}, /docs-page
│ ├── config.py # Pydantic-Settings (.env bootstrap)
│ ├── api/
│ │ ├── auth.py # login/refresh/logout/whoami
│ │ ├── scan.py # quick, quick/json, quick/stream (SSE), deep
│ │ ├── folders.py # CRUD папок и файлов с ролями
│ │ └── admin.py # settings, LLM, API-keys, users, judge-status
│ ├── services/
│ │ ├── storage.py # aiosqlite + users + folders с owner_id
│ │ ├── auth_service.py # JWT + API keys + role-based Principal
│ │ ├── signal1_stat.py # 20 метрик Сигнала 1
│ │ ├── signal2_judge.py # Ансамбль + метасудья, саморефлексия
│ │ ├── file_parser.py # txt/docx/pdf
│ │ └── pipeline.py # Оркестратор + progress-callback для SSE
│ └── templates/
│ ├── index.html # SPA
│ ├── report.html # Страница отчёта с подсветкой
│ └── docs.html # Документация API в стиле системы
├── static/
│ ├── css/
│ │ ├── style.css # Tektur + JetBrains Mono + роли + прогресс
│ │ ├── report.css # Отчётная страница + print-color-adjust
│ │ └── docs.css
│ └── js/
│ ├── app.js # SPA + SSE прогресс + роли
│ └── report.js # Отчёт + градация подсветки
├── tests/
│ ├── test_stat.py # Тесты метрик
│ └── test_api.py # Тесты API + роли + users
├── .env.example
├── Dockerfile
├── docker-compose.yml
├── pyproject.toml
├── LICENSE (MIT)
└── README.md
| Слой | Технология |
|---|---|
| Backend | Python 3.11, FastAPI, Pydantic v2, Uvicorn |
| Auth | JWT (HMAC-SHA256) + role-based (admin/teacher) |
| Storage | SQLite (aiosqlite) |
| Files | python-docx, pypdf |
| NLP | regex tokenizer (spacy-ru — опционально) |
| LLM | httpx + OpenAI-compatible API, ансамбль |
| Frontend | HTML5, CSS3, Vanilla JS, SSE, Lucide, Google Fonts |
| Packaging | Docker, docker-compose, pyproject.toml |
- Судья тоже LLM — у него есть свои предпочтения и слепые пятна. Выбор модели-судьи влияет на результат. Рекомендуется Claude Sonnet/Opus или Gemini Pro как наиболее нейтральные.
- 20 метрик Сигнала 1 калиброваны на русскоязычных текстах — для других языков нужна проверка и переподбор весов.
- ВЕТО — не приговор, а сигнал для человека. Финальное решение об академической честности остаётся за преподавателем; отчёт даёт обоснование, а не автоматическое наказание.
MIT — используйте, модифицируйте, форкайте. Ссылка на репозиторий приветствуется.