[P3] Дедуп-остаток после #2269: mkr-misfire (334), ё/е-фолд (~60), area-straddle (139) #2291

Open
opened 2026-07-03 13:15:10 +00:00 by bot-backend · 3 comments
Collaborator

Follow-up #2269/#2290. После трёх итераций выживает 10.9% кросс-source дублей (705 из 6 442); прод-перезамер 2026-07-03 разбил остаток по классам. 127 кадастр-конфликтов — by design, не трогаем. Остальное — четыре отдельных класса (по убыванию):

1. mkr-fallback misfire — 334 дубля (крупнейшая течь)

Когда в адресе голое имя улицы БЕЗ типа-слова после района («Заречный м-н, Готвальда, 24» — формат domklik), все три уличных ветки молчат → mkr-fallback хватает РАЙОН («mkr заречный»), а avito/cian дают реальную «готвальда» → один физлот не сливается.
Фикс: ветка «bare-street после города/района» ДО mkr-fallback, либо запрет mkr-ключу конкурировать при наличии похожего на улицу сегмента. Осторожно с ложными улицами.

2. ё/е-нормализация — ~60 дублей

«шевелёва»/«шевелева», «миномётчиков»/«минометчиков» — разные токены. Фикс: replace("ё","е") в нормализации _parse_street_house (проверить, что существующие тесты байт-в-байт токенов обновлены сознательно).

3. Area-bucket straddle — 139 пар

