Files
jellybit/docs/specs/recognition.md
T

93 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Распознавание контента
## Задача
По доступным сигналам определить: это фильм или сериал; каноническое
название и год; для сериала — сезон и соответствие файлов сериям; при
включённых базах — 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).