feat(core): safety-детектор, лексикон риска и кризисный скрипт #33

Merged
Eleboba merged 2 commits from feat/4-safety into dev 2026-10-03 15:03:11 +03:00
Owner

Что меняется

Детектор кризиса (guardrail №2): лексикон риска с нормализацией и обработкой отрицаний + LLM-сигнал (берём максимум), фиксированный кризисный скрипт для пациента и семьи. Recall acute = 100% на eval-наборе из 99 фраз.

Closes #4

Зона

core

Как проверить

make lint test
uv run python -c "from app.core.safety import check, crisis_reply; r = check('хочу покончить с собой'); print(r); print(crisis_reply(r.categories).text)"

API для других зон:

  • check(text: ScrubbedText, llm_signal: RiskLevel | None = None) -> SafetyResult (level, categories, matched_rules, negated_rules, source) — без сырого текста.
  • crisis_reply(categories: list[str], audience: Literal["patient","family"] = "patient") -> CrisisScript — .text готов к отправке дословно.

Чек-лист

  • rebase на origin/dev
  • make lint + make test зелёные
  • лог в issue (### YYYY-MM-DD)
  • нет ПДн в логах, нет реальных данных, нет секретов
  • общие файлы не трогал

🤖 Generated with Claude Code

## Что меняется Детектор кризиса (guardrail №2): лексикон риска с нормализацией и обработкой отрицаний + LLM-сигнал (берём максимум), фиксированный кризисный скрипт для пациента и семьи. Recall acute = 100% на eval-наборе из 99 фраз. Closes #4 ## Зона core ## Как проверить ```bash make lint test uv run python -c "from app.core.safety import check, crisis_reply; r = check('хочу покончить с собой'); print(r); print(crisis_reply(r.categories).text)" ``` API для других зон: - `check(text: ScrubbedText, llm_signal: RiskLevel | None = None) -> SafetyResult` (`level`, `categories`, `matched_rules`, `negated_rules`, `source`) — без сырого текста. - `crisis_reply(categories: list[str], audience: Literal["patient","family"] = "patient") -> CrisisScript` — `.text` готов к отправке дословно. ## Чек-лист - [x] rebase на origin/dev - [x] make lint + make test зелёные - [x] лог в issue (### YYYY-MM-DD) - [x] нет ПДн в логах, нет реальных данных, нет секретов - [x] общие файлы не трогал 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Eleboba added 2 commits 2026-10-03 15:02:31 +03:00
- 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>
test(core): check acute recall after scrub() pipeline
CI / ruff · pytest (pull_request) Successful in 30s
123111bc9d
Refs #4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eleboba merged commit a86008f248 into dev 2026-10-03 15:03:11 +03:00
Eleboba deleted branch feat/4-safety 2026-10-03 15:03:11 +03:00
Sign in to join this conversation.