Backtest reasoning_validator — 47-дневные prod-логи (2 мая 2026)
Цель: понять реальные precision/recall свежеразвёрнутых (2 мая) reasoning rules на исторических данных до их деплоя. Это baseline для observation week — что бы поймал validator если бы был развёрнут раньше.
Что сделано
Прогнал reasoning_validator.validate(query, response) без модификации response на всех логах из hse_copilot/prod_logs/queries_2026-*.jsonl. Скрипт: hse_copilot/backtest_reasoning_validator.py. Результаты: hse_copilot/research/2026-05-02-backtest/{aggregates,samples}.json.
Дополнительно — два heuristic скана для возможных пропущенных reasoning mistakes:
1. Категоричные выражения в ответах (нельзя, обязан, всегда, никогда, только, должен, запрещ*) — потенциальная false certainty.
2. Follow-up юзера в течение 30 минут с маркерами несогласия (нет, не правильно, но ведь, а если, ты ошиблась) — возможные reasoning escapes.
Источник данных
| Параметр | Значение |
|---|---|
| Папка логов | hse_copilot/prod_logs/ |
| Файлов (дней с активностью) | 41 |
| Календарный охват | 2026-03-16 → 2026-05-01 (47 дней) |
| Записей всего (после фильтра пустых) | 954 |
| Уникальных правил в validator | 5 |
Главный результат: 0 истинных срабатываний за 47 дней
Validator backtest — rule hits
| rule_id | hits | hit rate | severity |
|---|---|---|---|
tr_ts_019_certificate_vs_lifetime |
0 | 0.000% | critical |
koap_vs_uk_distinction |
1 (FP, см. ниже) | 0.105% | warning |
medosmotr_office_workers |
0 | 0.000% | warning |
act_n1_authority |
0 | 0.000% | warning |
ptw_storage_period |
0 | 0.000% | warning |
| ИТОГО | 1 срабатывание | 0.10% записей | warning |
Записей с несколькими сработавшими правилами: 0.
Единственный hit — false positive
koap_vs_uk_distinction, 2026-04-30, ответ Sonnet 4 на «Напиши текст предписания по нарушению»:
«...по КоАП РК и может квалифицироваться как уголовно наказуемое деяние по ст. 156 УК РК (до 7 лет лишения свобод)...»
Сработал паттерн по\s+КоАП.*лишени[ея]\s+свобод — он сматчил всю фразу через посредник «уголовно наказуемое деяние по ст. 156 УК РК». В реальности ответ корректный: бот правильно различил административную (КоАП) и уголовную (УК) ответственность. Регекс схватил совпадение через несвязанные слова.
Suppress-паттерны не отработали: УК.*уголовн ищет «УК» до «уголовно», а в реальном тексте порядок обратный («уголовно ... УК»).
Вывод по слою 2A: на 47-дневных боевых данных validator поймал 0 истинных reasoning mistakes и сгенерировал 1 false positive. Hit rate = 0.10% (полностью FP).
Heuristic 1: категоричные выражения
| Фраза | Совпадений | На 100 записей |
|---|---|---|
| должен / должна / должны | 441 | 46.2 |
| только | 293 | 30.7 |
| обязан / обязаны / обязательно | 241 | 25.3 |
| запрещ(ено|ается|ён) | 59 | 6.2 |
| нельзя | 42 | 4.4 |
| всегда | 33 | 3.5 |
| никогда | 10 | 1.0 |
531 запись (55.7%) содержит хотя бы один категоричный маркер. Это неинтерпретируемо без второго слоя — HSE-домен по природе императивный («работник должен надеть СИЗ», «без наряд-допуска нельзя»). Большинство «нельзя/обязан» — это правомерные нормы, а не false certainty.
Сэмпл подсветил типовой паттерн: «нельзя» в ответах Lyumi чаще встречается в: - Корректных нормативных утверждениях («нельзя проводить аттестацию без СЭЗ») - Self-reflection («нельзя выдумывать инциденты, особенно даты») - Объяснении карточек («нельзя полагаться на запах H₂S»)
Вывод: категоричный сёрчинг как сигнал false certainty без LLM-классификации = шум. Список фраз нужно либо ужать (только «всегда»+«никогда» вне нормативных контекстов), либо комбинировать с reasoning-rule триггерами.
Heuristic 2: follow-up reasoning escapes
Найдено 707 пар (next message от того же uid в течение 30 минут). Из них с маркерами несогласия:
| Маркер | Совпадений |
|---|---|
а если / а что если / а как тогда |
4 |
но ведь / но это / однако |
2 |
нет, не / не правильно / ошиб |
1 |
ты не прав / это не так |
0 |
| ИТОГО | 7 / 707 пар (1.0%) |
Примеры (анонимизированные):
- Negation — единственный случай прямого «ты ошиблась»:
- prev_q: «Я имел в виду эту норму: Примечание: Для тонального и импульсного шума на 5 дБ менее...»
- prev_resp: «Да, здесь действительно есть снижение на 5 дБ для шума от вентиляции» (Lyumi сослалась на ГОСТ 12.1.003-83)
- follow_up: «С гостом ошиблась, но в целом логика понятна. Ты уверена?» — юзер поправил конкретный ГОСТ, логика верна.
-
Это reasoning OK, factual слабость (ссылка на ГОСТ). Не покрывается validator слоем.
-
But — Приказ 1057 / СЭЗ:
- prev_q: «Ну так в приказе 1057 ничего нет про СЭС»
- prev_resp: «Ты прав — в приказе нет требования о СЭЗ. Но логика аттестации требует ввода в эксплуатацию...»
- follow_up: «Но ведь акт об вводе в эксплуатацию идет раньше. И у нас уже он есть»
-
Юзер поправил последовательность процедуры — reasoning escape, validator пропустил.
-
What_if — Приказ 1053 / список вредных профессий:
- prev_q: «А что за приказ 1053 список там профессий?»
- follow_up: «А если в этом приказе нет моей должности, что делать?»
- Конструктивный follow-up, не escape.
Вывод: базовая статистика расхождения «юзер не согласен» = ~1% от диалогов. Из 7 случаев 2-3 — вероятные reasoning errors не покрытые правилами (ГОСТ ссылка, последовательность процедуры). Это слабый сигнал, но достаточный чтобы не считать тему закрытой.
Что это значит
По каждому развёрнутому правилу
-
tr_ts_019_certificate_vs_lifetime(critical) — задеплоено под конкретный live-кейс утром 2 мая. За предыдущие 47 дней юзеры не задавали этот вопрос в формулировке, которая попала бы под триггеры. Validator работает как точечный страховочный полис, не как широкий фильтр. -
koap_vs_uk_distinction— единственный hit, FP. Patternпо КоАП.*лишение свободыслишком широкий (матчит через посредник). Suppress-патернУК.*уголовнне симметричен (только один порядок). -
medosmotr_office_workers,act_n1_authority,ptw_storage_period— за 47 дней ни одна формулировка ответа не попала в violation_patterns. Возможные причины: (а) юзеры не задают эти вопросы достаточно часто, (б) когда задают, ответы Lyumi уже корректны, (в) формулировки реальных ошибок отличаются от unit-test mock'ов.
Архитектурный вывод
Reasoning rules в текущем виде = regression защита от уже исправленных кейсов, не превентивный фильтр. На 47-дневном backtest: - 0 истинных positives → recall не оценивается (ошибки могут быть, validator их не видит). - 1 false positive → precision формально 0%.
Это не доказывает что rules бесполезны — они добавлены ПОСЛЕ live regression и страхуют от повторения именно тех формулировок. Backtest просто показывает что ширина покрытия очень узкая.
Что предлагает данные
- Расширить корпус правил. 5 правил → 15-20 (план Sprint A после 9 мая, см.
lyumi/reasoning_layer_design). Кандидаты для новых rules можно собрать из: - 7 follow-up escapes (особенно «ты ошиблась с ГОСТом», «но ведь акт о вводе раньше») — кейсы где юзер указал на ошибку.
-
Reflection JSONL логов (
reflections_*.jsonl) — там async Haiku-fact-check уже маркирует ~30% запросов. Пересечение с reasoning-зоной даст реальные кандидаты. -
Сузить FP-источник в koap rule. Конкретно: pattern[5]
по\s+КоАП.*лишени[ея]\s+свободлибо ограничить расстоянием ({0,80}), либо добавить отрицательный lookahead на «по ст.\s*\d+\s+УК» в окне. -
Категоричные фразы как самостоятельный сигнал — слаб. 55.7% записей фолс-позитив. Если хотим использовать — нужна LLM-классификация контекста (Haiku decide: «категоричное утверждение в этом ответе — нормативная норма или reasoning short-circuit?»). Это уже Слой 4 из дизайна.
-
Honest baseline для observation week. Сейчас зафиксирован baseline = 1 hit/47 дней. После недели реальной работы validator на проде сравним с этим числом — если живой триггер-rate ≥3x от backtest baseline, значит правила что-то ловят. Если ≈ baseline, значит правила покрывают только синтетические/redo-кейсы.
Соблюдены принципы
- ❌ Prod не модифицировался.
- ❌ Сырые логи никуда не выгружены — все samples хранятся в
research/2026-05-02-backtest/локально, user_id хешированы (sha256[:8]). - ❌ Regex не тюнились до желаемой картинки. Записан baseline as is, включая FP в koap.
Что для ручного review
Камал, посмотри:
- Один FP koap-правила (раздел «Единственный hit») — подтверди что регекс действительно слишком широкий и стоит сузить.
- Negation case с ГОСТом — это reasoning или factual? Если reasoning, можно вытащить шаблон под новое правило.
- But-кейс с приказом 1057 / СЭЗ — последовательность процедуры (акт ввода → аттестация). Кандидат на правило
act_input_then_attestation_order? - Полный список из 7 follow-ups —
samples.json.followup_samples (3 категории по 2-3 кейса).
Связи
- [[lyumi/reasoning_layer_design]] — дизайн (Sprint A после 9 мая включает расширение rules)
- [[lyumi/sprints/2026-05-02-reasoning-layer-deployed]] — sprint write-up развёрнутого минимума
hse_copilot/backtest_reasoning_validator.py— скрипт прогонаhse_copilot/research/2026-05-02-backtest/aggregates.json— числовые агрегатыhse_copilot/research/2026-05-02-backtest/samples.json— анонимизированные сэмплы