Диаграмма компонентов и потоков данных (frontend/API/очереди/воркеры/общая инфра/опциональные Qdrant и Prometheus-Grafana) + sequence-диаграмма конвейера проверки плагиата L1-L4. Дополняет текстовое ARCHITECTURE.md, на который ссылается. ARCHITECTURE.md теперь ссылается на DIAGRAM.md и INGESTION.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
14 KiB
Архитектура — Академический помощник
Каноничное описание системы. Обновляется вместе с кодом; при расхождении верить коду, а не этому файлу. Визуальная схема — DIAGRAM.md. Смежные документы: DR-HA.md (отказоустойчивость), INGESTION.md (наполнение корпуса), ../README.md (быстрый старт и команды).
1. Назначение
Веб-сервис для студентов: ввёл тему → система находит открытые академические источники, делает изложения, форматирует список литературы по ГОСТ и проверяет текст на плагиат. Всё асинхронно: пользователь отправляет задачу, закрывает браузер и получает результат на email (или в реальном времени через WebSocket, если вкладка открыта).
2. Общая схема
┌────────────────────────────┐
│ Frontend (React SPA) │ CT 102 → nginx
│ Home/Search/Check/Cabinet/ │
│ Bibliography/Settings/Admin │
└──────────────┬──────────────┘
│ HTTPS (/api, /ws)
┌──────────────▼──────────────┐
│ API Gateway (FastAPI) │ 1.32:8000
│ JWT · rate-limit · WebSocket │
│ /metrics (Prometheus) │
└───┬───────────────────────┬──┘
│ publish (RabbitMQ) │ read/write
│ │
┌────────────────────┼───────────────────┐ │
▼ ▼ ▼ │
queue.index queue.gpu queue.gost
┌───────────┐ ┌────────────┐ ┌───────────┐
│ worker- │ │ worker-gpu │ │ worker- │
│ indexer │ │ FAISS/Qdr. │ │ gost │
│ L1 Winnow │ │ L3 семант. │ │ ГОСТ 7.1/ │
│ L2 MinHash│ │ L4 LLM │ │ 7.0.5 │
│ PDF/DOCX │ │ эмбеддинги │ │ │
└─────┬─────┘ └──────┬─────┘ └─────┬─────┘
│ │ │
└─────────┬─────────┴───────┬──────────┘
▼ ▼
queue.notify общие данные
┌────────────┐ ┌──────────────────────────────┐
│ worker- │ │ PostgreSQL 1.38 · Redis 1.35 │
│ notifier │ │ RabbitMQ .82 · MinIO 1.21 │
│ SMTP email │ │ Elasticsearch (local 1.32) │
└────────────┘ │ Ollama .163 (qwen2.5:7b) │
│ [opt] Qdrant · Prometheus/Graf.│
└──────────────────────────────┘
3. Сервисы
| Сервис | Технологии | Ответственность |
|---|---|---|
| api | FastAPI, SQLAlchemy async (asyncpg), Redis, Celery-producer | HTTP/WS API, auth (JWT), rate-limits, диспетч задач в очереди, админ-панель |
| worker-indexer | Celery, PyMuPDF, python-docx, xxhash, datasketch | Извлечение текста (PDF/DOCX/TXT), фрагментация, L1 Winnowing, L2 MinHash LSH, парсинг источников, обогащение full-text |
| worker-gpu | Celery, sentence-transformers, FAISS/Qdrant, httpx→Ollama | Эмбеддинги, L3 семантический поиск, L4 LLM-анализ парафраза, семантический поиск источников |
| worker-gost | Celery | Список литературы по ГОСТ 7.1-2003 / Р 7.0.5-2008 |
| worker-notifier | Celery, smtplib | Email: письма-результаты и верификация (jze9mail.ru) |
| frontend | React 18, Vite, TS, Tailwind, Zustand, React Query | SPA: 11 публичных страниц + админ-панель. Собирается в статику, отдаётся nginx |
4. Модель данных (PostgreSQL)
- users —
email,hashed_password(bcrypt),name,is_verified,is_admin,plan(free/student/premium),verification_token. - tasks —
id(UUID),public_id(внешний),user_id,type(TaskType: search/plagiarism/summarize/gost),status(TaskStatus: queued→processing→done/failed),celery_task_id,input_data(JSON),result(JSON),error,queue_position. - documents — корпус источников:
source(openalex/arxiv/cyberleninka/ user_submission),ext_id,doi,title,authors(JSON),year,lang,journal/volume/issue/pages,abstract,url,minio_key(full-text в MinIO),faiss_id. - fingerprints —
doc_id,hash_value(BIGINT, Winnowing),position— для L1. - usage_logs —
user_id,action— учёт лимитов по тарифу. - parse_sources — задания парсеров (админка): тип, query, годы, лимит, статус.
- staged_works — пользовательские загрузки на модерацию перед добавлением в корпус.
- admin_sessions — одноразовые коды входа в админку.
5. Асинхронный конвейер (Celery + RabbitMQ)
Брокер — RabbitMQ, backend результатов — Redis. Маршрутизация по префиксу задачи:
| Очередь | Задачи | Воркер |
|---|---|---|
queue.index |
index.extract_and_check, index.add_document, index.run_parser, index.enrich_full_text |
worker-indexer |
queue.gpu |
gpu.check_plagiarism, gpu.embed_documents, gpu.search_semantic |
worker-gpu |
queue.gost |
gost.format_bibliography |
worker-gost |
queue.notify |
notify.send_task_done, notify.send_verification |
worker-notifier |
Важно: API коммитит задачу в БД до send_task (иначе гонка dispatch-before-commit).
6. Ключевые потоки
Проверка плагиата. upload (api, файл→MinIO, Task) → index.extract_and_check
(извлечь текст → фрагментация → L1 Winnowing по fingerprints → L2 MinHash LSH
в Redis) → передаёт частичные совпадения в gpu.check_plagiarism (L3 FAISS/Qdrant
семантика по фрагментам → для подозрительных L4 Ollama-парафраз) →
app.scoring.aggregate_results (итоговый %) → результат в Task → notify.send_task_done.
Поиск источников. api → gpu.search_semantic: эмбеддинг запроса → векторный поиск
(FAISS/Qdrant) + Elasticsearch BM25 → объединение → результат.
Список литературы. api → gost.format_bibliography: документы из БД →
app.bibliography.build_bibliography (сортировка кириллица→латиница, нумерация,
формат 7.1/7.0.5) → результат.
Наполнение корпуса. админка/CLI → index.run_parser (OpenAlex/arXiv/КиберЛенинка,
фильтр is_oa) → index.add_document (дедуп по ext_id, fingerprints, MinHash,
эмбеддинг) → index.enrich_full_text (скачать OA-PDF → MinIO → переиндексация).
7. Детекция плагиата — 4 уровня
- L1 Winnowing (
worker-indexer/app/algorithms/winnowing.py) — точные/частичные совпадения: k-граммы → xxHash → минимум в скользящем окне → fingerprint; Jaccard. - L2 MinHash LSH (
.../minhash.py) — нечёткие совпадения: шинглы → MinHash (128 перм.) → LSH-индекс в общем Redis (префиксantiplag_lsh, upsert, graceful-фолбэк в память). - L3 семантика (
worker-gpu) — эмбеддингиparaphrase-multilingual-mpnet-base-v2(768d, нормированы) → cosine в FAISSIndexIDMap2(IndexFlatIP)или Qdrant (VECTOR_BACKEND); порог 0.75. - L4 LLM-парафраз — Ollama
qwen2.5:7bоценивает пары «источник↔фрагмент» для подозрительных из L3; порог confidence 0.7.
Итог: scoring.aggregate_results — доля уникальных помеченных позиций (не выше 100%).
8. Векторный бэкенд
Абстрагирован за worker-gpu/app/vector_store.get_backend(); VECTOR_BACKEND=faiss
(файловый синглтон, дефолт) или qdrant (сервис, снимает SPOF/конкурентную запись).
Переключение и миграция — см. README, раздел «Векторный бэкенд».
9. Инфраструктура и топология
| Компонент | Узел | Примечание |
|---|---|---|
| api + воркеры + Elasticsearch | 1.32 (app-хост) | docker-compose.prod.yml |
| Frontend (nginx, статика + TLS) | CT 102 | деплоится отдельно |
| PostgreSQL 16 | 1.38 (выделенный LXC) | UTF8; бэкап→MinIO |
| Redis 7 | 1.35 (выделенный LXC) | кэш, rate-limits, LSH |
| RabbitMQ | 192.168.20.82 | брокер Celery |
| MinIO (S3) | 1.21 | документы, full-text, бэкапы |
| Ollama (qwen2.5:7b) | 192.168.20.163 | GPU-сервер |
| Qdrant / Prometheus / Grafana | 1.32 | опционально, под compose-профилями |
Деплой — Gitea Actions по push в main: гейт test (ruff+mypy → 82 юнит-теста),
затем deploy (needs: test) через scripts/deploy.sh (умная пересборка изменённых
сервисов). PG/Redis не в compose — общая инфра берётся из .env.
10. Конфигурация
Всё через .env (пример — .env.example). Обязательно менять: SECRET_KEY,
POSTGRES_PASSWORD, MINIO_SECRET_KEY. Опции: VECTOR_BACKEND, QDRANT_URL,
GRAFANA_ADMIN_PASSWORD. .env не в git и исключён из деплой-rsync (не откатывается).
11. Качество и тесты
- 82 юнит-теста (pytest, per-service) на чистую логику L1-L4/скоринг/фрагменты/
ГОСТ/библиография; инфра замокана или не нужна. Запуск:
make test. - Гейты CI: ruff (весь Python) + mypy (доменная логика) + тесты — блокируют деплой.
make lint. Хермет-раннеры вpython:3.11-slim. - Чистая доменная логика вынесена из Celery-задач в тестируемые модули
(
scoring.py,fragments.py,bibliography.py). Подробнее — README «Тестирование».
12. Наблюдаемость и эксплуатация
- Мониторинг:
antiplag_monitor.py(cron 5 мин, 7 сервисов, email-алерт при смене статуса). Опционально — Prometheus+Grafana (профильobservability, метрики API + Flower). - Бэкапы:
pg_dump→gzip→MinIO, cron 03:00, ротация 14. Проверка восстановления —scripts/ops/pg_restore_verify.sh. HA/DR — DR-HA.md.
13. Безопасность
JWT-аутентификация, bcrypt-хэши паролей, email-верификация, отдельный вход в админку
(одноразовые коды, admin_sessions). Rate-limits по тарифу — в Redis. CORS — явные
origins. Пользователь видит только свои задачи (ownership проверяется, в т.ч. на WebSocket).
14. Раскладка репозитория
services/ api, worker-{gpu,indexer,notifier,gost}, frontend
scripts/ parsers/ (OpenAlex/arXiv/КиберЛенинка), ops/, deploy.sh,
run_tests.sh, run_lint.sh
infra/ nginx/, prometheus/, grafana/
docs/ ARCHITECTURE.md (этот файл), DR-HA.md
.gitea/workflows/ deploy.yml (гейт test → deploy)
ruff.toml · mypy.ini · Makefile · docker-compose.prod.yml