Skip to main content

Toolkit for Obfuscating Text Through Transformations.

Project description

Powered by spaCy English German

A package for applying transformations to text for creating derived formats, intended for preventing reconstruction of the original data. This can be applied, for instance, to sensitive training data to prevent its reconstruction while preserving some usefulness of the text in pre-training on primarily encoder-based tasks such as classification and retrieval tasks. Such obfuscated representations are therefore intended to accompany non-sensitive, non-obfuscated data in the pre-training mix where the text's usage would otherwise risk infringing on copyright.

The package natively supports text processing in English and German.

Install

pip install text-mallet

# For obfuscating English, download the English model you want to use 
# The default is the "lg" i.e. large SpaCy model:
python -m spacy download en_core_web_lg

# Or alternatively, download the model for German
python -m spacy download de_core_news_lg

Strategic Obfuscation

The central aim of text obfuscation using this package is to prevent reconstructability. Doing so involves eroding various aspects of text, such as:

  • Word Forms: The exact sequence of characters.
  • Syntactic Features: Morpho-syntactic token properties.
  • Meanings: Core semantic associations.
  • Grammatical Relations: Hierarchical sentence dependency tree structure.
  • Sequence Information: Flat linear sequence boundaries.

Each layer contributes to the discoverability and reconstructibility of the source text. This package provides four main approaches to obfuscation: POS filtering, mutual information filtering, hierarchical scrambling, and bag-of-words. For a more detailed overview of each method, please see the documentation.

Why Obfuscate Text?

When training models for text generation, we typically need all of the content and style of the original, fluent text. However, there are many tasks such as classification, semantic similarity scoring, topic modelling, and so on, where the original text may not be required in its original form to help model performance. There is typically a trove of public-domain data that can be used for model training, but there are still many questions around the usage of copyright-protected data in training. This package offers a route to preserve some of the value of copyrighted texts while hindering their reconstruction, whether that be through training-data reconstruction or model outputs.

The creation of transformed texts that are thus no longer consumable by humans, but still useful for training on specific tasks.

Impact on Performance

While training on transformed text formats can introduce minor performance drops compared to raw text baselines, text-mallett is explicitly designed to accompany non-obfuscated, public-domain collections. Introducing these anonymised, non-human-consumable formats adds proprietary text signals into your pipeline without exposing the original text to model parameters.

Basic Obfuscation

There are multiple general obfuscation approaches to choose from, separated into three general categories:

  • Structural Obfuscation (bag-of-words, hierarchical)
  • Part-of-Speech Filtering
  • Mutual-Information Filtering

Let's start with an example of bag-of-words scrambling.

from tmallet import TMallet

# 1. Define the Obfuscation Configuration
algorithm = "scramble-BoW"
config = {
    "level": "document",
}

# 2. Define Sample Text
sample = "Leipzig is the most populous city in the German state of Saxony. The city has a population of 633,592 residents as of 31 December 2025. It is the eighth-largest city in Germany and is part of the Central German Metropolitan Region. Leipzig is located about 150 km (90 mi) southwest of Berlin, in the southernmost part of the North German Plain (the Leipzig Bay), at the confluence of the White Elster and its tributaries Pleiße and Parthe."

# 3. Load Text Mallet and Obfuscate
tmallet = TMallet(lang="en", prefer_gpu=True)
tmallet.load_obfuscator(algorithm, config)

obfuscated_text_sample = tmallet.obfuscate(sample)
print(obfuscated_text_sample)

Output

southernmost 150 eighth-largest most the (90 Central located Bay), Parthe. mi) in city of German Germany part population the is Plain of populous and as Leipzig the German the the km White its Metropolitan Berlin, and Leipzig in the confluence 2025. of of city It Elster is Region. December tributaries The state Saxony. (the southwest the residents the of city Leipzig German is in is Pleiße of a has at part about of 31 and North 633,592

Obfuscate based on an approximation of 'word importance' Mutual information measures how much information context tells you about a word. Words which are both rare and context-dependant tend to be important to the meaning of a text. We can apply a filter to set upper or lower bounds on such an MI score, filering at the word level.

from tmallet import TMallet

algorithm = "shannon", 
config = {
    "threshold": 9.5,
    "bound": "lower",
    "replacement_mechanism": "default",
    "max_context_length": 128,
}

tmallet = TMallet(lang=lang, prefer_gpu=True)
tmallet.load_obfuscator(algorithm, config)

text = "Data obfuscation is the process of modifying sensitive data in such a way that it is of no or little value to unauthorized intruders while still being usable by software or authorized personnel. Data masking can also be referred as anonymization, or tokenization, depending on different context."
obfuscated = tmallet.obfuscate(text)
print(obfuscated)

Output

_ _ is the _ of _ _ _ in _ a _ that it is of no or little _ to _ _ _ _ _ _ by software or _ _. _ _ can also be referred as _, or _, _ on different _.

If we obfuscate too strongly using mutual information, we'll end up with obfuscated sentences like:

, . . - ., or . the / . the . - –, . -

That's, well, probably not very useful. Ideally, we can find a balance between the obfuscation of some words and inclusion of others. Using the bound as lower instead of upper will preserve those words which tend to be more meaningful in a text. Running the above example again with the lower bound of 9, we get an obfuscation which preserves core semantic value while make the text more difficult to reconstruct:

Data obfuscation _ _ process _ modifying sensitive data _ such _ way _ _ _ _ _ _ _ value _ unauthorized intruders while still being usable _ _ _ authorized personnel _ Data masking _ _ _ _ _ anonymization _ _ tokenization _ depending _ _ context _

Here's an overview of an approximation of pointwise word-level mutual information, i.e. PMI(word; context), over 12,000 tokens taken from 10 random texts in the FineWeb-Edu dataset, for instance. Distribution of Word-Level Mutual Information

Contributions

Contributions are always welcome, this package was primarily developed in conjunction with carrying out research on the potential value of such obfuscation formats in encoder pre-training. Therefore, the package has many ways it could be improved upon and there are likely opportunities for efficiency improvements in particular.

Acknowledgements

Part of this work was conducted within the CORAL project funded by the German Federal Ministry of Research, Technology, and Space (BMFTR) under the grant number 16IS24077A. Responsibility for the content of this publication lies with the authors.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

text_mallet-0.1.3.tar.gz (26.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

text_mallet-0.1.3-py3-none-any.whl (29.3 kB view details)

Uploaded Python 3

File details

Details for the file text_mallet-0.1.3.tar.gz.

File metadata

  • Download URL: text_mallet-0.1.3.tar.gz
  • Upload date:
  • Size: 26.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for text_mallet-0.1.3.tar.gz
Algorithm Hash digest
SHA256 18b4f86cac467dfb4e28a1f8b87b3dab01cde736e65a42311c9e685a66213625
MD5 19ed714af744b57bfeb03026605459a7
BLAKE2b-256 510e455e993c02053c56b0e61c39866b20bd98fb556560d873ca6c44578a1087

See more details on using hashes here.

File details

Details for the file text_mallet-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: text_mallet-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 29.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for text_mallet-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 9f6e67d8754e7dfb7f1b0387077a691b4022cb7a98b2fcfed204cb6a6840b457
MD5 1ac5bc3e9a5e086dffc17480820ded85
BLAKE2b-256 28c3cbb18662437ad379c524502373bfed3cb6525921c73519b5b681cd4e8aab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page