Files
grabber-ai/docs/plan.md
T
DenozordecandClaude Sonnet 5.5 8cbd800ec7 Релиз целиком: вход по ссылке, агрегат студий/типов/18+, малая int8-модель
- src/fetch.py: загрузка по URL (allowlist трекеров, защита от SSRF, cp1251)
- src/release.py: агрегат релиза, студии из заголовка раздачи (ПМ (LostFilm))
- predict --url, POST /predict {"url"}; ответ расширен, tracks сохранён
- export_onnx --quantize: tiny2 int8 29 МБ, parity 99.2-100%
- тесты (52 ok), docs/plan.md, docs; target/ убран из git

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-27 17:02:04 +07:00

5.4 KiB
Raw Blame History

План доработки: модель озвучки для grabber

Цель

По ссылке на раздачу (rutracker / kinozal / nnm-club) или её HTML определить на уровне релиза: какие дорожки озвучки есть, кто их сделал (студия / переводчик), какого они типа (дубляж, многоголосый, …) и есть ли 18+. Модель должна быть маленькой и встраиваемой в grabber.

Что уже есть (анализ)

  • Multi-task RuBERT (тип 14 классов + BIO-спан автора + 18+), 3742 строки, joint exact 0.946 (base) / 0.915 (tiny2); ONNX-экспорт с parity 100%; FastAPI-сервис; клиенты Rust/TS/PowerShell; тесты и документация.
  • grabber (C:\Users\shats\Dev\grabber) — PHP 8.1 + Docker, интеграции Radarr/Sonarr/qBittorrent/Prowlarr; студии с kinozal разбирает регулярками (KinozalReleaseParser.php, ProwlarrReleaseEnricher.php), идёт Rust-порт. Естественный путь интеграции — HTTP-сервис (PHP ходит curl-ом), ONNX нужен для Rust-порта.

Пробелы относительно задачи

# Пробел Решение
1 Нет входа «по ссылке» (только text/html) url в CLI, сервисе, API: fetch (таймаут, UA, cp1251), определение трекера по домену
2 Ответ — плоский список дорожек Агрегат релиза: дедуп дорожек, уникальные студии с типами, is_18plus релиза; поле tracks не ломаем
3 Заголовок раздачи (/ ПМ (LostFilm) /) не используется fallback-парсинг title, если дорожек 0 или студии нет в дорожках
4 kinozal: авторы грузятся JS при работе по URL запросить вкладку озвучки напрямую (эндпоинт — из data/samples/kinozal*.html, не угадывать)
5 «Маленькая» модель: best = base (~440 МБ) tiny2 (30M) + ONNX + int8-квантизация; решение по цифрам parity/размера
6 Precision 0.83 на rutracker разобрать ложные срабатывания e2e — скорее всего регулярки сегментации
7 В git закоммичен examples/rust/*/target/ .gitignore + удалить из индекса

Порядок работ

  1. Baseline: tests + e2e на текущих моделях (цифры в конец документа).
  2. URL + агрегат релиза (src/fetch.py, src/release.py, эндпоинт POST /predict с url, CLI --url).
  3. Title-fallback в html_extract.py.
  4. kinozal-вкладка (если эндпоинт найден в сэмплах).
  5. Разбор false-positives сегментации.
  6. tiny2 + int8 ONNX, замер размера/parity.
  7. Тесты на каждый пункт, обновление docs/README.
  8. .gitignore + чистка target/.

Критерии готовности

  • python -m src.predict --url <ссылка> печатает агрегат релиза;
  • e2e precision/recall не хуже baseline;
  • малая модель < ~40 МБ (int8), parity ≥ 99%;
  • тесты зелёные, docs обновлены.

Baseline

Модель models/best (ruBert-base), tests/e2e_check.py:

  • rutracker: precision 0.826 / recall 0.984 (n=290);
  • kinozal: 0.107 / 0.107 (n=28) — в текстовых дампах нет авторов (JS), потолок данных;
  • smoke вне датасета: тип 9/10, автор 5/10, 18+ 10/10;
  • tests/run_tests.py: 34 ok.

Статус

Шаг Состояние
1 baseline сделано
2 URL + агрегат релиза сделано: src/fetch.py, src/release.py, --url, POST /predict {"url"}
3 title-fallback сделано (ПМ (LostFilm) → дорожка с source: "title"); работает для HTML, у текстовых дампов заголовка нет
4 kinozal-вкладка не сделано в сервисе: страница релиза требует авторизации, а get_srv_details.php?id=…&pagesd=N уже вызывает KinozalClient.php в grabber. Рекомендация: grabber скачивает вкладку сам и шлёт {"html": …}
5 false-positives сегментации не сделано (precision rutracker 0.826 — отдельный разбор)
6 tiny2 + int8 сделано: 29.3 МБ, parity 99.8% тип / 99.2% спан / 100% 18+ (reports/onnx_parity_tiny2_int8.md)
7 тесты run_tests.py: 52 ok (URL allowlist/SSRF, декодирование, title, агрегат)
8 target/ сделано

Открытые вопросы

  • Подтвердить, что grabber (PHP) интегрируется по HTTP (рекомендуется), а Rust-порт — через ONNX int8 (models/tiny2-onnx/model.int8.onnx).
  • Качество tiny2 против base по e2e на страницах не мерили — только parity.