docker / build (push) Successful in 1m49s
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
115 lines
6.1 KiB
Markdown
115 lines
6.1 KiB
Markdown
# Инференс: 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`
|
||
взаимозаменяемы.
|
||
|
||
## Ссылка на раздачу и агрегат релиза
|
||
|
||
```bash
|
||
python -m src.predict --url https://rutracker.org/forum/viewtopic.php?t=123
|
||
python -m src.predict --url https://kinozal.tv/details.php?id=1 # kinozal без входа
|
||
python -m src.predict --url https://kinozal.tv/details.php?id=1 --cookie "uid=..; pass=.." # если раздача закрыта для гостей
|
||
```
|
||
|
||
Поддерживаются только rutracker / kinozal / nnm-club (allowlist доменов,
|
||
редиректы за его пределы запрещены). Для `--html`, `--file` и `--url` ответ —
|
||
агрегат релиза: к `tracks` добавлены
|
||
|
||
| Поле | Описание |
|
||
|---|---|
|
||
| `studios` | уникальные `{studio, translation_type, is_18plus}` |
|
||
| `translation_types` | отсортированный список типов релиза |
|
||
| `is_18plus` | `true`, если 18+ хотя бы у одной дорожки |
|
||
| `title` | заголовок раздачи (если найден в HTML) |
|
||
| `tracker` | только для `--url` |
|
||
|
||
Дорожки дедуплицируются по (тип, студия). Студии из заголовка раздачи вида
|
||
`ПМ (LostFilm)`, которых нет в описании, добавляются с `source: "title"`
|
||
(у остальных `source: "page"`). `--text` по-прежнему возвращает только `tracks`.
|
||
|
||
## 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-контракт
|
||
|
||
Полный справочник значений (15 классов `translation_type`, `lang`, `role`, `audio`, агрегат релиза, принцип работы) — в [api-reference.md](api-reference.md); ниже краткий пример.
|
||
|
||
```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 | один из 15 классов (см. 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.
|