Две связанные проблемы, ломавшие качество детекции:
1. Уровень 1 (Winnowing) репортил весь документ одним совпадением на позиции
0..длина — в отчёте нельзя было понять, ГДЕ плагиат. Теперь winnow'им
каждый фрагмент и находим источник + позицию для каждого, так отчёт
показывает "символы A-B скопированы из источника X".
2. MAX_FINGERPRINTS_PER_DOC=500 обрезал отпечатки статьи (у типичной статьи
их ~3600), причём произвольную выборку. Из-за этого скопированный фрагмент
почти не разделял отпечатки с источником (проверено: хранилось ~14%,
фрагмент находил 17% своих хэшей → не срабатывало). Winnowing рассчитан на
ПОЛНОЕ хранение; поднял лимит до 20000.
Также overall_similarity считается по числу уникальных помеченных позиций,
а не совпадений — фрагмент, совпавший с несколькими источниками, больше не
раздувает процент выше 100.
Проверено end-to-end: документ с дословной вставкой из статьи корпуса →
вставка локализована (chars 1027-2385 = 100%, источник атрибутирован);
чисто оригинальный текст → 0% (нет ложных срабатываний).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Семантический поиск (уровень 3) не работал вообще: индекс IndexIVFFlat с
nlist=1024 требует ~40000 векторов для обучения, а до обучения векторы
складывались во временный in-memory _flat_index, который:
- не сохранялся на диск (save() писал только пустой _index) → терялся при
рестарте;
- не участвовал в поиске (search() искал только в необученном _index и
сразу возвращал []).
Итог: в FAISS всегда было 0 векторов, семантика возвращала пусто.
Заменено на IndexIDMap2(IndexFlatIP): без обучения, работает с первого
вектора, doc_id хранится внутри индекса, корректно персистится. На
нормализованных векторах inner product = cosine, порог 0.75 сохраняет смысл.
Добавлена идемпотентность add_vectors (remove_ids перед add).
Проверено: 66 документов → ntotal=66, поиск возвращает релевантные
результаты со score 0.72-0.78, round-trip save/load сохраняет векторы.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Резенд письма верификации (/auth/resend-verification), модалка на
фронте с поллингом статуса, страница /verify-email/:token
- SMTP переведён на собственный Postfix (mail.jze9mail.ru, STARTTLS,
SMTP_TLS_VERIFY) вместо Yandex-заглушки в дефолтах и .env.example
- OLLAMA_URL и модель в worker-gpu синхронизированы с новым GPU-хостом
(llama3:8b -> qwen2.5:7b, которой раньше не было на сервере)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>