# Инференс: CLI, Python API, JSON-контракт ## CLI (src/predict.py) ```bash # одна дорожка текстом (префикс «Перевод:» не обязателен, но допустим) python -m src.predict --text "Перевод: Профессиональный (многоголосый закадровый) | HDRezka Studio 18+" # HTML-страница целиком -> все дорожки релиза python -m src.predict --html data/samples/rt-topic.html # текстовый дамп страницы python -m src.predict --file data/pages/6907007.txt # результат в файл + выбор модели python -m src.predict --file page.txt --out result.json --model models/base ``` Кодировка входных файлов определяется автоматически (utf-8 → cp1251). HTML распознаётся по содержимому, так что `--html` и `--file` взаимозаменяемы. ## Python API ```python from src.predict import DubPredictor model = DubPredictor() # models/best; параметр device определяется сам model.predict_text("Авторский (одноголосый закадровый) - Ю. Сербин") # -> dict (см. контракт ниже) model.predict_html(open("page.html", encoding="utf-8").read()) # -> list[dict] — по одному на каждую найденную дорожку model.predict_page("Перевод: Дублированный | MovieDalen\n...") # текст без HTML model.predict_file("page.txt") ``` ## JSON-контракт ```json { "tracks": [ { "segment": "Профессиональный (многоголосый закадровый) | HDRezka Studio 18+", "translation_type": "проф. многоголосый", "type_confidence": 0.99, "studio_span": "HDRezka Studio", "studio": "HDrezka", "studio_confidence": 0.97, "is_18plus": true, "age_confidence": 0.99 } ] } ``` | Поле | Тип | Описание | |---|---|---| | `segment` | string | текст дорожки, по которому сделано предсказание (префикс снят) | | `translation_type` | string | один из 14 классов (см. docs/dataset.md) | | `type_confidence` | float | softmax-вероятность класса | | `studio_span` | string \| null | фрагмент текста, распознанный как имя автора | | `studio` | string \| null | каноническое имя автора по словарю алиасов; null — автора в тексте нет | | `studio_confidence` | float \| null | средняя вероятность токенов спана | | `is_18plus` | bool | дорожка помечена 18+ | | `age_confidence` | float | вероятность предсказанного класса 18+ | ## Как обрабатывается страница 1. HTML → текст (BeautifulSoup: `div.post_body` (rutracker) → `#tabs` (kinozal) → весь документ); 2. строки вида «Перевод/Озвучка/Озвучивание/Озвучено/Звук/Аудио N: …»; 3. разбиение многострочных дорожек: нумерация «1. … 2. …», разделители «+ ; /» перед словами типов, перечисление типов через запятую; 4. строки без признаков типа озвучки (например, чисто кодек-строки) не попадают в результат; 5. каждая дорожка — отдельное предсказание модели. ## Ограничения * `studio` — нормализация по словарю; неизвестные имена возвращаются как есть (спан), без канонизации; * если дорожка в тексте написана без какой-либо информации о типе, модель вернёт наиболее вероятный класс (обычно «неизвестно») — фильтрация таких строк уже сделана на этапе сегментации; * классы с единичными примерами в обучении (см. docs/dataset.md) предсказываются хуже — видно в confusion matrix.