개선관리 요구사항과 Google 로그인을 완료
This commit is contained in:
parent
cc0a15b7c6
commit
2a39636163
112 changed files with 10166 additions and 527 deletions
|
|
@ -363,6 +363,89 @@ def mask_synthetic_generated_pii(text: str) -> MaskResult:
|
|||
)
|
||||
|
||||
|
||||
_IDENTITY_SEGMENT_RE = re.compile(r"\s*[·|,/]\s*", re.UNICODE)
|
||||
_IDENTITY_UUID_RE = re.compile(
|
||||
r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
_IDENTITY_KO_PARTICLE_LOOKAHEAD = (
|
||||
r"(?:은|는|이|가|을|를|와|과|의|도|에게|께|랑|하고|님|씨)"
|
||||
)
|
||||
|
||||
|
||||
def _known_identity_variants(identity: str | None) -> list[str]:
|
||||
"""Return conservative display-name variants that are safe to role-tokenize."""
|
||||
|
||||
raw = str(identity or "").strip()
|
||||
if not raw or "@" in raw or _IDENTITY_UUID_RE.fullmatch(raw):
|
||||
return []
|
||||
first_segment = _IDENTITY_SEGMENT_RE.split(raw, maxsplit=1)[0].strip()
|
||||
first_segment = re.sub(r"\s*\(가명\)\s*$", "", first_segment).strip()
|
||||
variants: list[str] = []
|
||||
for candidate in (raw, first_segment):
|
||||
if candidate in variants:
|
||||
continue
|
||||
letters = re.sub(r"[^A-Za-z가-힣]", "", candidate)
|
||||
if len(letters) < 2:
|
||||
continue
|
||||
variants.append(candidate)
|
||||
return sorted(variants, key=len, reverse=True)
|
||||
|
||||
|
||||
def mask_role_identities(
|
||||
text: str,
|
||||
*,
|
||||
counselor_identity: str | None = None,
|
||||
client_identity: str | None = None,
|
||||
synthetic_generated: bool = False,
|
||||
) -> MaskResult:
|
||||
"""Mask known session identities with role tokens, then apply the normal PII gate.
|
||||
|
||||
Only identities already owned by the authenticated session are role-tokenized.
|
||||
Unknown third-party names keep the generic ``[NAME]`` token so the UI cannot
|
||||
incorrectly present every person as the client.
|
||||
"""
|
||||
|
||||
role_values = (
|
||||
("ROLE_COUNSELOR", "[COUNSELOR]", counselor_identity),
|
||||
("ROLE_CLIENT", "[CLIENT]", client_identity),
|
||||
)
|
||||
redacted = text
|
||||
role_entities: list[str] = []
|
||||
claimed_variants: set[str] = set()
|
||||
for entity, placeholder, identity in role_values:
|
||||
for variant in _known_identity_variants(identity):
|
||||
normalized = variant.casefold()
|
||||
if normalized in claimed_variants:
|
||||
continue
|
||||
pattern = (
|
||||
rf"(?<![A-Za-z가-힣]){re.escape(variant)}"
|
||||
rf"(?=$|[^A-Za-z가-힣]|{_IDENTITY_KO_PARTICLE_LOOKAHEAD})"
|
||||
)
|
||||
replaced, count = re.subn(
|
||||
pattern,
|
||||
placeholder,
|
||||
redacted,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
if count:
|
||||
redacted = replaced
|
||||
role_entities.append(entity)
|
||||
claimed_variants.add(normalized)
|
||||
|
||||
masked = (
|
||||
mask_synthetic_generated_pii(redacted)
|
||||
if synthetic_generated
|
||||
else mask_pii(redacted)
|
||||
)
|
||||
return MaskResult(
|
||||
text_masked=masked.text_masked,
|
||||
entities=sorted(set(masked.entities + role_entities)),
|
||||
used_presidio=masked.used_presidio,
|
||||
used_ko_recognizer=masked.used_ko_recognizer,
|
||||
)
|
||||
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════════
|
||||
# 2. 위기 분류 (입력 — 실제위기 vs 페르소나 연기 구분, R8)
|
||||
# ════════════════════════════════════════════════════════════════════════════
|
||||
|
|
@ -438,6 +521,8 @@ _MEANS_TERMS = [
|
|||
"커터", "면도날", "손목 긋", "깊게 그으", "라이터로 지",
|
||||
]
|
||||
_DISPLAY_PLACEHOLDER_LABELS = {
|
||||
"COUNSELOR": "상담자",
|
||||
"CLIENT": "내담자",
|
||||
"NAME": "그 이름",
|
||||
"ORG": "그 기관",
|
||||
"PHONE": "연락처",
|
||||
|
|
@ -449,7 +534,7 @@ _DISPLAY_PLACEHOLDER_LABELS = {
|
|||
"ADDR": "그 주소",
|
||||
}
|
||||
_DISPLAY_PLACEHOLDER_RE = re.compile(
|
||||
r"\[(?P<label>NAME|ORG|PHONE|EMAIL|RRN|NUMID|DATE|MONEY|ADDR)\]"
|
||||
r"\[(?P<label>COUNSELOR|CLIENT|NAME|ORG|PHONE|EMAIL|RRN|NUMID|DATE|MONEY|ADDR)\]"
|
||||
r"(?P<particle>[은는이가을를와과])?"
|
||||
)
|
||||
_DISPLAY_PLACEHOLDER_STREAM_TAIL = 16
|
||||
|
|
@ -625,6 +710,7 @@ __all__ = [
|
|||
"PiiEntitySpan",
|
||||
"set_ko_pii_recognizer",
|
||||
"mask_pii",
|
||||
"mask_role_identities",
|
||||
"mask_synthetic_generated_pii",
|
||||
"CrisisKind",
|
||||
"CrisisResult",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue