Поиск по нескольким названиям при сверке с базой (recognition)
Сверка с метабазой промахивалась на иностранных фильмах с русским релиз-именем (кейс «Тёмный рыцарь»): поиск шёл по одной строке provider_hint||title и игнорировал original_title, а базы индексированы прежде всего по оригинальным названиям. - matchMetadata ищет по ключам original_title → title → provider_hint с ранним стопом на первом единичном сильном матче; пустые и нормализованно-дублирующие ключи пропускаются, кандидаты для review копятся из всех заходов. - Промпт требует всегда заполнять title и original_title (дублировать при отсутствии оригинала / российском контенте; при неуверенности дублировать, не выдумывать). Разбор остаётся мягким к пустому original_title. - TMDB-поиск передаёт language (по умолчанию ru-RU, настраивается [metadata.tmdb].language); original_title не зависит от локали. - Нормализация названий сводит ё→е. Инварианты не ослаблены: авто только при подтверждённом единичном матче + структурной валидации + согласованности сигналов. Capability recognition впервые перенесена в OpenSpec; change архивирован. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+85
@@ -0,0 +1,85 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Сверка с базой по нескольким названиям
|
||||
|
||||
При сверке плана с включёнными базами метаданных система SHALL искать по
|
||||
нескольким названиям в порядке убывания силы ключа: сначала по
|
||||
`original_title`, затем по локализованному `title`, затем по `provider_hint`.
|
||||
Поиск SHALL останавливаться, как только очередной запрос дал единичный
|
||||
сильный матч (ровно один кандидат с совпадением названия и года). Запрос с
|
||||
названием, нормализованно совпадающим с уже выполненным, система SHALL
|
||||
пропускать, чтобы не обращаться к базе повторно с тем же ключом.
|
||||
|
||||
Кандидаты для ручного выбора в review система SHALL собирать из всех
|
||||
выполненных заходов с дедупликацией по `provider:id` и общим потолком.
|
||||
|
||||
#### Scenario: Иностранный фильм находится по оригинальному названию
|
||||
|
||||
- **GIVEN** план с `title` «Тёмный рыцарь», `original_title` «The Dark Knight», год 2008
|
||||
- **WHEN** выполняется сверка с базой
|
||||
- **THEN** первый запрос идёт по «The Dark Knight»
|
||||
- **AND** при единичном сильном матче дальнейшие запросы (по `title`, `provider_hint`) не выполняются
|
||||
|
||||
#### Scenario: Фолбэк на локализованное название
|
||||
|
||||
- **GIVEN** план, для которого запрос по `original_title` не дал единичного сильного матча
|
||||
- **WHEN** продолжается сверка
|
||||
- **THEN** выполняется запрос по локализованному `title`
|
||||
- **AND** при отсутствии матча и там — запрос по `provider_hint`
|
||||
|
||||
#### Scenario: Дублирующий запрос пропускается
|
||||
|
||||
- **GIVEN** план, у которого `original_title` нормализованно совпадает с `title`
|
||||
- **WHEN** выполняется сверка
|
||||
- **THEN** база запрашивается этим названием один раз, повторный заход по `title` не делается
|
||||
|
||||
### Requirement: Контракт LLM на оригинальное и локализованное названия
|
||||
|
||||
Промпт распознавания SHALL требовать от модели всегда заполнять и `title`, и
|
||||
`original_title`. Если отдельного оригинального названия нет или контент
|
||||
российского происхождения, модель SHALL дублировать `title` в
|
||||
`original_title`. При неуверенности в оригинальном названии модель SHALL
|
||||
дублировать `title`, а не выдумывать название (защита от ложного авто-матча).
|
||||
|
||||
Разбор ответа SHALL оставаться устойчивым к пустому `original_title`: пустое
|
||||
значение не отбраковывается и не вызывает correction-ретрай; сверка
|
||||
gracefully использует доступные названия.
|
||||
|
||||
#### Scenario: Российский фильм — дублирование
|
||||
|
||||
- **GIVEN** раздача российского фильма без отдельного оригинального названия
|
||||
- **WHEN** модель возвращает план
|
||||
- **THEN** `title` и `original_title` заполнены одинаковым каноническим названием
|
||||
|
||||
#### Scenario: Пустой original_title не ломает разбор
|
||||
|
||||
- **GIVEN** ответ модели с пустым `original_title`
|
||||
- **WHEN** план разбирается
|
||||
- **THEN** разбор успешен без correction-ретрая
|
||||
- **AND** сверка использует `title` (и `provider_hint`)
|
||||
|
||||
### Requirement: Локаль запроса к TMDB
|
||||
|
||||
Запрос поиска к TMDB SHALL передавать параметр `language`, по умолчанию
|
||||
`ru-RU`, со значением, настраиваемым конфигом `[metadata.tmdb].language`.
|
||||
Это влияет только на локализованное поле `Title`/`Name`; поле
|
||||
`original_title`/`original_name` остаётся на языке оригинала, поэтому
|
||||
оригинальная сторона сравнения не затрагивается.
|
||||
|
||||
#### Scenario: Локализованный заголовок приходит по-русски
|
||||
|
||||
- **GIVEN** TMDB включён, `language` не задан в конфиге
|
||||
- **WHEN** выполняется поиск фильма с русской локализацией
|
||||
- **THEN** запрос содержит `language=ru-RU`
|
||||
- **AND** в кандидате `Title` приходит на русском, а `OriginalTitle` — на языке оригинала
|
||||
|
||||
### Requirement: Нормализация названий при сравнении
|
||||
|
||||
Нормализация названий для гейта сильного матча SHALL сводить букву `ё` к `е`,
|
||||
чтобы написания, различающиеся только `ё`/`е`, считались одним названием.
|
||||
|
||||
#### Scenario: «Тёмный» и «Темный» совпадают
|
||||
|
||||
- **GIVEN** план с названием «Тёмный рыцарь» и кандидат базы «Темный рыцарь»
|
||||
- **WHEN** сравниваются нормализованные названия
|
||||
- **THEN** они считаются совпадающими
|
||||
Reference in New Issue
Block a user