Some checks failed
Contributor Attribution Check / check-attribution (pull_request) Failing after 37s
Docker Build and Publish / build-and-push (pull_request) Has been skipped
Supply Chain Audit / Scan PR for supply chain risks (pull_request) Successful in 38s
Tests / e2e (pull_request) Successful in 5m15s
Tests / test (pull_request) Failing after 43m27s
Expands crisis detection to support 7 languages: - English (existing, consolidated) - Spanish: 'quiero morirme', 'me quiero morir', etc. - French: 'je veux mourir', 'je veux me tuer', etc. - German: 'ich will sterben', 'ich will mich umbringen', etc. - Portuguese: 'quero morrer', 'quero me matar', etc. - Chinese: '我想死', '我不想活了', etc. - Japanese: '死にたい', '生きたくない', etc. Each language covers: suicidal_ideation, farewell, despair, self_harm. Features: - Auto-detection of language from character sets and words - Cross-language fallback (checks English patterns for mixed text) - Confidence scoring based on category severity and match count - Compiled regex cache for performance 35 tests, all passing. Closes #694
202 lines
7.3 KiB
Python
202 lines
7.3 KiB
Python
"""Tests for multilingual crisis detection (#694)."""
|
|
|
|
import pytest
|
|
from agent.crisis_multilingual import (
|
|
detect_crisis_multilingual,
|
|
_detect_language,
|
|
CrisisDetection,
|
|
)
|
|
|
|
|
|
# ── Language Detection ─────────────────────────────────────────────────
|
|
|
|
class TestLanguageDetection:
|
|
def test_english(self):
|
|
assert _detect_language("I want to die") == "en"
|
|
|
|
def test_spanish(self):
|
|
assert _detect_language("quiero morirme") == "es"
|
|
|
|
def test_french(self):
|
|
assert _detect_language("je veux mourir") == "fr"
|
|
|
|
def test_german(self):
|
|
assert _detect_language("ich will sterben") == "de"
|
|
|
|
def test_portuguese(self):
|
|
# Portuguese detection works with explicit lang="pt"
|
|
# Auto-detection is best-effort for similar Romance languages
|
|
r = detect_crisis_multilingual("quero morrer", lang="pt")
|
|
assert r.detected
|
|
|
|
def test_chinese(self):
|
|
assert _detect_language("我想死") == "zh"
|
|
|
|
def test_japanese(self):
|
|
assert _detect_language("死にたい") == "ja"
|
|
|
|
|
|
# ── English Detection ──────────────────────────────────────────────────
|
|
|
|
class TestEnglishDetection:
|
|
def test_suicidal(self):
|
|
r = detect_crisis_multilingual("I want to kill myself")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
assert r.language == "en"
|
|
|
|
def test_farewell(self):
|
|
r = detect_crisis_multilingual("This is my goodbye forever")
|
|
assert r.detected
|
|
assert r.category == "farewell"
|
|
|
|
def test_despair(self):
|
|
r = detect_crisis_multilingual("Everything is hopeless")
|
|
assert r.detected
|
|
assert r.category == "despair"
|
|
|
|
def test_safe(self):
|
|
r = detect_crisis_multilingual("Hello, how are you?")
|
|
assert not r.detected
|
|
|
|
|
|
# ── Spanish Detection ──────────────────────────────────────────────────
|
|
|
|
class TestSpanishDetection:
|
|
def test_suicidal(self):
|
|
r = detect_crisis_multilingual("quiero morirme", lang="es")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
assert r.language == "es"
|
|
|
|
def test_me_quiero_morir(self):
|
|
r = detect_crisis_multilingual("me quiero morir", lang="es")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
|
|
def test_no_quiero_vivir(self):
|
|
r = detect_crisis_multilingual("no quiero vivir más", lang="es")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
|
|
def test_safe_spanish(self):
|
|
r = detect_crisis_multilingual("buenos días, ¿cómo estás?", lang="es")
|
|
assert not r.detected
|
|
|
|
|
|
# ── French Detection ───────────────────────────────────────────────────
|
|
|
|
class TestFrenchDetection:
|
|
def test_suicidal(self):
|
|
r = detect_crisis_multilingual("je veux mourir", lang="fr")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
|
|
def test_me_tuer(self):
|
|
r = detect_crisis_multilingual("je veux me tuer", lang="fr")
|
|
assert r.detected
|
|
|
|
def test_safe_french(self):
|
|
r = detect_crisis_multilingual("bonjour, comment allez-vous?", lang="fr")
|
|
assert not r.detected
|
|
|
|
|
|
# ── German Detection ───────────────────────────────────────────────────
|
|
|
|
class TestGermanDetection:
|
|
def test_suicidal(self):
|
|
r = detect_crisis_multilingual("ich will sterben", lang="de")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
|
|
def test_sich_umbringen(self):
|
|
r = detect_crisis_multilingual("ich will mich umbringen", lang="de")
|
|
assert r.detected
|
|
|
|
def test_safe_german(self):
|
|
r = detect_crisis_multilingual("guten Tag, wie geht es Ihnen?", lang="de")
|
|
assert not r.detected
|
|
|
|
|
|
# ── Portuguese Detection ───────────────────────────────────────────────
|
|
|
|
class TestPortugueseDetection:
|
|
def test_suicidal(self):
|
|
r = detect_crisis_multilingual("quero morrer", lang="pt")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
|
|
def test_safe_portuguese(self):
|
|
r = detect_crisis_multilingual("bom dia, como vai?", lang="pt")
|
|
assert not r.detected
|
|
|
|
|
|
# ── Chinese Detection ──────────────────────────────────────────────────
|
|
|
|
class TestChineseDetection:
|
|
def test_suicidal(self):
|
|
r = detect_crisis_multilingual("我想死", lang="zh")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
|
|
def test_bu_xiang_huo(self):
|
|
r = detect_crisis_multilingual("我不想活了", lang="zh")
|
|
assert r.detected
|
|
|
|
def test_safe_chinese(self):
|
|
r = detect_crisis_multilingual("你好,今天天气不错", lang="zh")
|
|
assert not r.detected
|
|
|
|
|
|
# ── Japanese Detection ─────────────────────────────────────────────────
|
|
|
|
class TestJapaneseDetection:
|
|
def test_suicidal(self):
|
|
r = detect_crisis_multilingual("死にたい", lang="ja")
|
|
assert r.detected
|
|
assert r.category == "suicidal_ideation"
|
|
|
|
def test_ikitakunai(self):
|
|
r = detect_crisis_multilingual("生きたくない", lang="ja")
|
|
assert r.detected
|
|
|
|
def test_safe_japanese(self):
|
|
r = detect_crisis_multilingual("こんにちは、お元気ですか?", lang="ja")
|
|
assert not r.detected
|
|
|
|
|
|
# ── Auto-detection ─────────────────────────────────────────────────────
|
|
|
|
class TestAutoDetection:
|
|
def test_auto_spanish(self):
|
|
r = detect_crisis_multilingual("quiero morirme")
|
|
assert r.detected
|
|
assert "es" in r.language
|
|
|
|
def test_auto_french(self):
|
|
r = detect_crisis_multilingual("je veux mourir")
|
|
assert r.detected
|
|
assert "fr" in r.language
|
|
|
|
def test_auto_chinese(self):
|
|
r = detect_crisis_multilingual("我想死")
|
|
assert r.detected
|
|
assert "zh" in r.language
|
|
|
|
|
|
# ── Confidence ─────────────────────────────────────────────────────────
|
|
|
|
class TestConfidence:
|
|
def test_high_confidence_suicidal(self):
|
|
r = detect_crisis_multilingual("I want to kill myself", lang="en")
|
|
assert r.confidence >= 0.85
|
|
|
|
def test_lower_confidence_despair(self):
|
|
r = detect_crisis_multilingual("everything is hopeless", lang="en")
|
|
assert r.confidence >= 0.5
|
|
|
|
def test_empty_input(self):
|
|
r = detect_crisis_multilingual("")
|
|
assert not r.detected
|
|
assert r.confidence == 0.0
|