SqueakyCleanText 0.6.1__tar.gz → 0.7.0__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.
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/PKG-INFO +138 -7
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/README.md +130 -1
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/SqueakyCleanText.egg-info/PKG-INFO +138 -7
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/SqueakyCleanText.egg-info/SOURCES.txt +24 -1
- squeakycleantext-0.7.0/SqueakyCleanText.egg-info/entry_points.txt +3 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/SqueakyCleanText.egg-info/requires.txt +7 -4
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/pyproject.toml +13 -6
- squeakycleantext-0.7.0/sct/__init__.py +71 -0
- squeakycleantext-0.7.0/sct/adapters.py +215 -0
- squeakycleantext-0.7.0/sct/browser.py +123 -0
- squeakycleantext-0.7.0/sct/cli.py +101 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/config.py +93 -7
- squeakycleantext-0.7.0/sct/evaluation.py +209 -0
- squeakycleantext-0.7.0/sct/mcp_server.py +104 -0
- squeakycleantext-0.7.0/sct/model_benchmark.py +173 -0
- squeakycleantext-0.7.0/sct/model_candidates.py +89 -0
- squeakycleantext-0.7.0/sct/ocr.py +123 -0
- squeakycleantext-0.7.0/sct/privacy.py +169 -0
- squeakycleantext-0.7.0/sct/risk.py +58 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/sct.py +222 -11
- squeakycleantext-0.7.0/sct/streaming.py +87 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/contact.py +1 -10
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/gliclass_adapter.py +10 -8
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/gliner_adapter.py +6 -3
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/ner.py +186 -13
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/onnx_pipeline.py +3 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/process_result.py +3 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/torch_pipeline.py +11 -2
- squeakycleantext-0.7.0/tests/test_adapters.py +104 -0
- squeakycleantext-0.7.0/tests/test_browser.py +37 -0
- squeakycleantext-0.7.0/tests/test_cli.py +79 -0
- squeakycleantext-0.7.0/tests/test_contracts.py +136 -0
- squeakycleantext-0.7.0/tests/test_evaluation.py +129 -0
- squeakycleantext-0.7.0/tests/test_mcp_server.py +95 -0
- squeakycleantext-0.7.0/tests/test_model_benchmarks.py +119 -0
- squeakycleantext-0.7.0/tests/test_ocr.py +87 -0
- squeakycleantext-0.7.0/tests/test_privacy.py +334 -0
- squeakycleantext-0.7.0/tests/test_risk.py +21 -0
- squeakycleantext-0.7.0/tests/test_streaming.py +34 -0
- squeakycleantext-0.6.1/sct/__init__.py +0 -13
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/LICENSE +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/SqueakyCleanText.egg-info/dependency_links.txt +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/SqueakyCleanText.egg-info/top_level.txt +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/__init__.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/anonymization_map.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/constants.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/datetime.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/normtext.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/resources.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/special.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/stopwords.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/sct/utils/synthetic.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/setup.cfg +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/setup.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/tests/test_functional.py +0 -0
- {squeakycleantext-0.6.1 → squeakycleantext-0.7.0}/tests/test_sct.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SqueakyCleanText
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
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
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/rhnfzl/SqueakyCleanText
|
|
8
8
|
Project-URL: Repository, https://github.com/rhnfzl/SqueakyCleanText
|
|
9
9
|
Project-URL: Issues, https://github.com/rhnfzl/SqueakyCleanText/issues
|
|
@@ -22,7 +22,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
-
Classifier:
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
26
26
|
Classifier: Operating System :: OS Independent
|
|
27
27
|
Requires-Python: >=3.11
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
@@ -32,7 +32,6 @@ Requires-Dist: stop-words>=2025.11.4
|
|
|
32
32
|
Requires-Dist: emoji>=2.14
|
|
33
33
|
Requires-Dist: ftfy>=6.3
|
|
34
34
|
Requires-Dist: Unidecode>=1.4
|
|
35
|
-
Requires-Dist: beautifulsoup4>=4.14
|
|
36
35
|
Requires-Dist: onnxruntime>=1.24.2
|
|
37
36
|
Requires-Dist: tokenizers>=0.22.2
|
|
38
37
|
Requires-Dist: huggingface-hub>=1.5.0
|
|
@@ -56,8 +55,6 @@ Provides-Extra: presidio
|
|
|
56
55
|
Requires-Dist: presidio-analyzer>=2.2.360; extra == "presidio"
|
|
57
56
|
Provides-Extra: classify
|
|
58
57
|
Requires-Dist: gliclass>=0.1.16; extra == "classify"
|
|
59
|
-
Provides-Extra: classify-onnx
|
|
60
|
-
Requires-Dist: onnxruntime>=1.24.2; extra == "classify-onnx"
|
|
61
58
|
Provides-Extra: all-ner
|
|
62
59
|
Requires-Dist: torch>=2.6.0; extra == "all-ner"
|
|
63
60
|
Requires-Dist: transformers>=4.48; extra == "all-ner"
|
|
@@ -73,6 +70,11 @@ Requires-Dist: rapidfuzz>=3.12; extra == "dev"
|
|
|
73
70
|
Provides-Extra: test
|
|
74
71
|
Requires-Dist: coverage>=7.8; extra == "test"
|
|
75
72
|
Requires-Dist: pytest-cov>=6.0; extra == "test"
|
|
73
|
+
Provides-Extra: mcp
|
|
74
|
+
Requires-Dist: fastmcp>=4.0.5; extra == "mcp"
|
|
75
|
+
Provides-Extra: ocr
|
|
76
|
+
Requires-Dist: pillow>=12.3.0; extra == "ocr"
|
|
77
|
+
Requires-Dist: pytesseract>=0.3.13; extra == "ocr"
|
|
76
78
|
Dynamic: license-file
|
|
77
79
|
|
|
78
80
|
<div align="center">
|
|
@@ -82,7 +84,7 @@ Dynamic: license-file
|
|
|
82
84
|
[](https://pypi.org/project/squeakycleantext/)
|
|
83
85
|
[](https://pypistats.org/packages/squeakycleantext)
|
|
84
86
|
[](https://github.com/rhnfzl/SqueakyCleanText/actions/workflows/python-package.yml)
|
|
85
|
-
[](https://pypi.org/project/squeakycleantext/)
|
|
87
|
+
[](https://pypi.org/project/squeakycleantext/)
|
|
86
88
|
[](LICENSE)
|
|
87
89
|
|
|
88
90
|
A comprehensive text cleaning and preprocessing pipeline for machine learning and NLP tasks.
|
|
@@ -179,6 +181,8 @@ The base install uses **ONNX Runtime** for NER inference - no PyTorch or Transfo
|
|
|
179
181
|
| Synthetic | `pip install SqueakyCleanText[synthetic]` | Faker-based synthetic replacement (realistic fake values instead of `<TAG>` tokens) |
|
|
180
182
|
| Presidio | `pip install SqueakyCleanText[presidio]` | Presidio-analyzer for `presidio_gliner` backend |
|
|
181
183
|
| Classify | `pip install SqueakyCleanText[classify]` | GLiClass document-level pre-classification |
|
|
184
|
+
| MCP | `pip install SqueakyCleanText[mcp]` | FastMCP server with text and JSON cleaning tools |
|
|
185
|
+
| OCR | `pip install SqueakyCleanText[ocr]` | Pillow image redaction and Tesseract OCR adapter |
|
|
182
186
|
| All NER | `pip install SqueakyCleanText[all-ner]` | All NER backends combined |
|
|
183
187
|
| Development | `pip install SqueakyCleanText[dev]` | Testing and linting tools |
|
|
184
188
|
|
|
@@ -653,6 +657,116 @@ new_cfg = dataclasses.replace(cfg, check_ner_process=False)
|
|
|
653
657
|
|
|
654
658
|
</details>
|
|
655
659
|
|
|
660
|
+
## Privacy Engine
|
|
661
|
+
|
|
662
|
+
Applications can apply versioned policy rules and inspect each decision.
|
|
663
|
+
This makes privacy behavior testable across services, datasets, and model upgrades.
|
|
664
|
+
|
|
665
|
+
```python
|
|
666
|
+
from sct import EntityRule, PrivacyPolicy, TextCleaner, TextCleanerConfig
|
|
667
|
+
|
|
668
|
+
policy = PrivacyPolicy(
|
|
669
|
+
name="support-export",
|
|
670
|
+
version="1",
|
|
671
|
+
rules={
|
|
672
|
+
"PERSON": EntityRule(action="redact", min_score=0.8),
|
|
673
|
+
"ORGANISATION": EntityRule(action="keep"),
|
|
674
|
+
},
|
|
675
|
+
allowlist=frozenset({"Jane Public"}),
|
|
676
|
+
)
|
|
677
|
+
|
|
678
|
+
cleaner = TextCleaner(
|
|
679
|
+
cfg=TextCleanerConfig(ner_mode="pii"),
|
|
680
|
+
privacy_policy=policy,
|
|
681
|
+
include_entities=True,
|
|
682
|
+
)
|
|
683
|
+
result = cleaner.process("Contact Maria Chen for help.")
|
|
684
|
+
|
|
685
|
+
print(result.metadata["findings"])
|
|
686
|
+
print(result.metadata["detector"])
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
Reversible output is pseudonymized personal data. Anyone with the token map can
|
|
690
|
+
restore the source values. Keep token maps outside logs and cleaned datasets.
|
|
691
|
+
|
|
692
|
+
Use a `TokenStore` implementation to keep maps behind opaque references:
|
|
693
|
+
|
|
694
|
+
```python
|
|
695
|
+
from sct import InMemoryTokenStore, TextCleaner, TextCleanerConfig
|
|
696
|
+
|
|
697
|
+
store = InMemoryTokenStore()
|
|
698
|
+
cleaner = TextCleaner(
|
|
699
|
+
cfg=TextCleanerConfig(replacement_mode="reversible"),
|
|
700
|
+
token_store=store,
|
|
701
|
+
)
|
|
702
|
+
result = cleaner.process("Maria lives in Utrecht.")
|
|
703
|
+
reference = result.metadata["anon_map_reference"]
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
`InMemoryTokenStore` supports tests and short sessions. Production systems
|
|
707
|
+
should implement `TokenStore` with encryption, access control, expiry, and audit logs.
|
|
708
|
+
|
|
709
|
+
### Boundary adapters
|
|
710
|
+
|
|
711
|
+
The base package includes JSON, DataFrame, retrieval, command-line, and streaming adapters:
|
|
712
|
+
|
|
713
|
+
```python
|
|
714
|
+
from sct import RAGChunk, process_json, process_rag_chunks
|
|
715
|
+
|
|
716
|
+
cleaned_json = process_json(cleaner, {"message": "Email a@example.com"})
|
|
717
|
+
cleaned_chunks = process_rag_chunks(
|
|
718
|
+
cleaner,
|
|
719
|
+
[RAGChunk(id="1", text="Call +1-202-555-0147", metadata={})],
|
|
720
|
+
)
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
```sh
|
|
724
|
+
printf 'Email maria@example.com' | sct-clean --no-ner
|
|
725
|
+
printf 'Email maria@example.com' | sct-clean --no-ner \
|
|
726
|
+
--replacement-mode reversible --token-map tokens.json
|
|
727
|
+
pip install 'SqueakyCleanText[mcp]'
|
|
728
|
+
sct-mcp
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
`BufferedStreamingRedactor` holds a full document for cross-chunk NER safety.
|
|
732
|
+
`WindowedStreamingRedactor` provides bounded latency for contact tokens.
|
|
733
|
+
|
|
734
|
+
The OCR adapter accepts any `OCRProvider`. The included Tesseract provider also
|
|
735
|
+
needs a local Tesseract executable. Browser export writes an ONNX Runtime Web
|
|
736
|
+
manifest, but it does not copy model files or Python language detection.
|
|
737
|
+
|
|
738
|
+
Corpus owners can call `assess_reidentification_risk` to measure k-anonymity
|
|
739
|
+
for selected quasi-identifiers. Reports contain counts only, not source values.
|
|
740
|
+
|
|
741
|
+
## PII Evaluation
|
|
742
|
+
|
|
743
|
+
Model changes need ground-truth privacy evaluation, not only backend agreement.
|
|
744
|
+
The evaluation harness reports exact entity metrics by label, language, domain,
|
|
745
|
+
and named slice.
|
|
746
|
+
|
|
747
|
+
```sh
|
|
748
|
+
python -m scripts.evaluate_pii \
|
|
749
|
+
--dataset evaluation/pii_starter.jsonl \
|
|
750
|
+
--predictions path/to/model-predictions.jsonl \
|
|
751
|
+
--model model-name-and-revision \
|
|
752
|
+
--output evaluation/results/model-name.json
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
The included starter corpus is synthetic and only checks the evaluation path.
|
|
756
|
+
See [`evaluation/README.md`](evaluation/README.md) for schemas and release rules.
|
|
757
|
+
|
|
758
|
+
Pinned candidates live in `sct.model_candidates`. Run one candidate with:
|
|
759
|
+
|
|
760
|
+
```sh
|
|
761
|
+
python -m scripts.benchmark_models \
|
|
762
|
+
--dataset evaluation/pii_starter.jsonl \
|
|
763
|
+
--candidate gliner2-pii \
|
|
764
|
+
--output evaluation/results/gliner2-pii.json
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
Published third-party results are reference data only. `assess_candidate`
|
|
768
|
+
requires local recall, exact-span F1, latency, and ONNX parity before adoption.
|
|
769
|
+
|
|
656
770
|
## Architecture
|
|
657
771
|
|
|
658
772
|
SqueakyCleanText processes text through a configurable pipeline of sequential steps:
|
|
@@ -690,6 +804,23 @@ Each step is toggled by a `TextCleanerConfig` field. The pipeline is built once
|
|
|
690
804
|
|
|
691
805
|
## What's New
|
|
692
806
|
|
|
807
|
+
**v0.7.0**
|
|
808
|
+
- **Privacy policies**: Apply versioned entity rules, allowlists, thresholds, and redaction actions.
|
|
809
|
+
- **Structured audit findings**: Inspect entity decisions, detector backends, and pinned model revisions.
|
|
810
|
+
- **Safer reversible processing**: Restore contact values and keep token maps behind an optional `TokenStore`.
|
|
811
|
+
- **Boundary adapters**: Clean JSON, DataFrame-like objects, RAG chunks, standard input, and MCP tool requests.
|
|
812
|
+
- **Privacy evaluation**: Score exact PII spans by label, language, domain, and custom slice.
|
|
813
|
+
- **Model adoption gates**: Compare pinned candidates using recall, F1, latency, and ONNX parity.
|
|
814
|
+
- **Extended media support**: Redact OCR regions, process bounded streams, and export browser deployment manifests.
|
|
815
|
+
- **Corpus risk indicators**: Measure k-anonymity for user-selected quasi-identifiers.
|
|
816
|
+
- **Supply-chain improvements**: Pin model revisions, publish through PyPI Trusted Publishing, and ship standard lockfiles.
|
|
817
|
+
- **Python 3.14**: Added CI coverage alongside Python 3.11 through 3.13.
|
|
818
|
+
|
|
819
|
+
Migration notes:
|
|
820
|
+
- `gliclass_onnx=True` now raises an error because the upstream package has no native ONNX loader.
|
|
821
|
+
- HTML processing now honors `replace_with_html` instead of silently stripping tags.
|
|
822
|
+
- Structured adapters reject reversible mode unless each token map can be retained safely.
|
|
823
|
+
|
|
693
824
|
**v0.6.0**
|
|
694
825
|
- **PII detection mode** (`ner_mode='pii'`): auto-configures GLiNER with 60+ PII entity labels (personal, financial, healthcare, identity, digital)
|
|
695
826
|
- **Synthetic replacement** (`replacement_mode='synthetic'`): Faker-generated realistic values instead of `<TAG>` placeholders, with per-document consistency
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://pypi.org/project/squeakycleantext/)
|
|
6
6
|
[](https://pypistats.org/packages/squeakycleantext)
|
|
7
7
|
[](https://github.com/rhnfzl/SqueakyCleanText/actions/workflows/python-package.yml)
|
|
8
|
-
[](https://pypi.org/project/squeakycleantext/)
|
|
8
|
+
[](https://pypi.org/project/squeakycleantext/)
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
|
|
11
11
|
A comprehensive text cleaning and preprocessing pipeline for machine learning and NLP tasks.
|
|
@@ -102,6 +102,8 @@ The base install uses **ONNX Runtime** for NER inference - no PyTorch or Transfo
|
|
|
102
102
|
| Synthetic | `pip install SqueakyCleanText[synthetic]` | Faker-based synthetic replacement (realistic fake values instead of `<TAG>` tokens) |
|
|
103
103
|
| Presidio | `pip install SqueakyCleanText[presidio]` | Presidio-analyzer for `presidio_gliner` backend |
|
|
104
104
|
| Classify | `pip install SqueakyCleanText[classify]` | GLiClass document-level pre-classification |
|
|
105
|
+
| MCP | `pip install SqueakyCleanText[mcp]` | FastMCP server with text and JSON cleaning tools |
|
|
106
|
+
| OCR | `pip install SqueakyCleanText[ocr]` | Pillow image redaction and Tesseract OCR adapter |
|
|
105
107
|
| All NER | `pip install SqueakyCleanText[all-ner]` | All NER backends combined |
|
|
106
108
|
| Development | `pip install SqueakyCleanText[dev]` | Testing and linting tools |
|
|
107
109
|
|
|
@@ -576,6 +578,116 @@ new_cfg = dataclasses.replace(cfg, check_ner_process=False)
|
|
|
576
578
|
|
|
577
579
|
</details>
|
|
578
580
|
|
|
581
|
+
## Privacy Engine
|
|
582
|
+
|
|
583
|
+
Applications can apply versioned policy rules and inspect each decision.
|
|
584
|
+
This makes privacy behavior testable across services, datasets, and model upgrades.
|
|
585
|
+
|
|
586
|
+
```python
|
|
587
|
+
from sct import EntityRule, PrivacyPolicy, TextCleaner, TextCleanerConfig
|
|
588
|
+
|
|
589
|
+
policy = PrivacyPolicy(
|
|
590
|
+
name="support-export",
|
|
591
|
+
version="1",
|
|
592
|
+
rules={
|
|
593
|
+
"PERSON": EntityRule(action="redact", min_score=0.8),
|
|
594
|
+
"ORGANISATION": EntityRule(action="keep"),
|
|
595
|
+
},
|
|
596
|
+
allowlist=frozenset({"Jane Public"}),
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
cleaner = TextCleaner(
|
|
600
|
+
cfg=TextCleanerConfig(ner_mode="pii"),
|
|
601
|
+
privacy_policy=policy,
|
|
602
|
+
include_entities=True,
|
|
603
|
+
)
|
|
604
|
+
result = cleaner.process("Contact Maria Chen for help.")
|
|
605
|
+
|
|
606
|
+
print(result.metadata["findings"])
|
|
607
|
+
print(result.metadata["detector"])
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
Reversible output is pseudonymized personal data. Anyone with the token map can
|
|
611
|
+
restore the source values. Keep token maps outside logs and cleaned datasets.
|
|
612
|
+
|
|
613
|
+
Use a `TokenStore` implementation to keep maps behind opaque references:
|
|
614
|
+
|
|
615
|
+
```python
|
|
616
|
+
from sct import InMemoryTokenStore, TextCleaner, TextCleanerConfig
|
|
617
|
+
|
|
618
|
+
store = InMemoryTokenStore()
|
|
619
|
+
cleaner = TextCleaner(
|
|
620
|
+
cfg=TextCleanerConfig(replacement_mode="reversible"),
|
|
621
|
+
token_store=store,
|
|
622
|
+
)
|
|
623
|
+
result = cleaner.process("Maria lives in Utrecht.")
|
|
624
|
+
reference = result.metadata["anon_map_reference"]
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
`InMemoryTokenStore` supports tests and short sessions. Production systems
|
|
628
|
+
should implement `TokenStore` with encryption, access control, expiry, and audit logs.
|
|
629
|
+
|
|
630
|
+
### Boundary adapters
|
|
631
|
+
|
|
632
|
+
The base package includes JSON, DataFrame, retrieval, command-line, and streaming adapters:
|
|
633
|
+
|
|
634
|
+
```python
|
|
635
|
+
from sct import RAGChunk, process_json, process_rag_chunks
|
|
636
|
+
|
|
637
|
+
cleaned_json = process_json(cleaner, {"message": "Email a@example.com"})
|
|
638
|
+
cleaned_chunks = process_rag_chunks(
|
|
639
|
+
cleaner,
|
|
640
|
+
[RAGChunk(id="1", text="Call +1-202-555-0147", metadata={})],
|
|
641
|
+
)
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
```sh
|
|
645
|
+
printf 'Email maria@example.com' | sct-clean --no-ner
|
|
646
|
+
printf 'Email maria@example.com' | sct-clean --no-ner \
|
|
647
|
+
--replacement-mode reversible --token-map tokens.json
|
|
648
|
+
pip install 'SqueakyCleanText[mcp]'
|
|
649
|
+
sct-mcp
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
`BufferedStreamingRedactor` holds a full document for cross-chunk NER safety.
|
|
653
|
+
`WindowedStreamingRedactor` provides bounded latency for contact tokens.
|
|
654
|
+
|
|
655
|
+
The OCR adapter accepts any `OCRProvider`. The included Tesseract provider also
|
|
656
|
+
needs a local Tesseract executable. Browser export writes an ONNX Runtime Web
|
|
657
|
+
manifest, but it does not copy model files or Python language detection.
|
|
658
|
+
|
|
659
|
+
Corpus owners can call `assess_reidentification_risk` to measure k-anonymity
|
|
660
|
+
for selected quasi-identifiers. Reports contain counts only, not source values.
|
|
661
|
+
|
|
662
|
+
## PII Evaluation
|
|
663
|
+
|
|
664
|
+
Model changes need ground-truth privacy evaluation, not only backend agreement.
|
|
665
|
+
The evaluation harness reports exact entity metrics by label, language, domain,
|
|
666
|
+
and named slice.
|
|
667
|
+
|
|
668
|
+
```sh
|
|
669
|
+
python -m scripts.evaluate_pii \
|
|
670
|
+
--dataset evaluation/pii_starter.jsonl \
|
|
671
|
+
--predictions path/to/model-predictions.jsonl \
|
|
672
|
+
--model model-name-and-revision \
|
|
673
|
+
--output evaluation/results/model-name.json
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
The included starter corpus is synthetic and only checks the evaluation path.
|
|
677
|
+
See [`evaluation/README.md`](evaluation/README.md) for schemas and release rules.
|
|
678
|
+
|
|
679
|
+
Pinned candidates live in `sct.model_candidates`. Run one candidate with:
|
|
680
|
+
|
|
681
|
+
```sh
|
|
682
|
+
python -m scripts.benchmark_models \
|
|
683
|
+
--dataset evaluation/pii_starter.jsonl \
|
|
684
|
+
--candidate gliner2-pii \
|
|
685
|
+
--output evaluation/results/gliner2-pii.json
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
Published third-party results are reference data only. `assess_candidate`
|
|
689
|
+
requires local recall, exact-span F1, latency, and ONNX parity before adoption.
|
|
690
|
+
|
|
579
691
|
## Architecture
|
|
580
692
|
|
|
581
693
|
SqueakyCleanText processes text through a configurable pipeline of sequential steps:
|
|
@@ -613,6 +725,23 @@ Each step is toggled by a `TextCleanerConfig` field. The pipeline is built once
|
|
|
613
725
|
|
|
614
726
|
## What's New
|
|
615
727
|
|
|
728
|
+
**v0.7.0**
|
|
729
|
+
- **Privacy policies**: Apply versioned entity rules, allowlists, thresholds, and redaction actions.
|
|
730
|
+
- **Structured audit findings**: Inspect entity decisions, detector backends, and pinned model revisions.
|
|
731
|
+
- **Safer reversible processing**: Restore contact values and keep token maps behind an optional `TokenStore`.
|
|
732
|
+
- **Boundary adapters**: Clean JSON, DataFrame-like objects, RAG chunks, standard input, and MCP tool requests.
|
|
733
|
+
- **Privacy evaluation**: Score exact PII spans by label, language, domain, and custom slice.
|
|
734
|
+
- **Model adoption gates**: Compare pinned candidates using recall, F1, latency, and ONNX parity.
|
|
735
|
+
- **Extended media support**: Redact OCR regions, process bounded streams, and export browser deployment manifests.
|
|
736
|
+
- **Corpus risk indicators**: Measure k-anonymity for user-selected quasi-identifiers.
|
|
737
|
+
- **Supply-chain improvements**: Pin model revisions, publish through PyPI Trusted Publishing, and ship standard lockfiles.
|
|
738
|
+
- **Python 3.14**: Added CI coverage alongside Python 3.11 through 3.13.
|
|
739
|
+
|
|
740
|
+
Migration notes:
|
|
741
|
+
- `gliclass_onnx=True` now raises an error because the upstream package has no native ONNX loader.
|
|
742
|
+
- HTML processing now honors `replace_with_html` instead of silently stripping tags.
|
|
743
|
+
- Structured adapters reject reversible mode unless each token map can be retained safely.
|
|
744
|
+
|
|
616
745
|
**v0.6.0**
|
|
617
746
|
- **PII detection mode** (`ner_mode='pii'`): auto-configures GLiNER with 60+ PII entity labels (personal, financial, healthcare, identity, digital)
|
|
618
747
|
- **Synthetic replacement** (`replacement_mode='synthetic'`): Faker-generated realistic values instead of `<TAG>` placeholders, with per-document consistency
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SqueakyCleanText
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
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
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/rhnfzl/SqueakyCleanText
|
|
8
8
|
Project-URL: Repository, https://github.com/rhnfzl/SqueakyCleanText
|
|
9
9
|
Project-URL: Issues, https://github.com/rhnfzl/SqueakyCleanText/issues
|
|
@@ -22,7 +22,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
-
Classifier:
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
26
26
|
Classifier: Operating System :: OS Independent
|
|
27
27
|
Requires-Python: >=3.11
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
@@ -32,7 +32,6 @@ Requires-Dist: stop-words>=2025.11.4
|
|
|
32
32
|
Requires-Dist: emoji>=2.14
|
|
33
33
|
Requires-Dist: ftfy>=6.3
|
|
34
34
|
Requires-Dist: Unidecode>=1.4
|
|
35
|
-
Requires-Dist: beautifulsoup4>=4.14
|
|
36
35
|
Requires-Dist: onnxruntime>=1.24.2
|
|
37
36
|
Requires-Dist: tokenizers>=0.22.2
|
|
38
37
|
Requires-Dist: huggingface-hub>=1.5.0
|
|
@@ -56,8 +55,6 @@ Provides-Extra: presidio
|
|
|
56
55
|
Requires-Dist: presidio-analyzer>=2.2.360; extra == "presidio"
|
|
57
56
|
Provides-Extra: classify
|
|
58
57
|
Requires-Dist: gliclass>=0.1.16; extra == "classify"
|
|
59
|
-
Provides-Extra: classify-onnx
|
|
60
|
-
Requires-Dist: onnxruntime>=1.24.2; extra == "classify-onnx"
|
|
61
58
|
Provides-Extra: all-ner
|
|
62
59
|
Requires-Dist: torch>=2.6.0; extra == "all-ner"
|
|
63
60
|
Requires-Dist: transformers>=4.48; extra == "all-ner"
|
|
@@ -73,6 +70,11 @@ Requires-Dist: rapidfuzz>=3.12; extra == "dev"
|
|
|
73
70
|
Provides-Extra: test
|
|
74
71
|
Requires-Dist: coverage>=7.8; extra == "test"
|
|
75
72
|
Requires-Dist: pytest-cov>=6.0; extra == "test"
|
|
73
|
+
Provides-Extra: mcp
|
|
74
|
+
Requires-Dist: fastmcp>=4.0.5; extra == "mcp"
|
|
75
|
+
Provides-Extra: ocr
|
|
76
|
+
Requires-Dist: pillow>=12.3.0; extra == "ocr"
|
|
77
|
+
Requires-Dist: pytesseract>=0.3.13; extra == "ocr"
|
|
76
78
|
Dynamic: license-file
|
|
77
79
|
|
|
78
80
|
<div align="center">
|
|
@@ -82,7 +84,7 @@ Dynamic: license-file
|
|
|
82
84
|
[](https://pypi.org/project/squeakycleantext/)
|
|
83
85
|
[](https://pypistats.org/packages/squeakycleantext)
|
|
84
86
|
[](https://github.com/rhnfzl/SqueakyCleanText/actions/workflows/python-package.yml)
|
|
85
|
-
[](https://pypi.org/project/squeakycleantext/)
|
|
87
|
+
[](https://pypi.org/project/squeakycleantext/)
|
|
86
88
|
[](LICENSE)
|
|
87
89
|
|
|
88
90
|
A comprehensive text cleaning and preprocessing pipeline for machine learning and NLP tasks.
|
|
@@ -179,6 +181,8 @@ The base install uses **ONNX Runtime** for NER inference - no PyTorch or Transfo
|
|
|
179
181
|
| Synthetic | `pip install SqueakyCleanText[synthetic]` | Faker-based synthetic replacement (realistic fake values instead of `<TAG>` tokens) |
|
|
180
182
|
| Presidio | `pip install SqueakyCleanText[presidio]` | Presidio-analyzer for `presidio_gliner` backend |
|
|
181
183
|
| Classify | `pip install SqueakyCleanText[classify]` | GLiClass document-level pre-classification |
|
|
184
|
+
| MCP | `pip install SqueakyCleanText[mcp]` | FastMCP server with text and JSON cleaning tools |
|
|
185
|
+
| OCR | `pip install SqueakyCleanText[ocr]` | Pillow image redaction and Tesseract OCR adapter |
|
|
182
186
|
| All NER | `pip install SqueakyCleanText[all-ner]` | All NER backends combined |
|
|
183
187
|
| Development | `pip install SqueakyCleanText[dev]` | Testing and linting tools |
|
|
184
188
|
|
|
@@ -653,6 +657,116 @@ new_cfg = dataclasses.replace(cfg, check_ner_process=False)
|
|
|
653
657
|
|
|
654
658
|
</details>
|
|
655
659
|
|
|
660
|
+
## Privacy Engine
|
|
661
|
+
|
|
662
|
+
Applications can apply versioned policy rules and inspect each decision.
|
|
663
|
+
This makes privacy behavior testable across services, datasets, and model upgrades.
|
|
664
|
+
|
|
665
|
+
```python
|
|
666
|
+
from sct import EntityRule, PrivacyPolicy, TextCleaner, TextCleanerConfig
|
|
667
|
+
|
|
668
|
+
policy = PrivacyPolicy(
|
|
669
|
+
name="support-export",
|
|
670
|
+
version="1",
|
|
671
|
+
rules={
|
|
672
|
+
"PERSON": EntityRule(action="redact", min_score=0.8),
|
|
673
|
+
"ORGANISATION": EntityRule(action="keep"),
|
|
674
|
+
},
|
|
675
|
+
allowlist=frozenset({"Jane Public"}),
|
|
676
|
+
)
|
|
677
|
+
|
|
678
|
+
cleaner = TextCleaner(
|
|
679
|
+
cfg=TextCleanerConfig(ner_mode="pii"),
|
|
680
|
+
privacy_policy=policy,
|
|
681
|
+
include_entities=True,
|
|
682
|
+
)
|
|
683
|
+
result = cleaner.process("Contact Maria Chen for help.")
|
|
684
|
+
|
|
685
|
+
print(result.metadata["findings"])
|
|
686
|
+
print(result.metadata["detector"])
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
Reversible output is pseudonymized personal data. Anyone with the token map can
|
|
690
|
+
restore the source values. Keep token maps outside logs and cleaned datasets.
|
|
691
|
+
|
|
692
|
+
Use a `TokenStore` implementation to keep maps behind opaque references:
|
|
693
|
+
|
|
694
|
+
```python
|
|
695
|
+
from sct import InMemoryTokenStore, TextCleaner, TextCleanerConfig
|
|
696
|
+
|
|
697
|
+
store = InMemoryTokenStore()
|
|
698
|
+
cleaner = TextCleaner(
|
|
699
|
+
cfg=TextCleanerConfig(replacement_mode="reversible"),
|
|
700
|
+
token_store=store,
|
|
701
|
+
)
|
|
702
|
+
result = cleaner.process("Maria lives in Utrecht.")
|
|
703
|
+
reference = result.metadata["anon_map_reference"]
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
`InMemoryTokenStore` supports tests and short sessions. Production systems
|
|
707
|
+
should implement `TokenStore` with encryption, access control, expiry, and audit logs.
|
|
708
|
+
|
|
709
|
+
### Boundary adapters
|
|
710
|
+
|
|
711
|
+
The base package includes JSON, DataFrame, retrieval, command-line, and streaming adapters:
|
|
712
|
+
|
|
713
|
+
```python
|
|
714
|
+
from sct import RAGChunk, process_json, process_rag_chunks
|
|
715
|
+
|
|
716
|
+
cleaned_json = process_json(cleaner, {"message": "Email a@example.com"})
|
|
717
|
+
cleaned_chunks = process_rag_chunks(
|
|
718
|
+
cleaner,
|
|
719
|
+
[RAGChunk(id="1", text="Call +1-202-555-0147", metadata={})],
|
|
720
|
+
)
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
```sh
|
|
724
|
+
printf 'Email maria@example.com' | sct-clean --no-ner
|
|
725
|
+
printf 'Email maria@example.com' | sct-clean --no-ner \
|
|
726
|
+
--replacement-mode reversible --token-map tokens.json
|
|
727
|
+
pip install 'SqueakyCleanText[mcp]'
|
|
728
|
+
sct-mcp
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
`BufferedStreamingRedactor` holds a full document for cross-chunk NER safety.
|
|
732
|
+
`WindowedStreamingRedactor` provides bounded latency for contact tokens.
|
|
733
|
+
|
|
734
|
+
The OCR adapter accepts any `OCRProvider`. The included Tesseract provider also
|
|
735
|
+
needs a local Tesseract executable. Browser export writes an ONNX Runtime Web
|
|
736
|
+
manifest, but it does not copy model files or Python language detection.
|
|
737
|
+
|
|
738
|
+
Corpus owners can call `assess_reidentification_risk` to measure k-anonymity
|
|
739
|
+
for selected quasi-identifiers. Reports contain counts only, not source values.
|
|
740
|
+
|
|
741
|
+
## PII Evaluation
|
|
742
|
+
|
|
743
|
+
Model changes need ground-truth privacy evaluation, not only backend agreement.
|
|
744
|
+
The evaluation harness reports exact entity metrics by label, language, domain,
|
|
745
|
+
and named slice.
|
|
746
|
+
|
|
747
|
+
```sh
|
|
748
|
+
python -m scripts.evaluate_pii \
|
|
749
|
+
--dataset evaluation/pii_starter.jsonl \
|
|
750
|
+
--predictions path/to/model-predictions.jsonl \
|
|
751
|
+
--model model-name-and-revision \
|
|
752
|
+
--output evaluation/results/model-name.json
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
The included starter corpus is synthetic and only checks the evaluation path.
|
|
756
|
+
See [`evaluation/README.md`](evaluation/README.md) for schemas and release rules.
|
|
757
|
+
|
|
758
|
+
Pinned candidates live in `sct.model_candidates`. Run one candidate with:
|
|
759
|
+
|
|
760
|
+
```sh
|
|
761
|
+
python -m scripts.benchmark_models \
|
|
762
|
+
--dataset evaluation/pii_starter.jsonl \
|
|
763
|
+
--candidate gliner2-pii \
|
|
764
|
+
--output evaluation/results/gliner2-pii.json
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
Published third-party results are reference data only. `assess_candidate`
|
|
768
|
+
requires local recall, exact-span F1, latency, and ONNX parity before adoption.
|
|
769
|
+
|
|
656
770
|
## Architecture
|
|
657
771
|
|
|
658
772
|
SqueakyCleanText processes text through a configurable pipeline of sequential steps:
|
|
@@ -690,6 +804,23 @@ Each step is toggled by a `TextCleanerConfig` field. The pipeline is built once
|
|
|
690
804
|
|
|
691
805
|
## What's New
|
|
692
806
|
|
|
807
|
+
**v0.7.0**
|
|
808
|
+
- **Privacy policies**: Apply versioned entity rules, allowlists, thresholds, and redaction actions.
|
|
809
|
+
- **Structured audit findings**: Inspect entity decisions, detector backends, and pinned model revisions.
|
|
810
|
+
- **Safer reversible processing**: Restore contact values and keep token maps behind an optional `TokenStore`.
|
|
811
|
+
- **Boundary adapters**: Clean JSON, DataFrame-like objects, RAG chunks, standard input, and MCP tool requests.
|
|
812
|
+
- **Privacy evaluation**: Score exact PII spans by label, language, domain, and custom slice.
|
|
813
|
+
- **Model adoption gates**: Compare pinned candidates using recall, F1, latency, and ONNX parity.
|
|
814
|
+
- **Extended media support**: Redact OCR regions, process bounded streams, and export browser deployment manifests.
|
|
815
|
+
- **Corpus risk indicators**: Measure k-anonymity for user-selected quasi-identifiers.
|
|
816
|
+
- **Supply-chain improvements**: Pin model revisions, publish through PyPI Trusted Publishing, and ship standard lockfiles.
|
|
817
|
+
- **Python 3.14**: Added CI coverage alongside Python 3.11 through 3.13.
|
|
818
|
+
|
|
819
|
+
Migration notes:
|
|
820
|
+
- `gliclass_onnx=True` now raises an error because the upstream package has no native ONNX loader.
|
|
821
|
+
- HTML processing now honors `replace_with_html` instead of silently stripping tags.
|
|
822
|
+
- Structured adapters reject reversible mode unless each token map can be retained safely.
|
|
823
|
+
|
|
693
824
|
**v0.6.0**
|
|
694
825
|
- **PII detection mode** (`ner_mode='pii'`): auto-configures GLiNER with 60+ PII entity labels (personal, financial, healthcare, identity, digital)
|
|
695
826
|
- **Synthetic replacement** (`replacement_mode='synthetic'`): Faker-generated realistic values instead of `<TAG>` placeholders, with per-document consistency
|
|
@@ -5,11 +5,23 @@ setup.py
|
|
|
5
5
|
SqueakyCleanText.egg-info/PKG-INFO
|
|
6
6
|
SqueakyCleanText.egg-info/SOURCES.txt
|
|
7
7
|
SqueakyCleanText.egg-info/dependency_links.txt
|
|
8
|
+
SqueakyCleanText.egg-info/entry_points.txt
|
|
8
9
|
SqueakyCleanText.egg-info/requires.txt
|
|
9
10
|
SqueakyCleanText.egg-info/top_level.txt
|
|
10
11
|
sct/__init__.py
|
|
12
|
+
sct/adapters.py
|
|
13
|
+
sct/browser.py
|
|
14
|
+
sct/cli.py
|
|
11
15
|
sct/config.py
|
|
16
|
+
sct/evaluation.py
|
|
17
|
+
sct/mcp_server.py
|
|
18
|
+
sct/model_benchmark.py
|
|
19
|
+
sct/model_candidates.py
|
|
20
|
+
sct/ocr.py
|
|
21
|
+
sct/privacy.py
|
|
22
|
+
sct/risk.py
|
|
12
23
|
sct/sct.py
|
|
24
|
+
sct/streaming.py
|
|
13
25
|
sct/utils/__init__.py
|
|
14
26
|
sct/utils/anonymization_map.py
|
|
15
27
|
sct/utils/constants.py
|
|
@@ -26,5 +38,16 @@ sct/utils/special.py
|
|
|
26
38
|
sct/utils/stopwords.py
|
|
27
39
|
sct/utils/synthetic.py
|
|
28
40
|
sct/utils/torch_pipeline.py
|
|
41
|
+
tests/test_adapters.py
|
|
42
|
+
tests/test_browser.py
|
|
43
|
+
tests/test_cli.py
|
|
44
|
+
tests/test_contracts.py
|
|
45
|
+
tests/test_evaluation.py
|
|
29
46
|
tests/test_functional.py
|
|
30
|
-
tests/
|
|
47
|
+
tests/test_mcp_server.py
|
|
48
|
+
tests/test_model_benchmarks.py
|
|
49
|
+
tests/test_ocr.py
|
|
50
|
+
tests/test_privacy.py
|
|
51
|
+
tests/test_risk.py
|
|
52
|
+
tests/test_sct.py
|
|
53
|
+
tests/test_streaming.py
|
|
@@ -3,7 +3,6 @@ stop-words>=2025.11.4
|
|
|
3
3
|
emoji>=2.14
|
|
4
4
|
ftfy>=6.3
|
|
5
5
|
Unidecode>=1.4
|
|
6
|
-
beautifulsoup4>=4.14
|
|
7
6
|
onnxruntime>=1.24.2
|
|
8
7
|
tokenizers>=0.22.2
|
|
9
8
|
huggingface-hub>=1.5.0
|
|
@@ -20,9 +19,6 @@ gliner2<2.0,>=1.0
|
|
|
20
19
|
[classify]
|
|
21
20
|
gliclass>=0.1.16
|
|
22
21
|
|
|
23
|
-
[classify-onnx]
|
|
24
|
-
onnxruntime>=1.24.2
|
|
25
|
-
|
|
26
22
|
[dev]
|
|
27
23
|
hypothesis>=6.130
|
|
28
24
|
faker>=33.0
|
|
@@ -43,6 +39,13 @@ gliner2<2.0,>=1.0
|
|
|
43
39
|
[gpu]
|
|
44
40
|
onnxruntime-gpu>=1.24.2
|
|
45
41
|
|
|
42
|
+
[mcp]
|
|
43
|
+
fastmcp>=4.0.5
|
|
44
|
+
|
|
45
|
+
[ocr]
|
|
46
|
+
pillow>=12.3.0
|
|
47
|
+
pytesseract>=0.3.13
|
|
48
|
+
|
|
46
49
|
[presidio]
|
|
47
50
|
presidio-analyzer>=2.2.360
|
|
48
51
|
|