SqueakyCleanText 0.5.2__tar.gz → 0.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {squeakycleantext-0.5.2/SqueakyCleanText.egg-info → squeakycleantext-0.6.1}/PKG-INFO +228 -36
  2. squeakycleantext-0.5.2/PKG-INFO → squeakycleantext-0.6.1/README.md +190 -75
  3. squeakycleantext-0.5.2/README.md → squeakycleantext-0.6.1/SqueakyCleanText.egg-info/PKG-INFO +267 -6
  4. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/SqueakyCleanText.egg-info/SOURCES.txt +5 -0
  5. squeakycleantext-0.6.1/SqueakyCleanText.egg-info/requires.txt +58 -0
  6. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/pyproject.toml +41 -29
  7. squeakycleantext-0.6.1/sct/__init__.py +13 -0
  8. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/config.py +170 -26
  9. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/sct.py +119 -36
  10. squeakycleantext-0.6.1/sct/utils/anonymization_map.py +89 -0
  11. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/contact.py +18 -0
  12. squeakycleantext-0.6.1/sct/utils/gliclass_adapter.py +97 -0
  13. squeakycleantext-0.6.1/sct/utils/gliner_adapter.py +200 -0
  14. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/ner.py +132 -28
  15. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/normtext.py +2 -1
  16. squeakycleantext-0.6.1/sct/utils/process_result.py +67 -0
  17. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/resources.py +41 -16
  18. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/special.py +4 -19
  19. squeakycleantext-0.6.1/sct/utils/synthetic.py +125 -0
  20. squeakycleantext-0.6.1/tests/test_functional.py +956 -0
  21. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/tests/test_sct.py +755 -7
  22. squeakycleantext-0.5.2/SqueakyCleanText.egg-info/requires.txt +0 -46
  23. squeakycleantext-0.5.2/sct/__init__.py +0 -7
  24. squeakycleantext-0.5.2/sct/utils/gliner_adapter.py +0 -110
  25. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/LICENSE +0 -0
  26. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/SqueakyCleanText.egg-info/dependency_links.txt +0 -0
  27. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/SqueakyCleanText.egg-info/top_level.txt +0 -0
  28. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/__init__.py +0 -0
  29. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/constants.py +0 -0
  30. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/datetime.py +0 -0
  31. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/onnx_pipeline.py +0 -0
  32. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/stopwords.py +0 -0
  33. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/sct/utils/torch_pipeline.py +0 -0
  34. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/setup.cfg +0 -0
  35. {squeakycleantext-0.5.2 → squeakycleantext-0.6.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SqueakyCleanText
3
- Version: 0.5.2
3
+ Version: 0.6.1
4
4
  Summary: Text preprocessing & PII anonymization pipeline for NLP/ML: ONNX NER ensemble, language detection, stopword removal, and configurable token replacement.
5
5
  Author: Rehan Fazal
6
6
  License: MIT
@@ -27,44 +27,52 @@ Classifier: Operating System :: OS Independent
27
27
  Requires-Python: >=3.11
28
28
  Description-Content-Type: text/markdown
29
29
  License-File: LICENSE
30
- Requires-Dist: lingua-language-detector>=2.0.2
30
+ Requires-Dist: lingua-language-detector>=2.1.0
31
31
  Requires-Dist: stop-words>=2025.11.4
32
- Requires-Dist: emoji>=2.8
33
- Requires-Dist: ftfy>=6.1
34
- Requires-Dist: Unidecode>=1.3
35
- Requires-Dist: beautifulsoup4>=4.12
36
- Requires-Dist: onnxruntime>=1.24.1
37
- Requires-Dist: tokenizers>=0.22.0
38
- Requires-Dist: huggingface-hub>=1.4.0
39
- Requires-Dist: numpy>=2.0.0
40
- Requires-Dist: presidio_anonymizer>=2.2.355
41
- Requires-Dist: regex>=2024.0.0
32
+ Requires-Dist: emoji>=2.14
33
+ Requires-Dist: ftfy>=6.3
34
+ Requires-Dist: Unidecode>=1.4
35
+ Requires-Dist: beautifulsoup4>=4.14
36
+ Requires-Dist: onnxruntime>=1.24.2
37
+ Requires-Dist: tokenizers>=0.22.2
38
+ Requires-Dist: huggingface-hub>=1.5.0
39
+ Requires-Dist: numpy>=2.2.0
40
+ Requires-Dist: presidio_anonymizer>=2.2.360
41
+ Requires-Dist: regex>=2024.11.6
42
42
  Provides-Extra: gpu
43
- Requires-Dist: onnxruntime-gpu>=1.24.1; extra == "gpu"
43
+ Requires-Dist: onnxruntime-gpu>=1.24.2; extra == "gpu"
44
44
  Provides-Extra: fuzzy
45
- Requires-Dist: rapidfuzz>=3.0; extra == "fuzzy"
45
+ Requires-Dist: rapidfuzz>=3.12; extra == "fuzzy"
46
46
  Provides-Extra: torch
47
- Requires-Dist: torch>=2.0.0; extra == "torch"
48
- Requires-Dist: transformers>=4.30; extra == "torch"
47
+ Requires-Dist: torch>=2.6.0; extra == "torch"
48
+ Requires-Dist: transformers>=4.48; extra == "torch"
49
49
  Provides-Extra: gliner
50
- Requires-Dist: gliner>=1.0; extra == "gliner"
50
+ Requires-Dist: gliner<1.0,>=0.2.25; extra == "gliner"
51
51
  Provides-Extra: gliner2
52
- Requires-Dist: gliner2>=0.0.1; extra == "gliner2"
52
+ Requires-Dist: gliner2<2.0,>=1.0; extra == "gliner2"
53
+ Provides-Extra: synthetic
54
+ Requires-Dist: faker>=33.0; extra == "synthetic"
55
+ Provides-Extra: presidio
56
+ Requires-Dist: presidio-analyzer>=2.2.360; extra == "presidio"
57
+ Provides-Extra: classify
58
+ Requires-Dist: gliclass>=0.1.16; extra == "classify"
59
+ Provides-Extra: classify-onnx
60
+ Requires-Dist: onnxruntime>=1.24.2; extra == "classify-onnx"
53
61
  Provides-Extra: all-ner
54
- Requires-Dist: torch>=2.0.0; extra == "all-ner"
55
- Requires-Dist: transformers>=4.30; extra == "all-ner"
56
- Requires-Dist: gliner>=1.0; extra == "all-ner"
57
- Requires-Dist: gliner2>=0.0.1; extra == "all-ner"
62
+ Requires-Dist: torch>=2.6.0; extra == "all-ner"
63
+ Requires-Dist: transformers>=4.48; extra == "all-ner"
64
+ Requires-Dist: gliner<1.0,>=0.2.25; extra == "all-ner"
65
+ Requires-Dist: gliner2<2.0,>=1.0; extra == "all-ner"
58
66
  Provides-Extra: dev
59
- Requires-Dist: hypothesis>=6.82; extra == "dev"
60
- Requires-Dist: faker>=20.0; extra == "dev"
61
- Requires-Dist: ruff>=0.4; extra == "dev"
62
- Requires-Dist: pytest>=8.0; extra == "dev"
63
- Requires-Dist: pytest-timeout>=2.2; extra == "dev"
64
- Requires-Dist: rapidfuzz>=3.0; extra == "dev"
67
+ Requires-Dist: hypothesis>=6.130; extra == "dev"
68
+ Requires-Dist: faker>=33.0; extra == "dev"
69
+ Requires-Dist: ruff>=0.11; extra == "dev"
70
+ Requires-Dist: pytest>=8.3; extra == "dev"
71
+ Requires-Dist: pytest-timeout>=2.3; extra == "dev"
72
+ Requires-Dist: rapidfuzz>=3.12; extra == "dev"
65
73
  Provides-Extra: test
66
- Requires-Dist: coverage>=7.3; extra == "test"
67
- Requires-Dist: pytest-cov>=4.1; extra == "test"
74
+ Requires-Dist: coverage>=7.8; extra == "test"
75
+ Requires-Dist: pytest-cov>=6.0; extra == "test"
68
76
  Dynamic: license-file
69
77
 
70
78
  <div align="center">
@@ -168,6 +176,9 @@ The base install uses **ONNX Runtime** for NER inference - no PyTorch or Transfo
168
176
  | PyTorch NER | `pip install SqueakyCleanText[torch]` | PyTorch/Transformers NER backend |
169
177
  | GLiNER | `pip install SqueakyCleanText[gliner]` | [GLiNER](https://github.com/urchade/GLiNER) zero-shot NER |
170
178
  | GLiNER2 | `pip install SqueakyCleanText[gliner2]` | [GLiNER2](https://github.com/Knowledgator/GLiNER) (knowledgator) backend |
179
+ | Synthetic | `pip install SqueakyCleanText[synthetic]` | Faker-based synthetic replacement (realistic fake values instead of `<TAG>` tokens) |
180
+ | Presidio | `pip install SqueakyCleanText[presidio]` | Presidio-analyzer for `presidio_gliner` backend |
181
+ | Classify | `pip install SqueakyCleanText[classify]` | GLiClass document-level pre-classification |
171
182
  | All NER | `pip install SqueakyCleanText[all-ner]` | All NER backends combined |
172
183
  | Development | `pip install SqueakyCleanText[dev]` | Testing and linting tools |
173
184
 
@@ -212,13 +223,28 @@ cfg = TextCleanerConfig(
212
223
  replace_with_url="<URL>",
213
224
  replace_with_email="<EMAIL>",
214
225
  replace_with_phone_numbers="<PHONE>",
215
- language="ENGLISH", # Skip auto-detection
226
+ language="en", # Pin to English (also accepts 'ENGLISH', 'eng')
216
227
  )
217
228
 
218
229
  # Initialize with config
219
230
  cleaner = TextCleaner(cfg=cfg)
220
231
  ```
221
232
 
233
+ #### Language Specification
234
+
235
+ All language parameters accept Lingua names (`'ENGLISH'`), ISO 639-1 (`'en'`), or ISO 639-3 (`'eng'`) codes:
236
+
237
+ ```python
238
+ # Pin to one language (skip auto-detection)
239
+ cfg = TextCleanerConfig(language='de', check_ner_process=False)
240
+
241
+ # Restrict detection to specific languages (auto-detect among them)
242
+ cfg = TextCleanerConfig(language=('en', 'nl', 'de'), check_ner_process=False)
243
+
244
+ # Add extra languages for detection
245
+ cfg = TextCleanerConfig(extra_languages=('fr', 'pt'), check_ner_process=False)
246
+ ```
247
+
222
248
  ### GLiNER: Zero-Shot Custom NER
223
249
 
224
250
  Use [GLiNER](https://github.com/urchade/GLiNER) to recognize any entity type without retraining:
@@ -262,6 +288,144 @@ cleaner = TextCleaner(cfg=cfg)
262
288
  lm_text, stat_text, lang = cleaner.process("Angela Merkel visited the Bundestag in Berlin.")
263
289
  ```
264
290
 
291
+ ### PII Detection Mode
292
+
293
+ Automatically configure GLiNER for comprehensive PII detection with 60+ entity types (personal, financial, healthcare, identity, digital):
294
+
295
+ ```python
296
+ from sct import TextCleaner, TextCleanerConfig
297
+
298
+ cfg = TextCleanerConfig(ner_mode='pii')
299
+
300
+ cleaner = TextCleaner(cfg=cfg)
301
+ lm_text, stat_text, lang = cleaner.process(
302
+ "John Smith's SSN is 123-45-6789, email john@example.com, DOB 1990-01-15"
303
+ )
304
+ # Entities are anonymized: names, SSNs, emails, dates of birth, and 50+ more PII types
305
+ ```
306
+
307
+ PII mode auto-configures: `ner_backend='gliner'`, uses [`knowledgator/gliner-pii-base-v1.0`](https://huggingface.co/knowledgator/gliner-pii-base-v1.0), sets threshold to 0.3 (recall-focused), and expands positional tags. User-provided values always take priority.
308
+
309
+ **Alternative PII models** (pass as `gliner_model`):
310
+
311
+ | Model | Type | Size | Labels | F1 |
312
+ |-------|------|------|--------|-----|
313
+ | [`knowledgator/gliner-pii-base-v1.0`](https://huggingface.co/knowledgator/gliner-pii-base-v1.0) | Uni-encoder | 330MB (ONNX FP16) | 60+ | 80.99% |
314
+ | [`nvidia/gliner-PII`](https://huggingface.co/nvidia/gliner-PII) | Bi-encoder | 570MB | 55+ | — |
315
+ | [`gretelai/gretel-gliner-bi-base-v1.0`](https://huggingface.co/gretelai/gretel-gliner-bi-base-v1.0) | Bi-encoder | ~800MB | 40+ | 95% |
316
+ | [`urchade/gliner_multi_pii-v1`](https://huggingface.co/urchade/gliner_multi_pii-v1) | Multilingual | — | — | — |
317
+
318
+ ### Synthetic Replacement
319
+
320
+ Replace detected entities with realistic fake values (via [Faker](https://faker.readthedocs.io/)) instead of `<TAG>` placeholder tokens:
321
+
322
+ ```python
323
+ from sct import TextCleaner, TextCleanerConfig
324
+
325
+ cfg = TextCleanerConfig(
326
+ ner_mode='pii',
327
+ replacement_mode='synthetic', # pip install squeakycleantext[synthetic]
328
+ )
329
+
330
+ cleaner = TextCleaner(cfg=cfg)
331
+ lm_text, stat_text, lang = cleaner.process(
332
+ "Contact John Smith at john.smith@company.com or +1-555-0123"
333
+ )
334
+ # Output: "Contact Jennifer Williams at lisa45@example.net or +1-555-0198"
335
+ # Same entity always maps to same fake value within a document
336
+ ```
337
+
338
+ > **Note**: Synthetic replacement preserves data utility for downstream ML tasks but is NOT GDPR-compliant anonymization. Same-document consistency is maintained (same entity text always maps to the same fake value).
339
+
340
+ ### Reversible Anonymization
341
+
342
+ Replace entities with indexed placeholders (`<PERSON_0>`, `<LOCATION_1>`) and get a mapping for round-trip deanonymization:
343
+
344
+ ```python
345
+ from sct import TextCleaner, TextCleanerConfig
346
+
347
+ cfg = TextCleanerConfig(
348
+ ner_mode='pii',
349
+ replacement_mode='reversible',
350
+ )
351
+
352
+ cleaner = TextCleaner(cfg=cfg)
353
+ result = cleaner.process("John Smith works at Google in London.")
354
+
355
+ print(result.lm_text)
356
+ # "<PERSON_0> works at <ORGANISATION_0> in <LOCATION_0>."
357
+
358
+ # Access the anonymization map via metadata
359
+ anon_map = result.metadata['anon_map']
360
+ restored = anon_map.deanonymize(result.lm_text)
361
+ # "John Smith works at Google in London."
362
+
363
+ # Serialize the map for storage
364
+ import json
365
+ json.dumps(anon_map.to_dict())
366
+ ```
367
+
368
+ > **Note**: `ProcessResult` from `process()` unpacks as a 3-tuple (`lm_text, stat_text, language`) for backward compatibility, but also exposes `.metadata` for reversible maps and document classification.
369
+
370
+ ### Document Classification (GLiClass)
371
+
372
+ Classify documents before processing using zero-shot classification with [GLiClass](https://github.com/Knowledgator/GLiClass):
373
+
374
+ ```python
375
+ from sct import TextCleaner, TextCleanerConfig
376
+
377
+ cfg = TextCleanerConfig(
378
+ check_classify_document=True,
379
+ gliclass_labels=('email', 'code', 'legal', 'medical'),
380
+ # gliclass_model defaults to 'knowledgator/gliclass-edge-v3.0' (32.7M params)
381
+ )
382
+
383
+ cleaner = TextCleaner(cfg=cfg) # pip install squeakycleantext[classify]
384
+ result = cleaner.process("Dear Sir, please find attached the contract...")
385
+
386
+ # Classification results in metadata
387
+ print(result.metadata['classes'])
388
+ # [{"label": "email", "score": 0.92}, {"label": "legal", "score": 0.78}]
389
+ ```
390
+
391
+ ### Bi-Encoder GLiNER Models
392
+
393
+ Bi-encoder models (ModernBERT, etc.) are auto-detected and leverage pre-computed label embeddings for faster inference with larger context windows:
394
+
395
+ ```python
396
+ from sct import TextCleaner, TextCleanerConfig
397
+
398
+ cfg = TextCleanerConfig(
399
+ ner_backend='gliner',
400
+ gliner_model='knowledgator/gliner-bi-base-v2.0',
401
+ gliner_labels=('person', 'organization', 'location'),
402
+ )
403
+
404
+ cleaner = TextCleaner(cfg=cfg)
405
+ # Auto-detects bi-encoder → caches label embeddings → uses 2048+ token context window
406
+ ```
407
+
408
+ ### Entity Description Labels (ZERONER-Style)
409
+
410
+ Provide natural-language descriptions for labels to improve zero-shot recognition accuracy:
411
+
412
+ ```python
413
+ from sct import TextCleaner, TextCleanerConfig
414
+
415
+ cfg = TextCleanerConfig(
416
+ ner_backend='gliner',
417
+ gliner_model='knowledgator/gliner-bi-base-v2.0',
418
+ gliner_label_descriptions={
419
+ 'person': "a person's full legal name",
420
+ 'location': "a geographical place or address",
421
+ 'organization': "a company, institution, or government body",
422
+ },
423
+ )
424
+
425
+ cleaner = TextCleaner(cfg=cfg)
426
+ # Descriptions are used for inference, results are mapped back to original label names
427
+ ```
428
+
265
429
  ### Batch Processing
266
430
 
267
431
  ```python
@@ -318,15 +482,16 @@ cleaner = sct.TextCleaner()
318
482
 
319
483
  ## NER Backends
320
484
 
321
- SqueakyCleanText supports five NER backends, selectable via the `ner_backend` config field:
485
+ SqueakyCleanText supports six NER backends, selectable via the `ner_backend` config field:
322
486
 
323
487
  | Backend | Description | Dependencies | Best for |
324
488
  |---------|-------------|-------------|----------|
325
489
  | `onnx` (default) | ONNX Runtime inference with quantized XLM-RoBERTa models | Base install | Production: fast, torch-free |
326
490
  | `torch` | PyTorch/Transformers pipeline with full XLM-RoBERTa models | `[torch]` extra | Compatibility with existing PyTorch workflows |
327
- | `gliner` | GLiNER zero-shot NER with custom entity labels | `[gliner]` or `[gliner2]` extra | Custom entity types (PRODUCT, SKILL, EVENT, etc.) |
491
+ | `gliner` | GLiNER zero-shot NER with custom entity labels | `[gliner]` or `[gliner2]` extra | Custom entity types, PII detection, bi-encoder models |
328
492
  | `ensemble_onnx` | ONNX + GLiNER ensemble voting | `[gliner]` extra | Maximum recall with custom entities |
329
493
  | `ensemble_torch` | Torch + GLiNER ensemble voting | `[torch,gliner]` extra | Maximum recall with PyTorch |
494
+ | `presidio_gliner` | Presidio + GLiNER recognizer (beta) | `presidio-analyzer`, `[gliner]` | Context-aware NER via Presidio's pipeline |
330
495
 
331
496
  ### Default NER Models (ONNX)
332
497
 
@@ -339,6 +504,17 @@ SqueakyCleanText supports five NER backends, selectable via the `ner_backend` co
339
504
  | French / Portuguese / Italian | [`rhnfzl/wikineural-multilingual-ner-onnx`](https://huggingface.co/rhnfzl/wikineural-multilingual-ner-onnx) (shared session) |
340
505
  | Multilingual (fallback) | [`rhnfzl/wikineural-multilingual-ner-onnx`](https://huggingface.co/rhnfzl/wikineural-multilingual-ner-onnx) |
341
506
 
507
+ ### GLiNER Model Recommendations
508
+
509
+ | Model | Architecture | Context | Languages | Best for |
510
+ |-------|-------------|---------|-----------|----------|
511
+ | `knowledgator/gliner-bi-base-v2.0` | Bi-encoder (ModernBERT) | 2048 | Multi | General NER, long documents |
512
+ | `knowledgator/gliner-pii-base-v1.0` | Bi-encoder | 2048 | Multi | PII detection (60+ entity types) |
513
+ | `urchade/gliner_large-v2.1` | Uni-encoder (DeBERTa) | 512 | Multi | Legacy, high accuracy on short texts |
514
+ | `MatteoFasulo/ModernBERT-base-NER` | ModernBERT | 8192 | English | English-only, very long context |
515
+
516
+ > **GLiNER2 note**: `pip install squeakycleantext[gliner2]` installs [Knowledgator's gliner2 package](https://github.com/Knowledgator/GLiNER), not Fastino AI's GLiNER2 from EMNLP 2025 (different API).
517
+
342
518
  ### GLiNER Label Mapping
343
519
 
344
520
  GLiNER uses lowercase free-text labels (e.g., `'person'`, `'product'`). To map them to standard NER tags used by the anonymizer, use `gliner_label_map`:
@@ -449,7 +625,9 @@ new_cfg = dataclasses.replace(cfg, check_ner_process=False)
449
625
 
450
626
  | Field | Default | Description |
451
627
  |-------|---------|-------------|
452
- | `ner_backend` | `'onnx'` | Backend: `onnx`, `torch`, `gliner`, `ensemble_onnx`, `ensemble_torch` |
628
+ | `ner_backend` | `'onnx'` | Backend: `onnx`, `torch`, `gliner`, `ensemble_onnx`, `ensemble_torch`, `presidio_gliner` |
629
+ | `ner_mode` | `'standard'` | `'standard'` or `'pii'` (auto-configures GLiNER for PII detection) |
630
+ | `replacement_mode` | `'placeholder'` | `'placeholder'`, `'synthetic'` (Faker), or `'reversible'` (indexed placeholders + deanonymize map) |
453
631
  | `positional_tags` | `('PER', 'LOC', 'ORG', 'MISC')` | Entity types to recognize |
454
632
  | `ner_confidence_threshold` | `0.85` | Minimum confidence score |
455
633
  | `ner_batch_size` | `8` | Inference batch size (must be >= 1) |
@@ -460,6 +638,7 @@ new_cfg = dataclasses.replace(cfg, check_ner_process=False)
460
638
  | `gliner_labels` | `('person', 'organization', 'location')` | GLiNER entity labels |
461
639
  | `gliner_label_map` | `None` | Maps GLiNER labels to NER tags |
462
640
  | `gliner_threshold` | `0.4` | GLiNER confidence threshold |
641
+ | `gliner_label_descriptions` | `None` | ZERONER-style: `{label: "description"}` for improved zero-shot accuracy |
463
642
  | `fuzzy_date_score_cutoff` | `85` | Fuzzy matching threshold (0-100) for misspelled months |
464
643
  | `custom_pipeline_steps` | `()` | Tuple of `(text: str) -> str` callables appended after all built-in steps |
465
644
 
@@ -467,8 +646,8 @@ new_cfg = dataclasses.replace(cfg, check_ner_process=False)
467
646
 
468
647
  | Field | Default | Description |
469
648
  |-------|---------|-------------|
470
- | `language` | `None` | Pin language (skip detection) |
471
- | `extra_languages` | `()` | Additional language names for detection |
649
+ | `language` | `None` | Pin language (`'en'`), restrict detection to a set (`('en','nl')`), or `None` for auto-detect. Accepts Lingua names, ISO 639-1, ISO 639-3 codes. |
650
+ | `extra_languages` | `()` | Additional language names/codes for detection |
472
651
  | `custom_stopwords` | `None` | `{LANG: frozenset({...})}` custom stopword sets |
473
652
  | `custom_month_names` | `None` | `{LANG: ('Jan', 'Feb', ...)}` for date detection |
474
653
 
@@ -511,6 +690,19 @@ Each step is toggled by a `TextCleanerConfig` field. The pipeline is built once
511
690
 
512
691
  ## What's New
513
692
 
693
+ **v0.6.0**
694
+ - **PII detection mode** (`ner_mode='pii'`): auto-configures GLiNER with 60+ PII entity labels (personal, financial, healthcare, identity, digital)
695
+ - **Synthetic replacement** (`replacement_mode='synthetic'`): Faker-generated realistic values instead of `<TAG>` placeholders, with per-document consistency
696
+ - **Reversible anonymization** (`replacement_mode='reversible'`): indexed placeholders (`<PERSON_0>`) with `AnonymizationMap` for round-trip deanonymization
697
+ - **Document classification** (`check_classify_document=True`): zero-shot GLiClass pre-classification before text processing
698
+ - **ProcessResult**: `process()` returns `ProcessResult` (backward-compatible 3-tuple) with `.metadata` for anonymization maps and classification results
699
+ - **GLiNER ONNX mode** (`gliner_onnx=True`): load GLiNER with pre-built ONNX weights from HuggingFace Hub (auto-set for PII + ONNX backend)
700
+ - **Bi-encoder support**: auto-detects ModernBERT and other bi-encoder GLiNER models, caches label embeddings, dynamic context windows (2048-8192 tokens)
701
+ - **Entity description labels**: ZERONER-style natural-language descriptions for improved zero-shot accuracy
702
+ - **Presidio GLiNER backend** (beta): opt-in `ner_backend='presidio_gliner'` for Presidio's context-aware recognition pipeline
703
+ - **ModernBERT ONNX export**: updated export script with ModernBERT support (English, 8192 token context)
704
+ - **Dynamic chunk sizing**: GLiNER chunk size adapts to model's actual context window instead of hardcoded 384
705
+
514
706
  **v0.5.x**
515
707
  - `aprocess_batch()`: async batch processing for FastAPI / aiohttp integrations
516
708
  - `warmup(languages)`: pre-load NER models at startup to eliminate first-request latency