위기 표현 경계를 확장
This commit is contained in:
parent
35a9d8802c
commit
aeca42475b
3 changed files with 115 additions and 7 deletions
|
|
@ -469,8 +469,10 @@ _CRISIS_TERMS = [
|
|||
"죽고 싶", "죽고싶", "자살 생각", "자살하고 싶", "자살을 생각", "자살 충동",
|
||||
"자살 시도", "목숨을 끊", "목숨을 버리", "사라지고 싶", "없어지고 싶",
|
||||
"자해하고 싶", "자해한 적", "자해를 했", "자해 충동", "자해 시도",
|
||||
"스스로를 다치게", "끝내고 싶", "살기 싫",
|
||||
"살아서 뭐", "죽어야", "안전을 스스로 지키기 어렵",
|
||||
"자살 계획", "자해 계획", "자살하려고", "자해하려고", "죽으려고",
|
||||
"스스로를 다치게", "스스로를 해칠 계획", "자살할지도", "끝내고 싶",
|
||||
"살기 싫", "살아서 뭐", "죽어야", "안전을 스스로 지키기 어렵",
|
||||
"안전을 유지할 수 없",
|
||||
]
|
||||
# 자살·자해 단어를 직접 쓰지 않더라도 본인의 현재 위험과 실제 도움 필요를 함께
|
||||
# 밝히는 짧은 진술은 엔진 호출 전에 막아야 한다. 단일 '위험'/'도움' 키워드만으로는
|
||||
|
|
@ -503,7 +505,7 @@ _PERSONAL_DANGER_PATTERNS = (
|
|||
),
|
||||
)
|
||||
_PERSONAL_IMMEDIATE_HARM = (
|
||||
r"(?:안전하지\s*않|안전을?\s*지킬\s*수\s*없|"
|
||||
r"(?:안전하지\s*않|안전을?\s*(?:지킬|유지할)\s*수\s*없|"
|
||||
r"(?:제|내)\s*안전을?\s*지킬\s*(?:자신이|수)?\s*없|"
|
||||
r"혼자\s*있으면\s*위험|"
|
||||
r"(?:스스로를|저를|나를|제\s*자신을|내\s*자신을)\s*"
|
||||
|
|
@ -527,11 +529,14 @@ _PERSONAL_IMMEDIATE_HARM_PATTERNS = (
|
|||
),
|
||||
)
|
||||
_CURRENT_SUICIDE_OR_SELF_HARM = (
|
||||
r"(?:자살(?:하고)?\s*싶|자살할\s*것\s*같|죽고\s*싶|"
|
||||
r"(?:자살(?:하고)?\s*싶|자살(?:하)?려고\s*(?:해요|합니다)|"
|
||||
r"자살할\s*(?:것\s*같|지도\s*모르)|죽고\s*싶|"
|
||||
r"죽으려고\s*(?:해요|합니다)|"
|
||||
r"죽어버리고\s*싶|살기\s*싫|살고\s*싶지\s*않|"
|
||||
r"자해(?:하고)?\s*싶|자해할\s*것\s*같|"
|
||||
r"자해(?:하고)?\s*싶|자해(?:하)?려고\s*(?:해요|합니다)|"
|
||||
r"자해할\s*(?:것\s*같|지도\s*모르)|"
|
||||
r"(?:스스로를|저를|나를)\s*(?:다치게\s*하고|해치고)\s*싶|"
|
||||
r"(?:제|내)\s*목숨을\s*끊고\s*싶|삶을\s*끝내고\s*싶|"
|
||||
r"(?:제|내)\s*목숨을\s*(?:끊고\s*싶|끊으려고\s*(?:해요|합니다))|"
|
||||
r"끝내고\s*싶|없어지고\s*싶|죽어야\s*할\s*것\s*같|"
|
||||
r"살아갈\s*이유가\s*없|자해\s*충동이\s*있)"
|
||||
)
|
||||
|
|
@ -548,6 +553,12 @@ _FIRST_PERSON_CURRENT_CRISIS_PATTERNS = (
|
|||
rf"{_SELF_SUBJECT}(?:이|은|도)?\s*(?:정말|진짜)\s*"
|
||||
rf"{_CURRENT_SUICIDE_OR_SELF_HARM}"
|
||||
),
|
||||
re.compile(
|
||||
rf"{_CURRENT}\s*(?:당장\s*)?"
|
||||
r"(?:자살(?:하)?려고\s*(?:해요|합니다)|"
|
||||
r"죽으려고\s*(?:해요|합니다)|"
|
||||
r"자해(?:하)?려고\s*(?:해요|합니다))"
|
||||
),
|
||||
)
|
||||
_FIRST_PERSON_EXPLICIT_CRISIS_PATTERNS = (
|
||||
re.compile(
|
||||
|
|
@ -558,12 +569,27 @@ _FIRST_PERSON_EXPLICIT_CRISIS_PATTERNS = (
|
|||
rf"당장\s*{_SELF_SUBJECT}(?:이|은|도)?\s*"
|
||||
rf"{_CURRENT_SUICIDE_OR_SELF_HARM}"
|
||||
),
|
||||
re.compile(
|
||||
r"(?<![가-힣A-Za-z0-9])(?:제|내)\s*목숨을\s*"
|
||||
r"(?:끊고\s*싶|끊으려고\s*(?:해요|합니다))"
|
||||
),
|
||||
)
|
||||
_REAL_HELP_CUE = re.compile(
|
||||
r"(?:(?:실제로\s*)?도움(?:이|을)?\s*필요|도와(?:주|줄|주세요))"
|
||||
)
|
||||
_CURRENT_PERSONAL_DANGER_HELP = "first_person_current_danger_help"
|
||||
_FIRST_PERSON_CURRENT_CRISIS = "first_person_current_suicide_or_self_harm"
|
||||
_EXPLICIT_HIGH_RISK = "explicit_suicide_or_self_harm_risk"
|
||||
_EXPLICIT_HIGH_RISK_CUE = re.compile(
|
||||
r"(?<![가-힣A-Za-z0-9])(?:"
|
||||
r"(?:자살|자해)\s*(?:계획|충동|생각)(?:이|가|은|는)?\s*(?:있|세웠)|"
|
||||
r"(?:자살|자해)\s*시도(?:를|가|는)?\s*(?:하)?려고\s*(?:해요|합니다)|"
|
||||
r"(?:스스로를|저를|나를|제\s*자신을|내\s*자신을)\s*해칠\s*계획"
|
||||
r"(?:이|가|은|는)?\s*(?:있|세웠)|"
|
||||
r"(?:자살|자해)할지도\s*모르|"
|
||||
r"(?:제|내)\s*안전을?\s*(?:지킬|유지할)\s*수\s*없"
|
||||
r")"
|
||||
)
|
||||
_INDIRECT_SELF_ERASURE = "indirect_self_erasure"
|
||||
_INDIRECT_SELF_ERASURE_CUE = re.compile(
|
||||
r"(?<![가-힣A-Za-z0-9])(?:차라리\s*(?:없어졌으면|사라졌으면)|"
|
||||
|
|
@ -607,6 +633,12 @@ _NEGATED_CRISIS = re.compile(
|
|||
r"(?:자살(?:하고)?|죽고|자해(?:하고)?)\s*싶은\s*(?:생각|마음)"
|
||||
r"(?:이|은)?\s*(?:전혀\s*)?(?:없|들지\s*않)|"
|
||||
r"(?:자살\s*생각|자해\s*충동)(?:이|은)?\s*(?:전혀\s*)?(?:없|들지\s*않)|"
|
||||
r"(?:자살|자해)할\s*것\s*같지\s*않|살기\s*싫지\s*않|"
|
||||
r"없어지고\s*싶지\s*않|죽어야\s*할\s*것\s*같지\s*않|"
|
||||
r"살아갈\s*이유가\s*없는\s*(?:건|것은)\s*아니|"
|
||||
r"자해\s*충동이\s*있지는\s*않|"
|
||||
r"(?:자살|자해)\s*(?:계획|충동|생각|시도)(?:이|가|은|는)?\s*"
|
||||
r"(?:전혀\s*)?(?:없|있지는\s*않|하지\s*않)|"
|
||||
r"위험(?:한|할)\s*것\s*같지\s*않|도움(?:이|을)?\s*필요하지\s*않"
|
||||
)
|
||||
_RECOVERED_PAST_CRISIS = re.compile(
|
||||
|
|
@ -716,6 +748,11 @@ def crisis_signal_matches(text: str) -> list[str]:
|
|||
matched.append(_CURRENT_PERSONAL_DANGER_HELP)
|
||||
if _first_person_current_crisis(text):
|
||||
matched.append(_FIRST_PERSON_CURRENT_CRISIS)
|
||||
if any(
|
||||
not _match_has_invalid_crisis_context(text, match)
|
||||
for match in _EXPLICIT_HIGH_RISK_CUE.finditer(text)
|
||||
):
|
||||
matched.append(_EXPLICIT_HIGH_RISK)
|
||||
return matched
|
||||
|
||||
|
||||
|
|
@ -739,8 +776,14 @@ def classify_crisis(text: str, *, speaker_is_persona_context: bool = True) -> Cr
|
|||
risk = min(5, 2 + len(matched)) # 거친 단계화(휴리스틱)
|
||||
explicit_real_signal = _CURRENT_PERSONAL_DANGER_HELP in matched
|
||||
explicit_current_crisis = _FIRST_PERSON_CURRENT_CRISIS in matched
|
||||
explicit_high_risk = _EXPLICIT_HIGH_RISK in matched
|
||||
|
||||
if not speaker_is_persona_context or explicit_real_signal or explicit_current_crisis:
|
||||
if (
|
||||
not speaker_is_persona_context
|
||||
or explicit_real_signal
|
||||
or explicit_current_crisis
|
||||
or explicit_high_risk
|
||||
):
|
||||
# 실제 위기 가능 → 에스컬레이션(보수적)
|
||||
return CrisisResult(
|
||||
kind=CrisisKind.LEARNER_REAL,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue