Добавил еще идеи в todo
This commit is contained in:
+172
@@ -68,6 +68,57 @@
|
|||||||
[architecture.md](specs/architecture.md) → «Раскладка файлов» (undo,
|
[architecture.md](specs/architecture.md) → «Раскладка файлов» (undo,
|
||||||
инвариант источника), [workflow.md](specs/workflow.md) (`done → reverted`).
|
инвариант источника), [workflow.md](specs/workflow.md) (`done → reverted`).
|
||||||
|
|
||||||
|
### Наблюдаемость: метрики и учёт стоимости LLM
|
||||||
|
|
||||||
|
Сейчас единственное окно в систему — `slog`. Нет быстрых ответов на
|
||||||
|
вопросы «сколько задач висит в review», «сколько токенов и денег съело
|
||||||
|
распознавание», «какова медиана времени ingest → done». Нужны метрики:
|
||||||
|
эндпоинт `/metrics` (Prometheus-формат) со счётчиками загрузок по
|
||||||
|
состояниям, длительностями стадий и расходом LLM (токены/стоимость на
|
||||||
|
задачу).
|
||||||
|
|
||||||
|
**Расход LLM уже снимается с провода** — `llm.openai` парсит `usage`
|
||||||
|
(prompt/completion/total tokens и `cost`, который отдаёт шлюз) в
|
||||||
|
`llm.Response.Usage` и пишет в лог. Не хватает только **персистентности и
|
||||||
|
отображения**: сохранять `usage` у попытки распознавания (`recognition`) и
|
||||||
|
показывать в карточке загрузки + агрегатом в `/metrics`. Где провайдер не
|
||||||
|
шлёт `cost` — считать из токенов по таблице «модель → цена» в конфиге.
|
||||||
|
|
||||||
|
Отдельный LLM-прокси (LiteLLM и т.п.) для этого **не нужен** и противоречит
|
||||||
|
принципам «один бинарь» / «минимум компонентов»: подсчёт токенов уже в коде,
|
||||||
|
а роль мульти-модельного шлюза играет используемый OpenAI-совместимый
|
||||||
|
эндпоинт (он и возвращает `cost`); разные модели подключаются сменой
|
||||||
|
`[llm].model` или новым типом провайдера за интерфейсом `llm.Provider`.
|
||||||
|
|
||||||
|
Связано: [architecture.md](specs/architecture.md) → «Логирование»,
|
||||||
|
[recognition.md](specs/recognition.md) (провайдер LLM, `[llm].type`),
|
||||||
|
пакеты `worker`, `llm`, `httpapi`.
|
||||||
|
|
||||||
|
### Ретеншн и очистка БД
|
||||||
|
|
||||||
|
Терминальные задачи (`done`/`cancelled`/`failed`/`reverted`), их попытки
|
||||||
|
`recognition` с сырыми ответами LLM и `metadata_candidate` копятся вечно —
|
||||||
|
со временем БД и список загрузок распухают и становятся нечитаемыми. Нужна
|
||||||
|
авточистка старше N дней (с настройкой в `[storage]` или `[worker]`) и/или
|
||||||
|
ручное удаление. Маленькая задача, но без неё интерфейс деградирует по мере
|
||||||
|
эксплуатации.
|
||||||
|
|
||||||
|
Связано: [architecture.md](specs/architecture.md) → «Хранилище» (таблицы
|
||||||
|
`download`/`recognition`/`metadata_candidate`/`file_link`), пакет `store`.
|
||||||
|
|
||||||
|
### Eval-харнес распознавания (корпус кейсов + метрика точности)
|
||||||
|
|
||||||
|
Распознавание — ядро продукта, но смена модели или правка промпта сейчас
|
||||||
|
вслепую: регрессий не видно. Нужен корпус размеченных кейсов (русские
|
||||||
|
релизы, аниме, сезон-паки, репаки, спецвыпуски) и прогон распознавания по
|
||||||
|
нему с метрикой точности (тип/название/год/нумерация). Тогда можно
|
||||||
|
сравнивать LLM-провайдеры и версии промпта по числам, а не на ощупь.
|
||||||
|
Прогон — отдельной командой (`jellybit eval` или тестом), на фикстурах, без
|
||||||
|
реального qBittorrent.
|
||||||
|
|
||||||
|
Связано: [recognition.md](specs/recognition.md) (конвейер, модель
|
||||||
|
уверенности), пакет `recognize`.
|
||||||
|
|
||||||
## Средний
|
## Средний
|
||||||
|
|
||||||
### Машина состояний на go-библиотеке
|
### Машина состояний на go-библиотеке
|
||||||
@@ -94,6 +145,33 @@
|
|||||||
веб = точные правки), [architecture.md](specs/architecture.md) →
|
веб = точные правки), [architecture.md](specs/architecture.md) →
|
||||||
«Транспорты».
|
«Транспорты».
|
||||||
|
|
||||||
|
### Раздачи с докачиванием (слияние при повторном добавлении)
|
||||||
|
|
||||||
|
Свежий сериал часто раздают по мере выхода: торрент содержит 5 эпизодов из
|
||||||
|
10. Позже его перезаливают целиком (или добавляют недостающие серии), и
|
||||||
|
пользователь повторно добавляет тот же торрент. Нужно распознать, что это
|
||||||
|
**та же** раздача/сезон, и повторить раскладку с **слиянием**: доложить
|
||||||
|
недостающие хардлинки, не дублируя уже разложенное и не перезаписывая
|
||||||
|
существующее (инвариант «существующее не трогаем»). Перекликается с
|
||||||
|
«Проблемой второго сезона», но здесь доливаются эпизоды внутри одного
|
||||||
|
сезона, а не новый сезон. Нужно продумать: как опознать повторное
|
||||||
|
добавление (хеш торрента / провайдер-id + сезон), как сверять состав файлов
|
||||||
|
и доливать только новые.
|
||||||
|
|
||||||
|
Связано: [«Проблема второго сезона»](#проблема-второго-сезона),
|
||||||
|
[jellyfin-layout.md](specs/jellyfin-layout.md) (раскладка, идемпотентность),
|
||||||
|
[workflow.md](specs/workflow.md) (повторный прогон загрузки).
|
||||||
|
|
||||||
|
### Улучшения UI клиентов: показывать матч с записью метабазы
|
||||||
|
|
||||||
|
Во всех транспортах (веб, Telegram) показывать, **с какой именно записью**
|
||||||
|
метабазы (TMDB/TVDB) сматчилась загрузка: название, год, провайдер-id,
|
||||||
|
ссылку. Сейчас результат распознавания непрозрачен — пользователь не видит,
|
||||||
|
к чему привязались, и не может быстро поймать ошибочный матч.
|
||||||
|
|
||||||
|
Связано: [review-ux.md](specs/review-ux.md), [recognition.md](specs/recognition.md)
|
||||||
|
(матч в базе), [architecture.md](specs/architecture.md) → «Транспорты».
|
||||||
|
|
||||||
### Добавление торрентов файлом/ссылкой — «единое окно»
|
### Добавление торрентов файлом/ссылкой — «единое окно»
|
||||||
|
|
||||||
Поддержать источники помимо magnet: `.torrent`-файл и URL (отдаём их в
|
Поддержать источники помимо magnet: `.torrent`-файл и URL (отдаём их в
|
||||||
@@ -106,6 +184,61 @@ qBittorrent, без исходящих запросов на пользоват
|
|||||||
(`source_type = magnet|torrent|url` уже в схеме), пакет `ingest` (сейчас
|
(`source_type = magnet|torrent|url` уже в схеме), пакет `ingest` (сейчас
|
||||||
поддержан только magnet).
|
поддержан только magnet).
|
||||||
|
|
||||||
|
### Бэкап SQLite
|
||||||
|
|
||||||
|
`architecture.md` требует «бекапить data-том», но *как* — не описано. Без
|
||||||
|
понятной стратегии сбой или редеплой стирают всё in-flight состояние.
|
||||||
|
Зафиксировать решение и реализовать: периодический `VACUUM INTO` в
|
||||||
|
`/data/backups` по расписанию (с ротацией) либо потоковая репликация
|
||||||
|
(litestream). Лучше сделать, пока БД маленькая.
|
||||||
|
|
||||||
|
Связано: [architecture.md](specs/architecture.md) → «Деплой» (data-том,
|
||||||
|
«бекапить-и-не-терять»), пакет `store`.
|
||||||
|
|
||||||
|
### Версии/качество одного тайтла (репаки, апгрейд 1080p → 2160p)
|
||||||
|
|
||||||
|
Фильм уже разложен, позже добавили раздачу лучшего качества — сейчас это
|
||||||
|
просто новая задача, упирающаяся в «коллизию цели → review», без понятия
|
||||||
|
«это та же вещь, заменить версию». Нужно осознанно обработать апгрейд
|
||||||
|
качества: распознать тот же тайтл, предложить замену существующей раскладки
|
||||||
|
либо сосуществование версий (Jellyfin поддерживает несколько версий одного
|
||||||
|
фильма). Близко к «докачиванию», но про качество, а не про эпизоды.
|
||||||
|
|
||||||
|
Связано: [«Раздачи с докачиванием»](#раздачи-с-докачиванием-слияние-при-повторном-добавлении),
|
||||||
|
[jellyfin-layout.md](specs/jellyfin-layout.md) (never-overwrite, коллизия),
|
||||||
|
[architecture.md](specs/architecture.md) → «Идентификация торрента»
|
||||||
|
(репаки = разные infohash → разные задачи).
|
||||||
|
|
||||||
|
### Глубокий healthcheck и статус зависимостей
|
||||||
|
|
||||||
|
`/healthz` проверяет только сам сервис. Если qBittorrent, LLM или метабаза
|
||||||
|
недоступны — узнаёшь лишь по застрявшим задачам. Нужна readiness-проверка
|
||||||
|
ключевых зависимостей и отражение их состояния в UI (бейдж «qBittorrent
|
||||||
|
недоступен»), чтобы причина простоя была видна сразу.
|
||||||
|
|
||||||
|
Связано: [architecture.md](specs/architecture.md) → «Деплой» (healthcheck),
|
||||||
|
пакеты `qbt`, `llm`, `metadata`, `httpapi`.
|
||||||
|
|
||||||
|
### Обучение на правках человека (few-shot из прошлых ревью)
|
||||||
|
|
||||||
|
Когда человек поправил матч, тип или нумерацию — сохранять это как пример и
|
||||||
|
подмешивать похожие в будущие промпты. Системно повышает точность на «твоих»
|
||||||
|
трекерах и форматах имён без смены модели. Развитие идеи многоступенчатой
|
||||||
|
верификации, но дешевле: учимся на уже собранных `hint`/`override`.
|
||||||
|
|
||||||
|
Связано: [recognition.md](specs/recognition.md) (конвейер, промпт),
|
||||||
|
[«Многоступенчатая верификация»](#многоступенчатая-верификация-привязки-тема-для-размышления),
|
||||||
|
[architecture.md](specs/architecture.md) → «Хранилище» (`hint`, `override`).
|
||||||
|
|
||||||
|
### Список загрузок: фильтр, поиск, пагинация
|
||||||
|
|
||||||
|
Прямое следствие роста БД (см. «Ретеншн»): плоский список загрузок со
|
||||||
|
временем становится непригоден. Нужны фильтр по состоянию, поиск по
|
||||||
|
названию и пагинация. Естественно ложится на экран расширенной информации.
|
||||||
|
|
||||||
|
Связано: [«Расширенная информация о загрузке в web-UI»](#расширенная-информация-о-загрузке-в-web-ui),
|
||||||
|
пакет `httpapi`.
|
||||||
|
|
||||||
## Низкий
|
## Низкий
|
||||||
|
|
||||||
### Многоступенчатая верификация привязки (тема для размышления)
|
### Многоступенчатая верификация привязки (тема для размышления)
|
||||||
@@ -119,6 +252,45 @@ qBittorrent, без исходящих запросов на пользоват
|
|||||||
Связано: [recognition.md](specs/recognition.md) (конвейер и модель
|
Связано: [recognition.md](specs/recognition.md) (конвейер и модель
|
||||||
уверенности).
|
уверенности).
|
||||||
|
|
||||||
|
### Расширенная информация о загрузке в web-UI
|
||||||
|
|
||||||
|
Экран просмотра деталей одной загрузки: исходный контекст и magnet, лог
|
||||||
|
переходов состояний, распознанные данные и матч в метабазе (см. «показывать
|
||||||
|
матч»), целевые пути и созданные хардлинки. Помогает разбираться, когда
|
||||||
|
что-то пошло не так, без чтения логов сервера.
|
||||||
|
|
||||||
|
Связано: [review-ux.md](specs/review-ux.md), пакет `httpapi`.
|
||||||
|
|
||||||
|
### Выбор из нескольких находок метабазы в Telegram
|
||||||
|
|
||||||
|
Когда распознавание даёт несколько подходящих кандидатов в метабазе,
|
||||||
|
предлагать их в Telegram списком (кнопки) для ручного выбора, а не молча
|
||||||
|
брать первый/лучший. Веб остаётся точкой точных правок, бот — быстрый выбор
|
||||||
|
из готового короткого списка.
|
||||||
|
|
||||||
|
Связано: [review-ux.md](specs/review-ux.md) (боты — быстрые действия, веб —
|
||||||
|
точные правки), [recognition.md](specs/recognition.md) (кандидаты матча).
|
||||||
|
|
||||||
|
### Проверка свободного места перед copy-fallback
|
||||||
|
|
||||||
|
Когда хардлинк невозможен (`EXDEV`/`ENOTSUP`/…), `layout` копирует файл,
|
||||||
|
дублируя место на диске. На забитом диске это упрётся в полку посреди
|
||||||
|
раскладки. Перед копированием проверять доступное место и при нехватке
|
||||||
|
внятно уходить в `failed` с понятной причиной, а не падать на полпути.
|
||||||
|
|
||||||
|
Связано: [architecture.md](specs/architecture.md) → «Раскладка файлов»
|
||||||
|
(фолбэк-копирование), пакет `layout`.
|
||||||
|
|
||||||
|
### Кэш метабаз (и опционально LLM)
|
||||||
|
|
||||||
|
Повторные и ретраящиеся прогоны распознавания бьют TMDB/TVDB/TVMaze одним и
|
||||||
|
тем же запросом. Кэш ответов с TTL экономит лимиты API и ускоряет «Распознать
|
||||||
|
заново»/«Уточнить». При желании — кэш ответов LLM по хешу входа (но он менее
|
||||||
|
полезен, т.к. вход меняется подсказками).
|
||||||
|
|
||||||
|
Связано: [recognition.md](specs/recognition.md) (сверка с базой), пакеты
|
||||||
|
`metadata`, `llm`.
|
||||||
|
|
||||||
### Современный Web-UI как PWA
|
### Современный Web-UI как PWA
|
||||||
|
|
||||||
Переделать веб-интерфейс в современное PWA-приложение (устанавливаемое,
|
Переделать веб-интерфейс в современное PWA-приложение (устанавливаемое,
|
||||||
|
|||||||
Reference in New Issue
Block a user