Spaces:
Running on Zero
Running on Zero
File size: 5,500 Bytes
0fe62e1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | """
ToxiGuard AI β Text Preprocessing Pipeline
============================================
Two distinct preprocessing pipelines optimised for different consumers:
1. preprocess_for_rules(text) β str
Aggressive normalisation for the keyword rule engine.
- Lowercases, strips URLs/emails, de-obfuscates leet-speak
- Strips punctuation and non-ASCII (ASCII-safe for pattern matching)
2. preprocess_for_model(text) β str
Light clean for DeBERTa tokenizer.
- Removes URLs and excessive whitespace
- Preserves unicode, emojis, and casing
- DeBERTa's tokenizer handles the rest
3. preprocess(text) β dict [backward-compatible wrapper]
Returns {"clean_text": ..., "rule_text": ..., "tokens": [...]}
"""
import re
import string
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# LEET-SPEAK DE-OBFUSCATION MAP (rule engine only)
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
_OBFUSCATION_MAP: dict[str, str] = {
"@": "a",
"$": "s",
"0": "o",
"1": "i",
"3": "e",
"4": "a",
"5": "s",
"7": "t",
"*": "",
"!": "",
"_": "",
"-": " ",
}
_URL_RE = re.compile(r"https?://\S+|www\.\S+", re.IGNORECASE)
_EMAIL_RE = re.compile(r"\S+@\S+\.\S+")
_WHITESPACE_RE = re.compile(r"\s+")
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PIPELINE 1 β Rule engine (aggressive, ASCII-safe)
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def preprocess_for_rules(text: str) -> str:
"""
Normalise text for the keyword rule engine.
Steps:
1. Lowercase + strip
2. Remove URLs and email addresses
3. De-obfuscate leet-speak characters (@ β a, $ β s, etc.)
4. Drop non-ASCII (covers emoji that can't map to leet-speak)
5. Remove punctuation
6. Collapse whitespace
"""
if not text:
return ""
text = text.lower().strip()
text = _URL_RE.sub(" ", text)
text = _EMAIL_RE.sub(" ", text)
for char, replacement in _OBFUSCATION_MAP.items():
text = text.replace(char, replacement)
# Drop non-ASCII (emoji, exotic unicode)
text = text.encode("ascii", "ignore").decode()
# Remove punctuation but keep spaces
text = text.translate(str.maketrans("", "", string.punctuation))
text = _WHITESPACE_RE.sub(" ", text).strip()
return text
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PIPELINE 2 β DeBERTa tokenizer (light clean, unicode-safe)
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def preprocess_for_model(text: str) -> str:
"""
Light normalisation for DeBERTa.
DeBERTa's SentencePiece tokenizer handles:
- Casing (it's uncased internally)
- Punctuation
- Unicode and emojis
We only remove noise that adds no semantic value:
- URLs
- Email addresses
- Excessive whitespace
"""
if not text:
return ""
text = _URL_RE.sub(" [URL] ", text)
text = _EMAIL_RE.sub(" [EMAIL] ", text)
text = _WHITESPACE_RE.sub(" ", text).strip()
return text
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# BACKWARD-COMPAT WRAPPER
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def tokenize(text: str) -> list[str]:
"""Split rule-preprocessed text into tokens."""
if not text:
return []
return text.split()
def preprocess(text: str) -> dict:
"""
Full preprocessing pipeline β backward-compatible wrapper.
Returns:
{
"clean_text": str β rule-safe (aggressive, ASCII)
"model_text": str β model-safe (light, unicode)
"tokens": list β tokens from clean_text
}
"""
rule_text = preprocess_for_rules(text)
model_text = preprocess_for_model(text)
return {
"clean_text": rule_text, # kept for backward compat
"model_text": model_text,
"tokens": tokenize(rule_text),
}
__all__ = [
"preprocess",
"preprocess_for_rules",
"preprocess_for_model",
"tokenize",
]
|