93 lines
5.6 KiB
Markdown
93 lines
5.6 KiB
Markdown
# Распознавание контента
|
||
|
||
## Задача
|
||
|
||
По доступным сигналам определить: это фильм или сериал; каноническое
|
||
название и год; для сериала — сезон и соответствие файлов сериям; при
|
||
включённых базах — provider-id. На выходе — план раскладки и оценка
|
||
уверенности.
|
||
|
||
## Сигналы
|
||
|
||
- Имя торрента и структура каталогов.
|
||
- Список файлов с размерами и расширениями.
|
||
- Текстовый контекст от человека.
|
||
- Распарсенное сообщение торрент-бота (если пришло через Telegram):
|
||
название с годом, качество, переводы, magnet — см. пример в
|
||
[BRIEF.md](../../BRIEF.md).
|
||
|
||
## Конвейер
|
||
|
||
1. **Пред-парс** имени релиза дешёвым парсером (`go-ptn`): черновые
|
||
название/год/сезон/серия и качество. Грубо, но бесплатно.
|
||
2. **LLM** (через провайдер-абстракцию, см. «Провайдер LLM»): получает
|
||
все сигналы и пред-парс, возвращает структурированный план в нашей
|
||
схеме. Хорошо справляется с русскими релиз-именами, чего не умеет
|
||
парсер.
|
||
3. **Сверка с базой** (опц., если включена TMDB/TVDB): подтверждаем
|
||
название+год, берём официальный id и каноническое имя.
|
||
4. **Оценка уверенности** и решение: авто-раскладка или ревью.
|
||
|
||
## Структура ответа LLM (черновик)
|
||
|
||
```
|
||
type movie | series
|
||
title каноническое название
|
||
original_title оригинальное название (если есть)
|
||
year год
|
||
season номер сезона (для сериала)
|
||
provider_hint подсказка для поиска в базе
|
||
files[] { src, role: main|episode|subtitle|extra|sample,
|
||
season?, episode? }
|
||
confidence 0..1 — самооценка модели по полям
|
||
notes пояснения, неоднозначности
|
||
```
|
||
|
||
## Провайдер LLM
|
||
|
||
Доступ к LLM — за интерфейсом; конкретная реализация выбирается полем
|
||
`[llm].type` в конфиге (дискриминатор). Это позволяет подключать
|
||
локальные модели и сторонние (в т.ч. китайские) эндпоинты — ради экономии
|
||
и независимости от одного вендора.
|
||
|
||
- Первый и пока единственный тип — **`openai-compat`**: OpenAI-совместимый
|
||
Chat Completions API (`base_url` + `api_key` + `model`). Под него
|
||
подходят локальные серверы (LM Studio, llama.cpp, Ollama) и облачные
|
||
совместимые провайдеры (DeepSeek, Qwen и др.).
|
||
- Структурированный вывод: запрашиваем JSON по нашей схеме
|
||
(`response_format` со схемой там, где поддерживается; иначе json-режим
|
||
или tool-call), **валидируем в Go** и ретраим при несоответствии —
|
||
серверы различаются по поддержке строгих схем.
|
||
- Новые типы (напр. нативный `anthropic`) добавляются, не трогая
|
||
`recognize`.
|
||
|
||
## Модель уверенности
|
||
|
||
Авто-раскладка только если выполнено всё:
|
||
|
||
1. **Самооценка LLM** ≥ порога (`recognition.auto_confidence_threshold`).
|
||
2. **Совпадение с базой** (если включена) — единственный сильный матч по
|
||
названию+году.
|
||
3. **Структурная валидация** проходит без предупреждений:
|
||
- фильм: ровно один основной видеофайл (семплы/экстра отброшены);
|
||
- сериал: число серий бьётся с базой (если есть), нумерация S·E
|
||
консистентна, без пропусков и дублей.
|
||
|
||
Иначе план уходит в **review** (сценарии — [review-ux.md](review-ux.md)).
|
||
На экране подтверждения всегда видно, *почему* не авто — это страховка на
|
||
дорогих файлах.
|
||
|
||
## Что делаем с краёв
|
||
|
||
- Семплы и «экстра» отбрасываем (эвристики по размеру/имени + LLM).
|
||
- Внешние субтитры (`.srt`, `.ass`) привязываем к видео и именуем по
|
||
Jellyfin (`*.ru.srt`).
|
||
- Сезон-паки разбираем по сериям; аниме с абсолютной нумерацией —
|
||
отдельный крайний случай, см. [drafts/ideas.md](../drafts/ideas.md).
|
||
|
||
## На будущее
|
||
|
||
`go-ptn` слабее питоновского `guessit`. Если точности пред-парса не
|
||
хватит — завернуть `guessit` лёгким сервисом-спутником (один файл рядом
|
||
с бинарём). См. [drafts/ideas.md](../drafts/ideas.md).
|