Skip to content

Latest commit

 

History

36 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AI Radar

Python FastAPI License Language Status

Детектор, который проверяет не текст, а смыслы.

Спойлер: обычные антиплагиат-детекторы ловят синтаксис («таким образом, подводя итог...»). Современные модели этот синтаксис уже научились маскировать — копируют стиль, добавляют «личный опыт», перефразируют штампы. Статистика одна, а смысл другой. AI Radar не спорит с текстом — он спрашивает у самих LLM: «это написал ты?». AI Radar определяет академическую честность, считая, что ИИ - современный инструмент, и само по себе его применение не является нарушением.


Откуда задача

Студенческие работы, рефераты, дипломы и эссе массово пишутся через ChatGPT, Claude, DeepSeek, Gemini, Grok, Kimi. Встроенные детекторы вроде Turnitin и GPTZero часто ошибаются в обе стороны: ложно срабатывают на живых текстах с богатой лексикой и пропускают явно сгенерированные — особенно после ручного перефразирования (paraphrase attack).

Преподаватели и научные руководители остаются один на один с текстом, без инструмента, которому можно доверять — и уж тем более без возможности обосновать вердикт студенту, который придёт оспаривать оценку.

AI Radar собран под принцип «не доверяй одному сигналу»: статистика считает математику, ансамбль LLM проверяет «свой почерк», а метасудья выносит финальный вердикт с правом заблокировать работу независимо от процента.


Почему не Turnitin / GPTZero / Originality.ai

Инструмент На чём основан Где ломается
Turnitin AI Detector Статистика + perplexity Ложные срабатывания на носителях языка с богатой лексикой
GPTZero Burstiness + perplexity Обходится простым перефразированием (paraphrase attack)
Originality.ai Классификатор-бинарник Чёрный ящик, нет обоснования вердикта, нет апелляции
ZeroGPT Эвристики + ML-модель Не различает «похоже на ИИ по стилю» и «реально написано ИИ»
AI Radar 20 метрик + ансамбль LLM + метасудья с ВЕТО Проверяет логику и «почерк» модели, а не только синтаксис. Каждый вердикт — с обоснованием для апелляции

Ключевое отличие: остальные детекторы ищут следы генерации в тексте. AI Radar ищет следы отсутствия человека — личного опыта, конкретики, сомнений, авторской позиции. А заодно спрашивает у 6 разных LLM: «похоже ли это на то, что написал бы ты сам?» — модели узнают собственный почерк лучше любой статистики.


В чём особенность

1. Двухуровневый AI-судья

Уровень 1 — Ансамбль детекторов. Любое число OpenAI-compatible моделей (ChatGPT, Claude, Gemini, DeepSeek, Grok, Kimi) параллельно анализируют текст. Каждая модель проводит саморефлексивный анализ: представляет, что могла бы написать этот текст сама, и оценивает, насколько это похоже на её собственный стиль аргументации.

Что ищут детекторы:

  • Следы генерации LLM — механическая однородность глубины абзацев, повторяющиеся клише, сверхправильная структура.
  • Чья логика — сбалансированные «про и контра», нейтральность, уход от позиции, «правильные», но поверхностные выводы, галлюцинации.
  • Человеческие особенности (их отсутствие = сигнал ИИ) — личный опыт, конкретные истории, имена, даты, креативность, юмор, ирония, авторская позиция, «шероховатости» и сомнения.

Уровень 2 — Метасудья. ОДНА сильная модель (рекомендация: Claude Sonnet/Opus, Gemini Pro), которая не видит исходный текст. Ей передаются: сводка 20 статистических метрик, вердикты всех детекторов ансамбля (ai_score, veto, фрагменты, признаки человека/ИИ) и промпт для оценки. Метасудья выявляет ошибки отдельных детекторов, оценивает согласованность ансамбля и выносит финальный вердикт.

2. Блокирующее ВЕТО

Судья может выставить academic_integrity = "НАРУШЕНА" независимо от итогового процента, если выявил критические логико-структурные аномалии генерации. Обоснование (veto_reason) сохраняется в отчёте и доступно для апелляции студента.

3. Три режима работы

Статус Что работает Финальный вердикт 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_THRESHOLDacademic_integrity = "НАРУШЕНА".


Что видит преподаватель

Отдельная страница отчёта с:

  • Круговой диаграммой итогового ai_score с цветовой индикацией (зелёный / жёлтый / красный).
  • Бейджем ВЕТО — «АКТИВИРОВАНО» / «НЕ АКТИВИРОВАНО».
  • Статусом академической честности — «ПОДТВЕРЖДЕНА» / «НАРУШЕНА».
  • Полной матрицей 20 метрик Сигнала 1 с тултипами-пояснениями.
  • Вердиктами ансамбля — какой детектор что поставил, какие признаки человека/ИИ нашёл.
  • Вердиктом метасудьи — финальный скор и обоснование.
  • Текстом работы с подсветкой в три уровня: жёлтый (подозрение), оранжевый (высокая уверенность), красный (критично).
  • Кнопками «Распечатать / PDF» и «Скачать JSON».

Прогресс-бар показывает пошаговые статусы в реальном времени: «Считаю метрики…» → «Опрашиваю ансамбль из 6 детекторов…» → «Метасудья оценивает вердикты…» → «Готово!» — с ETA в секундах.


Сигнал 1: 20 статистических метрик

Без локальных нейросетей — чистая математика на 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 (рекомендуется сменить в Админ-панели сразу после первого входа).


Доступ через API

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


Быстрый старт

Docker (рекомендуется)

git clone <your-repo-url> ai-radar
cd ai-radar
docker-compose up -d
# UI: http://localhost:8000
# Docs: http://localhost:8000/docs-page

Локально

python -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 8000

Тесты

pytest -v

Первый вход

  1. Логин: admin | Пароль: airadar
  2. Откройте Админ-панель → Ансамбль детекторов и добавьте модели. Рекомендуемые семейства: ChatGPT, Claude, Gemini, DeepSeek, Grok, Kimi.
  3. Назначьте Метасудью (Claude Sonnet/Opus или Gemini Pro).
  4. Бейдж в шапке покажет 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 все активные модели опрашиваются параллельно. Чем больше разных семейств — тем устойчивее вердикт.


API-эндпоинты

Метод Путь Описание
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 — каждая модель-детектор проверяет, не она ли могла написать текст. Это её «почерк»: типичные паттерны аргументации, нейтральность, сбалансированность.
  • Блокирующее ВЕТО — концепция «семантического вето-голоса»: в задачах детекции критических аномалий статистический процент недостаточен, поэтому судья наделяется правом блокирующего решения.

FAQ

Какие модели поддерживаются? Любые 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 калиброваны на русскоязычных текстах — для других языков нужна проверка и переподбор весов.
  • ВЕТО — не приговор, а сигнал для человека. Финальное решение об академической честности остаётся за преподавателем; отчёт даёт обоснование, а не автоматическое наказание.

License

MIT — используйте, модифицируйте, форкайте. Ссылка на репозиторий приветствуется.

About

Автономный детектор ИИ-контента и академической честности. Двухсигнальная математическая модель + AI-Судья, проверяющий смыслы и логику.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages