[core] Safety: лексикон + LLM-сигнал, кризисный скрипт, recall 100% на наборе #4
Notifications
Due Date
No due date set.
Blocks
Depends on
#10 [bot][A] Движок диалога: конвейер scrub → safety → FSM → мониторинг, согласие, возраст, кризис
MedITron/PTSRaiAgent
#24 [core] Eval извлечения и safety на размеченном наборе → цифры для слайда
MedITron/PTSRaiAgent
#1 [devops] Каркас: uv-проект, docker-compose, Makefile, CI
MedITron/PTSRaiAgent
Reference: MedITron/PTSRaiAgent#4
Reference in New Issue
Block a user
Описание
Guardrail №2: safety до LLM на каждом входящем. При
acuteотвечает фиксированный скрипт, LLM не генерирует. SPEC §3, §7.Желаемый результат
app/core/safety.py:check(text_scrubbed, llm_signal=None) -> SafetyResult(level: none|possible|acute, matched: list[str]); итог — максимум из лексикона и LLM.config/lexicon/risk_ru.yaml: категории (суицид, самоповреждение, насилие/угроза другим, оружие, домашнее насилие) × уровень; нормализация (lowercase, ё→е, леммы/стемминг через простые правила, опечатки), отрицания («не хочу умирать» не должно давать acute, но possible допустим).config/texts/crisis.yaml: 112, телефон доверия 8-800-2000-122, «вы не одни», что врач уже уведомлён; дляfamily— ресурсы по домашнему насилию.tests/test_safety.py: ≥ 40 фраз (из демо: «всё бессмысленно, устал от всего» → possible минимум), recall acute = 100%.Ограничения и риски
Ложноположительные допустимы, пропуск — нет. Сырой текст не логировать.
Лог выполнения
2026-10-03
2026-10-03
app/core/safety.py:check(text: ScrubbedText, llm_signal: RiskLevel | None = None) -> SafetyResult(frozen:level,categories,matched_rules,negated_rules,source), итог =max(лексикон, LLM);crisis_reply(categories, audience="patient"|"family") -> CrisisScript(готовыйtext+ части).hochu umeret'), пунктуация → пробел, «жииить» → «жить».config/lexicon/risk_ru.yaml: 6 категорий (suicide, self_harm, harm_others, weapon_access, domestic_violence, hopelessness), ~50 правил на основах слов + частые опечатки, ветеранский сленг («стать двухсотым», «лучше бы я там остался», «к пацанам туда»), комбинация «оружие + любой сигнал риска → acute».config/texts/crisis.yaml: варианты patient.default / patient.harm_others / patient.domestic_violence / family.default / family.domestic_violence; 112, телефон доверия 8-800-2000-122 (бесплатно, круглосуточно), 102 для насилия, «врач уже уведомлён», строка заземления; для семьи — не уговаривать «потерпеть».tests/data/safety_cases.yaml: 99 фраз (64 acute / 18 possible, из них 6 отрицаний / 17 none); recall acute = 100%, в т.ч. послеscrub(); ни одна none-фраза не acute; демо-фразы откалиброваны. ~0,1–1 мс на сообщение.tests/test_safety.py,make lint testзелёные.