docs(readme): секция «Тестирование и качество» + фикс устаревших фактов

Добавлена секция про CI-гейты (ruff+mypy, 73 юнит-теста, make-команды,
таблица покрытия по слоям L1-L4/скоринг/фрагменты/ГОСТ/библиография).

Заодно поправлены устаревшие технические утверждения, разошедшиеся с кодом:
- FAISS-GPU (IVFFlat) → FAISS-CPU (IndexIDMap2 · IndexFlatIP) — реальный индекс;
- Ollama llama3:8b → qwen2.5:7b; убран RTX 2060 (LLM на отдельном GPU-сервере);
- уточнено описание 4 уровней проверки под фактическую реализацию.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jze9
2026-08-11 20:22:45 +05:00
parent ccc3521e74
commit 37ee18ac55

View File

@@ -32,7 +32,7 @@
Инфраструктура: Инфраструктура:
PostgreSQL 16 · Redis 7 · RabbitMQ 3 · Elasticsearch 8 PostgreSQL 16 · Redis 7 · RabbitMQ 3 · Elasticsearch 8
MinIO (4TB) · Ollama (llama3:8b) · NVIDIA RTX 2060 MinIO (S3) · Ollama (qwen2.5:7b) · отдельный GPU-сервер
``` ```
## Быстрый старт ## Быстрый старт
@@ -74,8 +74,8 @@ make migrate # Применить Alembic миграции
make logs # Логи всех сервисов make logs # Логи всех сервисов
make shell-api # Shell в контейнере API make shell-api # Shell в контейнере API
make shell-gpu # Shell в контейнере GPU воркера make shell-gpu # Shell в контейнере GPU воркера
make lint # Запустить линтер make lint # ruff + mypy в контейнере (тот же гейт, что в CI)
make test # Запустить тесты make test # юнит-тесты всех сервисов в контейнерах
make clean # Удалить контейнеры и volumes make clean # Удалить контейнеры и volumes
``` ```
@@ -84,20 +84,20 @@ make clean # Удалить контейнеры и volumes
| Компонент | Технологии | | Компонент | Технологии |
|-----------|-----------| |-----------|-----------|
| API Gateway | FastAPI 0.111, Python 3.11, SQLAlchemy 2.0, Alembic | | API Gateway | FastAPI 0.111, Python 3.11, SQLAlchemy 2.0, Alembic |
| GPU Worker | sentence-transformers, FAISS-GPU (IVFFlat), Ollama (llama3:8b) | | GPU Worker | sentence-transformers, FAISS-CPU (IndexIDMap2 · IndexFlatIP), Ollama (qwen2.5:7b) |
| Indexer | PyMuPDF, python-docx, Winnowing, MinHash LSH | | Indexer | PyMuPDF, python-docx, Winnowing, MinHash LSH |
| Очереди | RabbitMQ (брокер) + Celery 5 (воркеры) + Redis (результаты) | | Очереди | RabbitMQ (брокер) + Celery 5 (воркеры) + Redis (результаты) |
| База данных | PostgreSQL 16 | | База данных | PostgreSQL 16 |
| Поиск | Elasticsearch 8 (BM25) + FAISS GPU (cosine) | | Поиск | Elasticsearch 8 (BM25) + FAISS (cosine, IndexFlatIP) |
| Хранилище | MinIO (S3-совместимый) | | Хранилище | MinIO (S3-совместимый) |
| Frontend | React 18, Vite, TypeScript, TailwindCSS, Zustand, React Query v5 | | Frontend | React 18, Vite, TypeScript, TailwindCSS, Zustand, React Query v5 |
## Проверка плагиата (4 уровня) ## Проверка плагиата (4 уровня)
1. **Winnowing + MinHash** (~мс) — точное совпадение по fingerprints 1. **Winnowing** — точные/частичные совпадения по fingerprint'ам (xxHash + скользящее окно)
2. **n-граммы + Jaccard** (~сек) — нечёткое совпадение 2. **MinHash LSH** — нечёткие совпадения (шинглы + Jaccard, индекс в общем Redis)
3. **FAISS GPU cosine** (~мс) — семантическое сходство (порог 0.75) 3. **FAISS cosine** — семантическое сходство (порог 0.75; IndexFlatIP на нормированных эмбеддингах)
4. **Ollama Llama3** (~2сек) — LLM анализ парафраза (confidence > 0.7) 4. **Ollama qwen2.5:7b** — LLM-анализ парафраза (порог confidence 0.7)
## Тарифные планы ## Тарифные планы
@@ -159,6 +159,40 @@ make migrate
Nginx работает внутри контейнера (`docker-compose.prod.yml`, сервис `nginx`, Dockerfile в `infra/nginx/Dockerfile`) — собирает `services/frontend` в статику и отдаёт её вместе с проксированием `/api/`, `/ws/` на `api:8000` по конфигу `infra/nginx/nginx.conf`. Контейнер монтирует `/etc/letsencrypt` с хоста как read-only — сертификат обновляется на хосте (`certbot renew`), контейнер просто читает его. Nginx работает внутри контейнера (`docker-compose.prod.yml`, сервис `nginx`, Dockerfile в `infra/nginx/Dockerfile`) — собирает `services/frontend` в статику и отдаёт её вместе с проксированием `/api/`, `/ws/` на `api:8000` по конфигу `infra/nginx/nginx.conf`. Контейнер монтирует `/etc/letsencrypt` с хоста как read-only — сертификат обновляется на хосте (`certbot renew`), контейнер просто читает его.
## Тестирование и качество кода
Перед деплоем CI (`.gitea/workflows/deploy.yml`, job `test`) прогоняет два гейта,
и `deploy` стартует, только если оба зелёные — кривой код в прод не уезжает:
1. **Линт** — `ruff` (весь Python) + `mypy` (чистая доменная логика).
Конфиги: [`ruff.toml`](ruff.toml), [`mypy.ini`](mypy.ini).
2. **Юнит-тесты** — `pytest` по сервисам: 73 теста на ядро детекции и форматирования,
без внешней инфры (БД/Redis/GPU/Ollama замоканы либо не нужны).
```bash
make lint # ruff + mypy в изолированном контейнере
make lint-fix # авто-исправления ruff
make test # все юнит-тесты в контейнерах
make test-one SVC=worker-gost # тесты одного сервиса
```
Всё гоняется в `python:3.11-slim` (не засоряя хост) через
[`scripts/run_lint.sh`](scripts/run_lint.sh) и [`scripts/run_tests.sh`](scripts/run_tests.sh).
**Что покрыто.** Чистая логика вынесена из Celery-задач в отдельные тестируемые
модули (доменная логика отдельно от оркестрации):
| Слой | Модуль | Тестов |
|------|--------|:------:|
| L1 — точные совпадения | `worker-indexer/app/algorithms/winnowing.py` | 13 |
| L2 — нечёткие (MinHash LSH) | `worker-indexer/app/algorithms/minhash.py` | 6 |
| Разбиение на фрагменты | `worker-indexer/app/fragments.py` | 5 |
| L3 — семантический индекс | `worker-gpu/app/faiss_manager.py` | 5 |
| L4 — LLM-парафраз | `worker-gpu/app/ollama_client.py` | 12 |
| Итоговый % плагиата | `worker-gpu/app/scoring.py` | 8 |
| ГОСТ 7.1 / 7.0.5 | `worker-gost/app/formatters/` | 17 |
| Список литературы | `worker-gost/app/bibliography.py` | 7 |
## Лицензия ## Лицензия
MIT MIT