Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ class KrRrnRecognizer(PatternRecognizer):
]

CONTEXT = [
"주민등록번호",
"주민번호",
"주민등록증",
"주민등록",
"신분증",
"본인인증",
"Korean RRN",
"Korean Resident Registration Number",
"Resident Registration Number",
Expand Down
105 changes: 101 additions & 4 deletions presidio-analyzer/tests/test_kr_rrn_recognizer.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import pytest
from presidio_analyzer.predefined_recognizers import KrRrnRecognizer

from tests import assert_result_within_score_range
from presidio_analyzer.predefined_recognizers import KrRrnRecognizer


@pytest.fixture(scope="module")
def recognizer():
"""Return KrRrnRecognizer instance."""
return KrRrnRecognizer()


@pytest.fixture(scope="module")
def entities():
"""Return supported entity list."""
return ["KR_RRN"]


@pytest.mark.parametrize(
"text, expected_len, expected_positions, expected_score_ranges",
[
Expand All @@ -20,15 +25,19 @@ def entities():
("000505-3637892", 1, ((0, 14),), ((0.5, 0.5),), ),
("0005053637892", 1, ((0, 13),), ((0.5, 0.5),), ),
("His Korean RRN is 960121-1234567", 1, ((18, 32),), ((0.5, 0.5),), ),

("주민등록번호: 960121-1234567", 1, ((8, 22),), ((0.5, 0.5),), ),
("신분증 확인: 960121-1234567", 1, ((8, 22),), ((0.5, 0.5),), ),
("본인인증 960121-1234567", 1, ((5, 19),), ((0.5, 0.5),), ),

# Valid RRNs, strong match by validate_result()
("960121-1021413", 1, ((0, 14),), ((1.0, 1.0),), ),
("9601211021413", 1, ((0, 13),), ((1.0, 1.0),), ),
("050912-2000019", 1, ((0, 14),), ((1.0, 1.0),), ),
("0509122000019", 1, ((0, 13),), ((1.0, 1.0),), ),
("His RRN is 9601211021413", 1, ((11, 24),), ((1.0, 1.0),), ),

# Invalid RRNs
("주민번호는 9601211021413입니다", 1, ((6, 19),), ((1.0, 1.0),), ),

# Invalid RRNs
("001332-1234567", 0, (), (),),
("0013321234567", 0, (), (),),
("960121+1021413", 0, (), (),),
Expand All @@ -48,6 +57,7 @@ def test_when_all_rrns_then_succeed(
entities,
max_score,
):
"""Test recognition and validation of Korean RRN across valid and invalid inputs."""
results = recognizer.analyze(text, entities)
assert len(results) == expected_len
for res, (st_pos, fn_pos), (st_score, fn_score) in zip(
Expand All @@ -58,3 +68,90 @@ def test_when_all_rrns_then_succeed(
assert_result_within_score_range(
res, entities[0], st_pos, fn_pos, st_score, fn_score
)


def test_korean_context_keywords_in_rrn_recognizer(recognizer):
"""Test that Korean context keywords are present in KrRrnRecognizer.context."""
expected_korean_keywords = [
"주민등록번호",
"주민번호",
"주민등록증",
"주민등록",
"신분증",
"본인인증",
]
for keyword in expected_korean_keywords:
assert keyword in recognizer.context


@pytest.mark.parametrize(
"context_word",
["주민등록번호", "주민번호", "주민등록증", "주민등록", "신분증", "본인인증"],
)
def test_when_korean_context_used_then_score_enhanced(recognizer, context_word):
"""Test that Korean context keywords enhance confidence score from 0.5 to 0.85."""
from presidio_analyzer.context_aware_enhancers import LemmaContextAwareEnhancer
from presidio_analyzer.nlp_engine import NlpArtifacts

text = f"{context_word} 960121-1234567"
results = recognizer.analyze(text, ["KR_RRN"])
assert len(results) == 1
assert results[0].score == 0.5

tokens = [context_word, "960121-1234567"]
tokens_indices = [0, len(context_word) + 1]
artifacts = NlpArtifacts(
entities=[],
tokens=tokens,
tokens_indices=tokens_indices,
lemmas=tokens,
nlp_engine=None,
language="ko",
)
artifacts.keywords = [context_word, "960121-1234567"]

enhancer = LemmaContextAwareEnhancer()
enhanced_results = enhancer.enhance_using_context(
text, results, artifacts, [recognizer]
)

assert len(enhanced_results) == 1
assert enhanced_results[0].score == 0.85
assert (
enhanced_results[0].analysis_explanation.supportive_context_word
== context_word
)


def test_when_no_korean_context_then_score_not_enhanced(recognizer):
"""Test that unrelated context does not enhance confidence score."""
from presidio_analyzer.context_aware_enhancers import LemmaContextAwareEnhancer
from presidio_analyzer.nlp_engine import NlpArtifacts

text = "random text 960121-1234567"
results = recognizer.analyze(text, ["KR_RRN"])
assert len(results) == 1
assert results[0].score == 0.5

tokens = ["random", "text", "960121-1234567"]
tokens_indices = [0, 7, 12]
artifacts = NlpArtifacts(
entities=[],
tokens=tokens,
tokens_indices=tokens_indices,
lemmas=tokens,
nlp_engine=None,
language="ko",
)
artifacts.keywords = ["random", "text", "960121-1234567"]

enhancer = LemmaContextAwareEnhancer()
enhanced_results = enhancer.enhance_using_context(
text, results, artifacts, [recognizer]
)

assert len(enhanced_results) == 1
assert enhanced_results[0].score == 0.5
assert (
enhanced_results[0].analysis_explanation.supportive_context_word == ""
)