# Распознавание контента ## Задача По доступным сигналам определить: это фильм или сериал; каноническое название и год; для сериала — сезон и соответствие файлов сериям; при включённых базах — 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).