Commit Graph

7 Commits

Author SHA1 Message Date
jze9
b471ec767a feat: две доработки в духе коммерческих систем — цитаты и авто-корпус
Some checks failed
Deploy / test (push) Failing after 4m15s
Deploy / deploy (push) Has been skipped
Ответ на "неужели больше нет" / "мы ведь можем это исправить": закрывает
две дыры относительно Антиплагиат.ру/Turnitin, о которых договорились.

1. Различение цитаты и голого плагиата (app.scoring.is_cited, worker-gpu):
   эвристика — фрагмент считается процитированным, если обрамлён кавычками
   («…», "…") либо сразу за ним (в пределах ~150 симв.) идёт скобочная ссылка
   с годом: [Иванов, 2023], (Smith, 2020) — совпадает и с нашим же форматом
   ГОСТ 7.0.5. aggregate_results теперь принимает full_text, размечает
   match["cited"] и считает uncited_similarity (доля БЕЗ похожих на цитаты —
   ближе к тому, что коммерческие системы называют "% некорректных
   заимствований") отдельно от overall_similarity (как было, для совместимости).
   Фронтенд: бейдж "Цитата" на совпадении + строка с разбивкой в отчёте
   (аддитивные опциональные поля в типах — старые задачи не ломаются).

2. Автопополнение корпуса проверенными работами (как у коммерческих систем —
   так ловится списывание у предыдущих потоков). Раньше загруженная на проверку
   работа складывалась в StagedWork и ждала РУЧНОГО одобрения админом — де-факто
   не пополняла базу для сравнения. Теперь index.auto_approve_submission
   (диспатчится из gpu.check_plagiarism ПОСЛЕ сохранения результата — чтобы
   работа не сматчилась сама с собой) добавляет её в documents автоматически,
   под настройкой AUTO_APPROVE_SUBMISSIONS (default True). Ручное
   approve/reject в админке остаётся рабочим (идемпотентно — auto-approve
   пропускает уже не-pending записи), пригодится при AUTO_APPROVE=False.
   Конвертация StagedWork→doc_data вынесена в чистый app/staging.py (без
   Celery/SQLAlchemy/MinIO) — тестируется изолированно, идентична ручному
   пути в admin.py (POST /admin/staging/{id}/approve).

Тестов добавлено 16 (scoring 8→18, новый staging.py — 6). Оба mypy-гейта
расширены (scoring.py, staging.py). Тестов всего: 112 (было 82 в последнем
подсчёте README — таблица давно отставала, заодно поправил на актуальные цифры
по всем сервисам, включая забытый в прошлый раз Qdrant).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-24 15:09:43 +05:00
jze9
e6c44f30dd docs: полное описание проекта — docs/ARCHITECTURE.md
Каноничная документация всей системы: назначение, схема, 6 сервисов и их зоны
ответственности, модель данных (все таблицы), Celery-очереди/задачи, ключевые
потоки (проверка плагиата, поиск, библиография, наполнение корпуса), 4 уровня
детекции, векторный бэкенд, инфра-топология (узлы/адреса), конфигурация, гейты
качества, наблюдаемость/эксплуатация, безопасность, раскладка репозитория.

README ссылается на ARCHITECTURE.md и DR-HA.md. Данные сверены с кодом (модели,
TaskType/TaskStatus, источники, тарифы, маршрутизация задач).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 20:45:23 +05:00
jze9
d2d99d8231 feat(obs): наблюдаемость Prometheus + Grafana под профилем observability
Раньше видимости в прод не было — только email-монитор (костыль). Добавлено
без нагрузки по умолчанию (профиль не поднимается, пока не попросят):

- API: /metrics через prometheus-fastapi-instrumentator (кол-во/латентность
  запросов по хендлерам);
- Prometheus (infra/prometheus/prometheus.yml) скрейпит API и Flower — из Flower
  приходят метрики Celery (задачи, время, воркеры) вообще без доп. кода;
- Grafana с автопровижном источника Prometheus (infra/grafana/provisioning),
  пароль через GRAFANA_ADMIN_PASSWORD;
- docker-compose.prod.yml: сервисы prometheus/grafana под profiles:[observability]
  + volumes; .env.example и README пополнены.

Запуск: docker compose --profile observability up -d prometheus grafana.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 20:37:47 +05:00
jze9
012b17304f feat(gpu): Qdrant как векторный бэкенд под флагом — снимает SPOF FAISS
FAISS-индекс — файловый синглтон в RAM одного воркера (save на каждую запись,
без блокировок, без HA, не горизонтален). Добавлен альтернативный бэкенд Qdrant
с тем же classmethod-интерфейсом, выбор через VECTOR_BACKEND — аддитивно и
безопасно: дефолт остаётся faiss, ничего не ломается, пока не переключат.

- app/qdrant_manager.py — search/add_vectors/save(no-op)/total_vectors поверх
  qdrant-client (коллекция Cosine, id точки = doc_id, upsert идемпотентен);
- app/vector_store.py — get_backend() по настройке; задачи search/plagiarism
  переведены на него (больше не импортируют FAISSManager напрямую);
- app/migrate_faiss_to_qdrant.py — перелив существующих векторов (reconstruct
  из IndexIDMap2 → upsert), идемпотентно;
- docker-compose.prod.yml — сервис qdrant под профилем `qdrant` (по умолчанию не
  поднимается, ресурсов не ест) + volume; README — раздел про переключение.

Тесты (9) гоняют QdrantManager против ВСТРОЕННОГО Qdrant (qdrant-client :memory:,
не моки) + диспетчеризацию бэкенда. Всего тестов: 82 (indexer 24, gost 24, gpu 34).
Плюсы Qdrant активируются только после явного переключения + миграции.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 20:34:43 +05:00
jze9
37ee18ac55 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>
2026-08-11 20:22:45 +05:00
jze9
673e72a15a feat(infra): переход прод/test на общую инфраструктуру вместо self-hosted
Postgres/Redis/RabbitMQ/MinIO/Ollama теперь общие серверы сети (адреса в .env),
локально в докере остаётся только Elasticsearch + app-сервисы. Старый
docker-compose.yml (полностью автономный стек) сохранён как
docker-compose.selfhosted.yml.example на случай отдельного GPU-сервера в
будущем. Добавлен docker-compose.prod.yml (app + свой nginx с TLS,
собирающий фронтенд в статику). Makefile переписан под три режима
(dev/test-up/prod). Мелкая чистка неиспользуемых импортов во фронтенде.
2026-07-27 12:22:36 +05:00
jze9
7758315632 feat: initial microservices project structure
Services:
- api: FastAPI gateway with JWT auth, async endpoints, WebSocket
- worker-gpu: CUDA sentence-transformers, FAISS IVFFlat, Ollama LLM
- worker-indexer: Winnowing+MinHash plagiarism detection, PDF/DOCX extraction
- worker-notifier: SMTP email notifications
- worker-gost: GOST 7.1-2003 and GOST R 7.0.5-2008 formatting

Infrastructure:
- docker-compose.yml (production) + docker-compose.dev.yml (hot reload)
- Nginx reverse proxy + WebSocket support
- PostgreSQL 16 with Alembic migrations
- Elasticsearch 8 with Russian/English analyzers
- MinIO, RabbitMQ, Redis, Ollama

Frontend:
- React 18 + Vite + TypeScript + TailwindCSS + Zustand + React Query v5
- 9 pages: Home, Search, Cabinet, Task, Check, Bibliography, Pricing, Login, Register

Scripts:
- Parser stubs: OpenAlex, КиберЛенинка, arXiv (Phase 0 - to be filled)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 19:42:39 +05:00