Документация сильно разошлась с кодом за последние недели работы — привёл в
соответствие ARCHITECTURE.md, README, DIAGRAM.md, INGESTION.md:
- LLM (L4) и эмбеддинги (L3) теперь переключаемые бэкенды (LLM_BACKEND,
EMBED_BACKEND), а не жёстко Ollama/qwen2.5:7b — старая модель эмбеддингов
(768d mpnet) заменена на bge-m3 (1024d); L4 может идти через OpenRouter
(DeepSeek) с прокси singbox для обхода геоблокировки.
- .env на проде больше не редактируется руками — на каждом деплое
генерируется из Infisical; старая инструкция "cp .env.example .env; nano
.env" вводила в заблуждение (правки терялись бы на следующем деплое).
- README "Три docker-compose файла"/deploy разделы противоречили реальности:
фронтенд+TLS реально раздаёт хостовой nginx на CT 102, не докеризованный
nginx-сервис из compose (тот не запускается вообще).
добавлен PMC-парсер, self-match исключение объяснено, число тестов (113)
синхронизировано между файлами (было 82/122 в разных местах).
- INGESTION.md: снимок "42K доков, 0 русских" от 12.08 заменён актуальным
(165K доков, ru теперь большинство) — иначе документ откровенно врёт.
- Diagram: узлы под текущую топологию (embedding-gpu, OpenRouter, Infisical).
Заодно, раз перепроверял код на соответствие докам:
- Удалён мёртвый и битый эндпоинт GET /reports/{task_id} — фильтровал по
внутреннему Task.id вместо public_id (никогда не мог сработать через
обычный клиентский поток), фронтенд его всё равно не вызывал —
функциональность полностью дублирует рабочий GET /tasks/{public_id}.
- Убран мёртвый конфиг FAISS_NLIST/FAISS_NPROBE (worker-gpu/config.py) —
индекс всегда IndexFlatIP, IVF нигде не строится, эти поля ничего не делали.
4.3 KiB
4.3 KiB
Схема системы
Визуальная схема к ARCHITECTURE.md (там — полное текстовое описание).
Компоненты и потоки данных
flowchart TB
subgraph client["Клиент"]
FE["Frontend (React SPA)<br/>CT 102, nginx"]
end
subgraph app["App-хост 1.32"]
API["API (FastAPI)<br/>JWT · rate-limit · /metrics"]
MQ[("RabbitMQ .82<br/>брокер Celery")]
subgraph workers["Celery-воркеры"]
IDX["worker-indexer<br/>L1 Winnowing · L2 MinHash<br/>PDF/DOCX · парсеры"]
GPU["worker-gpu<br/>L3 семантика · L4 LLM<br/>эмбеддинги"]
GOST["worker-gost<br/>ГОСТ 7.1 / 7.0.5"]
NOTIFY["worker-notifier<br/>SMTP email"]
end
ES[("Elasticsearch<br/>BM25, local")]
VEC{{"Векторный бэкенд<br/>VECTOR_BACKEND"}}
FAISS["FAISS<br/>(файл, дефолт)"]
QDR["Qdrant<br/>(опционально)"]
end
subgraph shared["Общая инфраструктура"]
PG[("PostgreSQL 1.38<br/>users/tasks/documents/<br/>fingerprints/...")]
REDIS[("Redis 1.35<br/>кэш · rate-limit · LSH-индекс")]
MINIO[("MinIO 1.21<br/>документы · full-text · бэкапы")]
OLLAMA["Ollama .109 embedding-gpu<br/>bge-m3, эмбеддинги (L3)"]
OPENROUTER["OpenRouter/DeepSeek<br/>LLM L4 (опц., через singbox-proxy)"]
INFISICAL["Infisical .111<br/>секреты → .env на каждом деплое"]
end
subgraph obs["Опционально (профили compose)"]
PROM["Prometheus"]
GRAF["Grafana"]
end
FE -->|"HTTPS /api, /ws"| API
API -->|"send_task"| MQ
API <-->|"users/tasks"| PG
API <-->|"session/rate-limit"| REDIS
MQ -->|"queue.index"| IDX
MQ -->|"queue.gpu"| GPU
MQ -->|"queue.gost"| GOST
MQ -->|"queue.notify"| NOTIFY
IDX <-->|"documents/fingerprints"| PG
IDX <-->|"MinHash LSH (antiplag_lsh)"| REDIS
IDX <-->|"PDF/full-text"| MINIO
IDX --> ES
IDX -->|"gpu.embed_documents"| MQ
GPU <-->|"documents"| PG
GPU -->|"L3 эмбеддинги"| OLLAMA
GPU --> VEC
VEC --> FAISS
VEC -.->|"переключение флагом"| QDR
GPU -.->|"L4 парафраз (LLM_BACKEND)"| OLLAMA
GPU -.->|"L4 парафраз, опц."| OPENROUTER
GPU --> ES
GOST <-->|"documents"| PG
NOTIFY <-->|"tasks"| PG
NOTIFY -->|"email"| SMTP(["jze9mail.ru"])
API -->|"/metrics"| PROM
PROM --> GRAF
style VEC fill:#00000000,stroke-dasharray: 4 3
style obs fill:#00000000,stroke-dasharray: 4 3
Конвейер проверки плагиата (4 уровня)
sequenceDiagram
participant U as Студент
participant API as API
participant IDX as worker-indexer
participant GPU as worker-gpu
participant LLM as Ollama/OpenRouter<br/>(LLM_BACKEND)
U->>API: upload файла
API->>API: сохранить в MinIO, создать Task, commit
API->>IDX: index.extract_and_check
IDX->>IDX: извлечь текст → фрагменты
IDX->>IDX: L1 Winnowing (fingerprints)
IDX->>IDX: L2 MinHash LSH (Redis)
IDX->>GPU: gpu.check_plagiarism (частичные совпадения)
loop по подозрительным фрагментам
GPU->>GPU: L3 семантический поиск (FAISS/Qdrant)
GPU->>LLM: L4 check_paraphrase
LLM-->>GPU: is_paraphrase, confidence
end
GPU->>GPU: app.scoring.aggregate_results (итоговый %)
GPU->>API: результат → Task.result
GPU-->>U: notify.send_task_done → email/WebSocket
Легенда
- Сплошные стрелки — прямые вызовы/запросы; пунктир у
VEC— переключение бэкенда по настройкеVECTOR_BACKEND, не одновременная работа обоих. Пунктир у L4 (OLLAMA/OPENROUTER) — то же самое дляLLM_BACKEND. obs(Prometheus/Grafana) иQdrant— опциональны, поднимаются подdocker compose --profile qdrant|observability, по умолчанию выключены.