- контракт с моделью переводится на адресацию файла номером строки списка, усечение промпта снимается, лимиты уходят в конфиг - раскладка показывает все файлы раздачи, покрытие плана блокирует авто только при непокрытом видеофайле
93 lines
9.3 KiB
Markdown
93 lines
9.3 KiB
Markdown
## Why
|
|
|
|
Раздача «Отчаянные домохозяйки» — один торрент на 8 сезонов, 180 файлов — распозналась
|
|
негодно: в план попало ровно 100 файлов, потому что промпт усекает список файлов жёсткой
|
|
константой `defaultMaxFiles = 100`. Остальные 80 файлов модель не видела, в интерфейсе они
|
|
не показаны никак, а причины ревью распухли до сорока строк «пропуск серий в сезоне N».
|
|
Порядок строк раскладки в UI — тот, в каком их вернула модель, то есть вперемешку по
|
|
сезонам.
|
|
|
|
Просто поднять лимит нельзя: каждый элемент плана обязан нести дословную копию пути
|
|
(~70 токенов на кириллице), 180 файлов дают ~15k выходных токенов при нашем же потолке
|
|
`defaultMaxTokens = 4000`. Обрыв генерации при этом неотличим от мусора — `finish_reason`
|
|
из ответа разбирается, но не проверяется, и обрыв уходит в три бессмысленных ретрая
|
|
с полным промптом. Вход тут не проблема (12–15k токенов промпта — ничто для современной
|
|
модели), проблема целиком на стороне ответа.
|
|
|
|
## What Changes
|
|
|
|
- **BREAKING (контракт с моделью, не с пользователем)**: элемент `files[]` в ответе LLM
|
|
адресует файл номером из напечатанного нами списка (`i`), а не дословной копией пути.
|
|
`src` заполняем сами резолвом индекса. Выход падает с ~85 до ~14 токенов на файл; путь,
|
|
которого нет в торренте, становится невыразимым. Старый формат с `src` принимается как
|
|
запасной, чтобы привычка модели не давала ретрая на пустом месте.
|
|
- Негодный элемент ответа (номер вне диапазона, повторная адресация файла, элемент без
|
|
номера и пути) отбрасывается поимённой причиной, а не роняет весь план: иначе одна
|
|
ошибка в одном из 180 элементов воспроизводит ровно тот отказ, против которого change и
|
|
затевается. Элемент, несущий и номер, и путь, резолвится по номеру, а расхождение между
|
|
ними становится причиной ревью — бесплатной сверкой против сдвига адресации.
|
|
- Жёсткое усечение списка файлов снимается: модели показываются все файлы раздачи.
|
|
`max_files` и `max_tokens` выводятся в `[recognition]` с дефолтами 500 и 8000 — сейчас
|
|
оба зашиты в код и на проде не крутятся.
|
|
- Повторная попытка перестаёт переприсылать список файлов: номера названы в первом
|
|
сообщении диалога, и цена неудачного распознавания больше не растёт вместе с числом
|
|
попыток.
|
|
- Порядок файлов, напечатанных в промпте, детерминирован и совпадает с порядком резолва
|
|
индексов — иначе повторное распознавание из ревью сдвинет привязку.
|
|
- Обрыв генерации (`finish_reason` = `length`) распознаётся как отдельная причина ухода
|
|
в review и не ретраится тем же промптом.
|
|
- В раскладке видны все файлы торрента: попавшие в план — с ролью и целью, не попавшие —
|
|
отдельной строкой. Молчаливый пропуск файла моделью перестаёт быть невидимым. Загрузки,
|
|
распознанные до этого изменения, списка файлов не имеют — и виджет говорит об этом
|
|
прямо, вместо того чтобы показать план как полный перечень.
|
|
- Строки раскладки упорядочены полностью — разложенные по (сезон, серия, путь), затем
|
|
файлы плана без цели, затем файлы вне плана, — а не по порядку ответа модели.
|
|
- Причины ревью по нумерации серий сворачиваются: перечисление недостающих серий по
|
|
сезону одной строкой и сводка покрытия плана вместо строки на каждый разрыв. Покрытие
|
|
показывается, когда покрыты не все файлы, но блокирует авто-раскладку только
|
|
непокрытый видеофайл: иначе опущенный моделью `.nfo` выключил бы авто-путь на типовых
|
|
раздачах. Отсюда же следствие для решения: `Reasons` перестают быть однородным
|
|
списком «причин не-авто» — в них появляются информационные строки, и решение
|
|
считается по блокирующим причинам, а не по длине списка.
|
|
|
|
Вне объёма: детерминированный разбор сезона/серии из имён файлов и сверка с ответом
|
|
модели — следующий change (этап B). Здесь модель по-прежнему единственный источник
|
|
разметки файлов.
|
|
|
|
## Capabilities
|
|
|
|
### New Capabilities
|
|
|
|
Нет.
|
|
|
|
### Modified Capabilities
|
|
|
|
- `recognition`: контракт ответа LLM (адресация файла индексом вместо дословного пути),
|
|
отказ от усечения списка файлов и вывод лимитов в конфиг, обрыв генерации как
|
|
отдельная причина review, форма причин по нумерации серий, решение auto/review
|
|
считается по блокирующим причинам (в `Reasons` появились информационные строки).
|
|
- `web-ui`: раскладка показывает все файлы раздачи, включая не попавшие в план, и
|
|
упорядочена по сезону и серии.
|
|
|
|
## Impact
|
|
|
|
- `internal/recognize`: `prompt.go` (нумерация и печать списка, схема в промпте,
|
|
correction-сообщение без повторной печати списка), `validate.go` (резолв индекса вместо
|
|
поиска пути, отбраковка негодных элементов, свёртка предупреждений, покрытие по
|
|
видеофайлам), `recognize.go` (упорядочивание входного списка в самом узле, лимиты,
|
|
обработка обрыва).
|
|
- `internal/llm`: `finish_reason` доводится до вызывающего в `Response`.
|
|
- `internal/config`: `[recognition].max_files`, `[recognition].max_tokens`;
|
|
`config.example.toml` и `docs/database.md` (настройки с числовым значением).
|
|
- `internal/httpapi/files.go` и `web/templates/partials/layout_widget.html`: сортировка,
|
|
файлы вне плана, колонка `#` (номер строки виджета обязан совпасть с номером адресации
|
|
либо исчезнуть), строка о недоступном списке файлов.
|
|
- Хранилище: миграция `0012` — колонка со списком файлов раздачи в таблице `recognition`,
|
|
и правка ER-схемы в `docs/database.md` (без неё краснеет шаг `canon` гейта).
|
|
- Совместимость: сохранённые планы в БД хранят `src` путями и не меняются. Записи,
|
|
созданные до миграции, списка файлов не имеют — виджет называет это явно. Уже
|
|
применённые раскладки не затрагиваются.
|
|
- Риск: ошибка модели в индексе становится тихой (валидный, но не тот файл). Смягчение —
|
|
требование уникальности индексов и сводка покрытия в причинах; перекрёстная проверка
|
|
разметки приходит в этапе B.
|