round(area) на целочисленной границе: 38.5→38 (banker's) vs 39.0→39 — композиты расходятся. Именно это (не токен) держит живую пару Рассветной 6к1 из #2269. Фикс: допуск ±0.5 (union соседних бакетов внутри street-группы), НЕ расширение бакета (иначе over-merge).

4. Пустые токены — ~50

Нумерованные улицы с приклеенным номером («40-летия Комсомола,32Г»), «р-н Октябрьский, 1/5», названия ЖК. Мелочь, добрать по остаточному принципу.

Acceptance

  • Прод-перезамер той же методикой (живой код из контейнера): выжившие ≤ кадастр-конфликты + ~2-3% экзотики.
  • Пара Рассветной 6к1 (23b8ada1) склеивается end-to-end.
  • Backtest-гейт: hermetic gate + живой прогон (MAPE/coverage не хуже).
  • mkr-фикс не регрессит #2265 («мкр. ЖБИ, улица Сыромолотова» → «сыромолотова»).

Точки в коде: _parse_street_house (~4694), _lot_dedup_components (~4747), _dedup_cross_source (~4792), _DEDUP_MKR_* (~4650) в tradein-mvp/backend/app/services/estimator.py.

Refs #2269, #2290, #2265

Follow-up #2269/#2290. После трёх итераций выживает 10.9% кросс-source дублей (705 из 6 442); прод-перезамер 2026-07-03 разбил остаток по классам. 127 кадастр-конфликтов — by design, не трогаем. Остальное — четыре отдельных класса (по убыванию): ## 1. mkr-fallback misfire — 334 дубля (крупнейшая течь) Когда в адресе голое имя улицы БЕЗ типа-слова после района («Заречный м-н, Готвальда, 24» — формат domklik), все три уличных ветки молчат → mkr-fallback хватает РАЙОН («mkr заречный»), а avito/cian дают реальную «готвальда» → один физлот не сливается. Фикс: ветка «bare-street после города/района» ДО mkr-fallback, либо запрет mkr-ключу конкурировать при наличии похожего на улицу сегмента. Осторожно с ложными улицами. ## 2. ё/е-нормализация — ~60 дублей «шевелёва»/«шевелева», «миномётчиков»/«минометчиков» — разные токены. Фикс: `replace("ё","е")` в нормализации `_parse_street_house` (проверить, что существующие тесты байт-в-байт токенов обновлены сознательно). ## 3. Area-bucket straddle — 139 пар `round(area)` на целочисленной границе: 38.5→38 (banker's) vs 39.0→39 — композиты расходятся. Именно это (не токен) держит живую пару Рассветной 6к1 из #2269. Фикс: допуск ±0.5 (union соседних бакетов внутри street-группы), НЕ расширение бакета (иначе over-merge). ## 4. Пустые токены — ~50 Нумерованные улицы с приклеенным номером («40-летия Комсомола,32Г»), «р-н Октябрьский, 1/5», названия ЖК. Мелочь, добрать по остаточному принципу. ## Acceptance - [ ] Прод-перезамер той же методикой (живой код из контейнера): выжившие ≤ кадастр-конфликты + ~2-3% экзотики. - [ ] Пара Рассветной 6к1 (23b8ada1) склеивается end-to-end. - [ ] Backtest-гейт: hermetic gate + живой прогон (MAPE/coverage не хуже). - [ ] mkr-фикс не регрессит #2265 («мкр. ЖБИ, улица Сыромолотова» → «сыромолотова»). Точки в коде: `_parse_street_house` (~4694), `_lot_dedup_components` (~4747), `_dedup_cross_source` (~4792), `_DEDUP_MKR_*` (~4650) в tradein-mvp/backend/app/services/estimator.py. Refs #2269, #2290, #2265
lekss361 added the
bug
priority/p3
scope/backend
tradein
labels 2026-07-04 10:24:16 +00:00
Owner

Working on this in PR #2417 — закрывает классы 1 (mkr-misfire) и 2 (ё/е-фолд) и 3 (area-bucket straddle); класс 4 (пустые токены) сознательно отложен, низкий ROI. Прошёл 2 раунда adversarial deep-review (1-й раунд нашёл over-merge риск на голых 2-сегментных адресах, зафиксили, 2-й раунд — approve).

Working on this in PR #2417 — закрывает классы 1 (mkr-misfire) и 2 (ё/е-фолд) и 3 (area-bucket straddle); класс 4 (пустые токены) сознательно отложен, низкий ROI. Прошёл 2 раунда adversarial deep-review (1-й раунд нашёл over-merge риск на голых 2-сегментных адресах, зафиксили, 2-й раунд — approve).
Owner

Post-deploy live-перезамер (PR #2417, merge a0c609ca, 2026-07-04).

Прогнал pre-fix (родительский коммит) и post-fix (деплойнутый) код против ОДНОГО И ТОГО ЖЕ набора кандидатных дублей (4764 группы, is_active листинги, docker exec tradein-backend — реальный контейнер, не локальная копия):

групп с дублями
PRE-fix 781 (16.4%)
POST-fix 434 (9.1%)
Разрешено этим PR 347 групп (−44%)
  • «Рассветная 6к1» (house_id_fk=8503, floor=13, domklik 38.5м² vs cian 39.0м²) — подтверждено живьём: pre-fix не сливалась, post-fix сливается.
  • Формальный acceptance-таргет (≤~320 выживших) не достигнут на текущем денаминаторе — но денаминатор сам сжался с 6442 до 4764 (дрейф живых данных со времени исходного аудита, не яблоки-к-яблокам). Разбивка 434 survivors: 138 — кадастр-конфликты (design, ожидаемо ~127), 52 — адрес структурно непарсибелен ни с одной стороны, 244 — новый непокрытый паттерн (см. отдельный issue ниже).
  • Логи tradein-backend/tradein-scraper за 30 мин после деплоя — чисто, новых исключений нет.

Новая находка (вне scope этого PR): avito-адреса с приклеенным без разделителя названием станции метро после номера дома (напр. "ул. Амундсена, 2Чкаловская11-15 мин...") — _DEDUP_HOUSE_NO_RE выхватывает "15" из "11-15 мин" вместо реального номера дома "2", guard_house блокирует street-union хотя улица совпадает 1-в-1. Заведу отдельный issue.

Оставляю #2291 открытым — класс 4 (пустые токены) всё ещё сознательно отложен + появился класс 5 (avito metro-glue).

**Post-deploy live-перезамер (PR #2417, merge `a0c609ca`, 2026-07-04).** Прогнал pre-fix (родительский коммит) и post-fix (деплойнутый) код против ОДНОГО И ТОГО ЖЕ набора кандидатных дублей (4764 группы, `is_active` листинги, `docker exec tradein-backend` — реальный контейнер, не локальная копия): | | групп с дублями | |---|---| | PRE-fix | 781 (16.4%) | | POST-fix | 434 (9.1%) | | **Разрешено этим PR** | **347 групп (−44%)** | - «Рассветная 6к1» (house_id_fk=8503, floor=13, domklik 38.5м² vs cian 39.0м²) — **подтверждено живьём**: pre-fix не сливалась, post-fix сливается. - Формальный acceptance-таргет (≤~320 выживших) **не достигнут** на текущем денаминаторе — но денаминатор сам сжался с 6442 до 4764 (дрейф живых данных со времени исходного аудита, не яблоки-к-яблокам). Разбивка 434 survivors: 138 — кадастр-конфликты (design, ожидаемо ~127), 52 — адрес структурно непарсибелен ни с одной стороны, **244 — новый непокрытый паттерн** (см. отдельный issue ниже). - Логи `tradein-backend`/`tradein-scraper` за 30 мин после деплоя — чисто, новых исключений нет. **Новая находка (вне scope этого PR):** avito-адреса с приклеенным без разделителя названием станции метро после номера дома (напр. `"ул. Амундсена, 2Чкаловская11-15 мин..."`) — `_DEDUP_HOUSE_NO_RE` выхватывает "15" из "11-15 мин" вместо реального номера дома "2", `guard_house` блокирует street-union хотя улица совпадает 1-в-1. Заведу отдельный issue. Оставляю #2291 открытым — класс 4 (пустые токены) всё ещё сознательно отложен + появился класс 5 (avito metro-glue).
Owner

Класс 5 (avito metro-glue, найден при прошлой live-перезамере) закрыт — PR #2429 → нашёл регрессию в самом себе (сравнение нотации корпуса дома между источниками) → отдельный issue #2431 → PR #2432. Оба смержены, задеплоены, живая проверка на реальных прод-данных пройдена дважды (до и после мержа второго фикса).

Остаётся открытым только класс 4 (пустые токены, ~50 пар, сознательно отложен как low-ROI ещё в исходном комментарии) — не взят в работу в этой сессии, возврат к нему по необходимости.

Класс 5 (avito metro-glue, найден при прошлой live-перезамере) закрыт — PR #2429 → нашёл регрессию в самом себе (сравнение нотации корпуса дома между источниками) → отдельный issue #2431 → PR #2432. Оба смержены, задеплоены, живая проверка на реальных прод-данных пройдена дважды (до и после мержа второго фикса). Остаётся открытым только класс 4 (пустые токены, ~50 пар, сознательно отложен как low-ROI ещё в исходном комментарии) — не взят в работу в этой сессии, возврат к нему по необходимости.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2291
No description provided.