feat(core): safety detector with RU risk lexicon and fixed crisis script

- check(text, llm_signal) -> SafetyResult: normalisation (ё, homoglyphs, translit,
  repeats), stem regexes per category, negation window (acute -> possible only),
  weapon+risk combination, final level = max(lexicon, llm)
- crisis_reply(categories, audience) loads config/texts/crisis.yaml (patient/family,
  domestic violence and harm-to-others variants)
- 99-phrase eval set; acute recall 100%, < 5 ms per message

Refs #4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 15:01:35 +03:00
co-authored by Claude Opus 5.5
parent bfccc21a58
commit 97f3173c9f
5 changed files with 1035 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
# Кризисный скрипт (guardrail №2, issue #4). Отправляется ДОСЛОВНО при safety = acute; LLM не вызывается.
# СТАТУС: черновик, утверждает психиатр (#8).
#
# Выбор варианта (app/core/safety.py::crisis_reply): `<audience>.<категория>` по порядку category_priority,
# иначе `<audience>.default`. Итоговое сообщение = text + ресурсы + doctor_notified + grounding.
status: "черновик, утверждает психиатр (#8)"
category_priority: [domestic_violence, harm_others]
resources:
emergency:
name: "Экстренные службы"
phone: "112"
note: "если есть угроза жизни прямо сейчас"
helpline:
name: "Телефон доверия"
phone: "8-800-2000-122"
note: "бесплатно, круглосуточно"
police:
name: "Полиция"
phone: "102"
note: "если вам угрожают или применяют насилие"
variants:
patient.default:
text: |-
Мне очень жаль, что вам сейчас так тяжело. Вы не одни, и хорошо, что вы об этом написали.
Если вы в опасности прямо сейчас — пожалуйста, позвоните 112. Если рядом есть то, чем можно причинить
себе вред (оружие, таблетки), по возможности уберите это подальше или отдайте близкому человеку
и побудьте рядом с кем-то, кому доверяете.
resources: [emergency, helpline]
doctor_notified: "Ваш врач уже уведомлён и свяжется с вами."
grounding: "Сейчас попробуйте сделать медленный вдох на 4 счёта и выдох на 6 — несколько раз. Я рядом."
patient.harm_others:
text: |-
Похоже, сейчас очень много злости и напряжения — это тяжело выдерживать. Вы не одни.
Пожалуйста, отойдите от человека и от всего, чем можно причинить вред, и побудьте там, где спокойнее.
Если кому-то угрожает опасность прямо сейчас — позвоните 112.
resources: [emergency, helpline]
doctor_notified: "Ваш врач уже уведомлён и свяжется с вами."
grounding: "Поставьте ступни на пол, сделайте медленный вдох на 4 счёта и выдох на 6 — несколько раз."
patient.domestic_violence:
text: |-
Мне очень жаль, что с вами это происходит. Вы не виноваты в насилии, и вы не обязаны его терпеть.
Если вам или детям угрожает опасность — уйдите в безопасное место (к соседям, родным) и позвоните 112.
Кризисные службы и телефон доверия помогут найти безопасное место и поддержку.
resources: [emergency, police, helpline]
doctor_notified: "Ваш врач уже уведомлён."
grounding: "Если вы сейчас в безопасности — сделайте медленный вдох на 4 счёта и выдох на 6. Я рядом."
family.default:
text: |-
Спасибо, что написали — вы делаете очень важное дело. Вы не одни.
Если есть угроза жизни прямо сейчас — позвоните 112. По возможности не оставляйте близкого одного,
спокойно уберите из доступа оружие, таблетки и острые предметы. Не спорьте и не стыдите —
просто будьте рядом и слушайте.
resources: [emergency, helpline]
doctor_notified: "Лечащий врач уже уведомлён."
grounding: "Позаботьтесь и о себе: сделайте медленный вдох на 4 счёта и выдох на 6."
family.domestic_violence:
text: |-
Ваша безопасность и безопасность детей важнее всего. Вы не виноваты в насилии и не обязаны его
терпеть — никто не вправе уговаривать вас «потерпеть», даже если близкий болен.
Если угрожает опасность — уйдите в безопасное место (к соседям, родным) и позвоните 112.
Кризисные службы помогут с временным убежищем и поддержкой.
resources: [emergency, police, helpline]
doctor_notified: "Лечащий врач уже уведомлён."
grounding: "Когда будете в безопасности — сделайте медленный вдох на 4 счёта и выдох на 6."