textual-haystack
PII detection, transformation, and entity extraction components for Haystack, powered by Tonic Textual.
Detect sensitive data in documents, extract the raw entities for auditing or custom logic, or synthesize and tokenize PII before ingestion. Drop these components into any Haystack pipeline.
Installation
pip install textual-haystack
Components
| Component | Purpose |
|---|---|
TonicTextualEntityExtractor |
Extract PII entities with type, value, location, and confidence score |
TonicTextualDocumentCleaner |
Synthesize or tokenize PII in document content |
Quick start
export TONIC_TEXTUAL_API_KEY="your-api-key"
Entity extraction
from haystack.dataclasses import Document
from haystack_integrations.components.tonic_textual import (
TonicTextualEntityExtractor,
)
extractor = TonicTextualEntityExtractor()
result = extractor.run(
documents=[Document(content="My name is John Smith and my email is john@example.com")]
)
for entity in TonicTextualEntityExtractor.get_stored_annotations(result["documents"][0]):
print(f"{entity.entity}: {entity.text} (confidence: {entity.score:.2f})")
# NAME_GIVEN: John (confidence: 0.90)
# NAME_FAMILY: Smith (confidence: 0.90)
# EMAIL_ADDRESS: john@example.com (confidence: 0.95)
Document cleaning
from haystack.dataclasses import Document
from haystack_integrations.components.tonic_textual import (
TonicTextualDocumentCleaner,
)
# Synthesize PII with realistic fakes
cleaner = TonicTextualDocumentCleaner(generator_default="Synthesis")
result = cleaner.run(
documents=[Document(content="Contact John Smith at john@example.com")]
)
print(result["documents"][0].content)
# "Contact Maria Chen at maria.chen@gmail.com"
Per-entity control — mix synthesis and tokenization per PII type:
cleaner = TonicTextualDocumentCleaner(
generator_default="Off",
generator_config={
"NAME_GIVEN": "Synthesis",
"NAME_FAMILY": "Synthesis",
"EMAIL_ADDRESS": "Redaction",
},
)
In a pipeline
from haystack import Pipeline
from haystack.dataclasses import Document
from haystack_integrations.components.tonic_textual import (
TonicTextualDocumentCleaner,
TonicTextualEntityExtractor,
)
pipeline = Pipeline()
pipeline.add_component("cleaner", TonicTextualDocumentCleaner(generator_default="Synthesis"))
pipeline.add_component("extractor", TonicTextualEntityExtractor())
pipeline.connect("cleaner", "extractor")
result = pipeline.run({
"cleaner": {
"documents": [
Document(content="Contact Jane Doe at jane@example.com"),
]
}
})
Configuration
Self-hosted deployment:
extractor = TonicTextualEntityExtractor(
base_url="https://textual.your-company.com"
)
Explicit API key:
from haystack.utils.auth import Secret
extractor = TonicTextualEntityExtractor(
api_key=Secret.from_token("your-api-key")
)
Development
# install dependencies
uv sync --group dev --group test --group lint --group typing
# install pre-commit hooks (auto-runs ruff on each commit)
uv tool install pre-commit
pre-commit install
# run unit tests
make test
# run integration tests (requires TONIC_TEXTUAL_API_KEY)
make integration_tests
# lint & format
make lint
make format
License
MIT
Release files for textual-haystack 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| textual_haystack-1.0.0.tar.gz | 268.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| textual_haystack-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 275.9 kB
Release files / textual_haystack-1.0.0.tar.gz
| Download URL | textual_haystack-1.0.0.tar.gz |
|---|---|
| Size | 268.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9f18f40762f38b385799749f1a140b1c48829a1bf013857d5a531f223b8a6cad
|
|
BLAKE2b-256 checksum How to use checksums |
454a14189de8abe4a56c5abcb555dee4f899fc43cb8796efedb7f8193ec4edb9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 19, 2026.
Transparency logRelease files / textual_haystack-1.0.0-py3-none-any.whl
| Download URL | textual_haystack-1.0.0-py3-none-any.whl |
|---|---|
| Size | 7.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c1d87827e84b2a04f4d6eb207aba0df06f1ae641959f3537ca666261e824cc30
|
|
BLAKE2b-256 checksum How to use checksums |
3b89542c60e017d803675f9e8b028e3ffd80e7d8dc02bcd0fc8dba42ff288462
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 19, 2026.
Transparency log