Перейти к содержанию

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%)

Примеры (анонимизированные):

  1. Negation — единственный случай прямого «ты ошиблась»:
  2. prev_q: «Я имел в виду эту норму: Примечание: Для тонального и импульсного шума на 5 дБ менее...»
  3. prev_resp: «Да, здесь действительно есть снижение на 5 дБ для шума от вентиляции» (Lyumi сослалась на ГОСТ 12.1.003-83)
  4. follow_up: «С гостом ошиблась, но в целом логика понятна. Ты уверена?» — юзер поправил конкретный ГОСТ, логика верна.
  5. Это reasoning OK, factual слабость (ссылка на ГОСТ). Не покрывается validator слоем.

  6. But — Приказ 1057 / СЭЗ:

  7. prev_q: «Ну так в приказе 1057 ничего нет про СЭС»
  8. prev_resp: «Ты прав — в приказе нет требования о СЭЗ. Но логика аттестации требует ввода в эксплуатацию...»
  9. follow_up: «Но ведь акт об вводе в эксплуатацию идет раньше. И у нас уже он есть»
  10. Юзер поправил последовательность процедуры — reasoning escape, validator пропустил.

  11. What_if — Приказ 1053 / список вредных профессий:

  12. prev_q: «А что за приказ 1053 список там профессий?»
  13. follow_up: «А если в этом приказе нет моей должности, что делать?»
  14. Конструктивный follow-up, не escape.

Вывод: базовая статистика расхождения «юзер не согласен» = ~1% от диалогов. Из 7 случаев 2-3 — вероятные reasoning errors не покрытые правилами (ГОСТ ссылка, последовательность процедуры). Это слабый сигнал, но достаточный чтобы не считать тему закрытой.

Что это значит

По каждому развёрнутому правилу

  1. tr_ts_019_certificate_vs_lifetime (critical) — задеплоено под конкретный live-кейс утром 2 мая. За предыдущие 47 дней юзеры не задавали этот вопрос в формулировке, которая попала бы под триггеры. Validator работает как точечный страховочный полис, не как широкий фильтр.

  2. koap_vs_uk_distinction — единственный hit, FP. Pattern по КоАП.*лишение свободы слишком широкий (матчит через посредник). Suppress-патерн УК.*уголовн не симметричен (только один порядок).

  3. 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 просто показывает что ширина покрытия очень узкая.

Что предлагает данные

  1. Расширить корпус правил. 5 правил → 15-20 (план Sprint A после 9 мая, см. lyumi/reasoning_layer_design). Кандидаты для новых rules можно собрать из:
  2. 7 follow-up escapes (особенно «ты ошиблась с ГОСТом», «но ведь акт о вводе раньше») — кейсы где юзер указал на ошибку.
  3. Reflection JSONL логов (reflections_*.jsonl) — там async Haiku-fact-check уже маркирует ~30% запросов. Пересечение с reasoning-зоной даст реальные кандидаты.

  4. Сузить FP-источник в koap rule. Конкретно: pattern[5] по\s+КоАП.*лишени[ея]\s+свобод либо ограничить расстоянием ({0,80}), либо добавить отрицательный lookahead на «по ст.\s*\d+\s+УК» в окне.

  5. Категоричные фразы как самостоятельный сигнал — слаб. 55.7% записей фолс-позитив. Если хотим использовать — нужна LLM-классификация контекста (Haiku decide: «категоричное утверждение в этом ответе — нормативная норма или reasoning short-circuit?»). Это уже Слой 4 из дизайна.

  6. 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

Камал, посмотри:

  1. Один FP koap-правила (раздел «Единственный hit») — подтверди что регекс действительно слишком широкий и стоит сузить.
  2. Negation case с ГОСТом — это reasoning или factual? Если reasoning, можно вытащить шаблон под новое правило.
  3. But-кейс с приказом 1057 / СЭЗ — последовательность процедуры (акт ввода → аттестация). Кандидат на правило act_input_then_attestation_order?
  4. Полный список из 7 follow-upssamples.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 — анонимизированные сэмплы