Spaces:
Sleeping
Sleeping
Download src/redactors/mapper.py from ayush678/ghostwriter-api: direct link, hf CLI and curl.
- Browser
- Download file 3.47 kB
-
https://huggingface.co/spaces/ayush678/ghostwriter-api/resolve/main/src/redactors/mapper.py
- Command line
-
hf download hf://spaces/ayush678/ghostwriter-api/src/redactors/mapper.py
-
curl -L -o mapper.py https://huggingface.co/spaces/ayush678/ghostwriter-api/resolve/main/src/redactors/mapper.py
3.47 kB
| import re | |
| import random | |
| from typing import Dict | |
| from faker import Faker | |
| class StatefulMapper: | |
| """ | |
| A stateful mapper that generates consistent fake replacements for PII entities. | |
| It stores the mapping of original_text -> fake_text to ensure that if the same | |
| real entity appears multiple times, it is replaced with the exact same fake entity. | |
| """ | |
| def __init__(self, seed: int = None): | |
| """ | |
| Initializes the StatefulMapper. | |
| Args: | |
| seed: An optional integer seed for the Faker instance to ensure | |
| reproducible replacements across runs. | |
| """ | |
| self.fake = Faker() | |
| if seed is not None: | |
| Faker.seed(seed) | |
| random.seed(seed) | |
| # Dictionary structure: { "clean_key": "fake_text" } | |
| self.mappings: Dict[str, str] = {} | |
| def get_replacement(self, entity_type: str, original_text: str) -> str: | |
| """ | |
| Retrieves or generates a fake replacement for the given original text. | |
| Args: | |
| entity_type: The type of the PII entity (e.g., "NAME", "EMAIL"). | |
| original_text: The actual PII text found in the document. | |
| Returns: | |
| The fake replacement string. | |
| """ | |
| # Strip honorifics and titles for a consistent base name | |
| clean_text = re.sub(r'\b(mr\.|mrs\.|dr\.|shri|smt\.?)\b', '', original_text, flags=re.IGNORECASE) | |
| # Normalize keys as requested: strip commas, punctuation, spaces | |
| lookup_key = re.sub(r'[^a-z0-9]', '', clean_text.lower()) | |
| # Check if we already have a mapping for this entity regardless of type | |
| if lookup_key in self.mappings: | |
| return self.mappings[lookup_key] | |
| # Generate a new fake value based on the entity type | |
| fake_value = self._generate_fake(entity_type, original_text) | |
| # Store for future lookups | |
| self.mappings[lookup_key] = fake_value | |
| return fake_value | |
| def _generate_fake(self, entity_type: str, original_text: str = "") -> str: | |
| """ | |
| Internal method to generate a fake string for a specific entity type. | |
| """ | |
| if entity_type == "NAME": | |
| return self.fake.name() | |
| elif entity_type == "COMPANY": | |
| return self.fake.company() | |
| elif entity_type == "ADDRESS": | |
| # Generate short, concise street and city strings | |
| return self.fake.street_address() + ", " + self.fake.city() | |
| elif entity_type == "EMAIL": | |
| return self.fake.safe_email() | |
| elif entity_type in ("PHONE", "PHONE_KEYWORD"): | |
| # Generating a standard phone format | |
| return self.fake.numerify(text="###-###-####") | |
| elif entity_type == "SSN": | |
| return self.fake.ssn() | |
| elif entity_type == "IP_ADDRESS": | |
| return self.fake.ipv4() | |
| elif entity_type == "CREDIT_CARD": | |
| # Generating a generic 16 digit number to represent CC | |
| return self.fake.credit_card_number(card_type=None) | |
| elif entity_type == "DOB": | |
| # Generate a date of birth (MM/DD/YYYY) | |
| date_obj = self.fake.date_of_birth(minimum_age=18, maximum_age=90) | |
| return date_obj.strftime("%m/%d/%Y") | |
| elif entity_type == "URL": | |
| # Strict generation as per request | |
| return "www." + self.fake.domain_name() | |
| return "[REDACTED]" | |