feat: две доработки в духе коммерческих систем — цитаты и авто-корпус
Ответ на "неужели больше нет" / "мы ведь можем это исправить": закрывает
две дыры относительно Антиплагиат.ру/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>
This commit is contained in:
@@ -66,6 +66,12 @@ export function PlagiarismReport({ data }: PlagiarismReportProps) {
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
Проверено фрагментов: {data.total_fragments} · Выявлено совпадений: {data.flagged_fragments}
|
||||
</p>
|
||||
{!!data.cited_fragments && (
|
||||
<p className="text-sm text-gray-500 mt-0.5">
|
||||
из них корректно процитировано: {data.cited_fragments} · без указания источника:{' '}
|
||||
{data.uncited_similarity?.toFixed(1)}%
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -125,6 +131,14 @@ export function PlagiarismReport({ data }: PlagiarismReportProps) {
|
||||
<span className="text-xs text-gray-400 px-2 py-0.5 bg-white rounded-full border border-gray-200">
|
||||
{METHOD_LABELS[match.method] || match.method}
|
||||
</span>
|
||||
{match.cited && (
|
||||
<span
|
||||
className="text-xs font-medium px-2 py-0.5 rounded-full bg-blue-100 text-blue-700"
|
||||
title="Похоже на корректно оформленную цитату (кавычки или ссылка с годом рядом)"
|
||||
>
|
||||
Цитата
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{/* Фрагмент */}
|
||||
<div className="px-4 py-3">
|
||||
|
||||
@@ -56,13 +56,22 @@ export interface PlagiarismMatch {
|
||||
source_title: string;
|
||||
source_url: string | null;
|
||||
source_db: string;
|
||||
// Похоже на корректную цитату (кавычки/ссылка с годом рядом) — эвристика,
|
||||
// см. app.scoring.is_cited. Опционально: старые задачи в БД посчитаны без
|
||||
// этого поля.
|
||||
cited?: boolean;
|
||||
}
|
||||
|
||||
export interface PlagiarismResultData {
|
||||
overall_similarity: number;
|
||||
// Доля БЕЗ похожих на корректную цитату фрагментов — «настоящий» плагиат.
|
||||
// Опционально по той же причине, что и cited.
|
||||
uncited_similarity?: number;
|
||||
matches: PlagiarismMatch[];
|
||||
total_fragments: number;
|
||||
flagged_fragments: number;
|
||||
cited_fragments?: number;
|
||||
uncited_fragments?: number;
|
||||
by_method?: {
|
||||
exact: number;
|
||||
fuzzy: number;
|
||||
|
||||
Reference in New Issue
Block a user