Skip to content
Draft
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file.
- The `kr` language code is deprecated in favor of the ISO 639-1 code `ko`. `KrRrnRecognizer` and `KrPassportRecognizer` still accept `kr` in `supported_languages` as a backward-compatibility alias for registries configured against their original class defaults; the alias will be removed in <release TBD>. `KrBrnRecognizer`, `KrDriverLicenseRecognizer` and `KrFrnRecognizer` have only ever defaulted to `ko`, so `kr` was removed from their `default_recognizers.yaml` entries in this release. (#2236)

#### Fixed
- `PhoneRecognizer.analyze` assigned the region detected for a match back to the `region` variable it was iterating over, so an international-format number that parsed successfully overwrote the region used to explain every later match in that pass. With the default recognizer, `"My international number is +44 1234 567890, and my US one is (415) 555-0132"` labelled the US number `Recognized as GB region phone number`; swapping the two numbers hid it. Detected spans, scores and entity types were unaffected — only `analysis_explanation` named a region that never matched the number. The detected region is now held in a per-match `matched_region`, and the `NumberParseException` branch reports the region the match was actually found under.
- `PhoneRecognizer.DEFAULT_SUPPORTED_REGIONS` used `"UK"`, which is not a valid `phonenumbers` (libphonenumber) region code — region codes are ISO 3166-1 alpha-2, where the United Kingdom is `"GB"`. The `"UK"` entry was a no-op, so UK numbers in national/local format (e.g. `020 7946 0958`) were never detected by default; only international-format `+44 …` numbers matched, because they carry the country code and match under any region. Replaced `"UK"` with `"GB"`.
- Language model recognizers (`BasicLangExtractRecognizer`, `AzureOpenAILangExtractRecognizer`) configured in a recognizer registry YAML now honour `config_path` (and other recognizer-specific kwargs). Previously these entries were validated by the strict `PredefinedRecognizerConfig` schema, which has no `config_path` field and does not allow extra keys, so `config_path` was silently dropped and the recognizer fell back to its bundled default model configuration. Added a `LangExtractRecognizerConfig` model (`extra="allow"`) and registered both recognizer class names in `CONFIG_MODEL_MAP`.
- `BasicLangExtractRecognizer` now honours values under `langextract.model.provider.language_model_params` (including `timeout` and `num_ctx`). Previously these were silently dropped because `langextract.extract()` ignores its `language_model_params` argument when a pre-built `ModelConfig` is passed via `config=`, causing Ollama-backed recognizers to fall back to langextract's 120s default regardless of the configured timeout. The recognizer now merges `language_model_params` into `ModelConfig.provider_kwargs`, which is the path that reaches the provider constructor. Explicit entries under `provider.kwargs:` still take precedence. Also fixed a `TypeError` when `kwargs:` or `language_model_params:` is `null` in the YAML. (#1943, Thanks @lsternlicht)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ def analyze(
):
try:
parsed_number = phonenumbers.parse(text[match.start : match.end])
region = phonenumbers.region_code_for_number(parsed_number)
results += [
self._get_recognizer_result(match, text, region, nlp_artifacts)
]
matched_region = phonenumbers.region_code_for_number(parsed_number)
except NumberParseException:
results += [
self._get_recognizer_result(match, text, region, nlp_artifacts)
]
matched_region = region
results += [
self._get_recognizer_result(
match, text, matched_region, nlp_artifacts
)
]

return EntityRecognizer.remove_duplicates(results)

Expand Down
8 changes: 8 additions & 0 deletions presidio-analyzer/tests/test_phone_recognizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ def test_when_phone_with_leniency_then_succeed(
2, ["PHONE_NUMBER", "PHONE_NUMBER"],
((16, 30), (60, 77),), 0.4,
['Recognized as US region phone number, using PhoneRecognizer','Recognized as FR region phone number, using PhoneRecognizer']),
# The international number comes first here: it is parsed successfully and
# used to be assigned back to the loop variable, so the national-format
# number that follows was explained with the previous match's region.
# Every case above puts the national number first, which hides that order.
("My international number is +44 1234 567890, and my US one is (415) 555-0132",
2, ["PHONE_NUMBER", "PHONE_NUMBER"],
((27, 42), (61, 75),), 0.4,
['Recognized as GB region phone number, using PhoneRecognizer','Recognized as US region phone number, using PhoneRecognizer']),
# fmt: on
],
)
Expand Down