ai-human-text-detector / src /preprocessing.py
mdarahmanxAI's picture
Deploy AI vs human detector with LLM explanations
d433145 verified
Raw
History Blame Contribute Delete
2.1 kB
"""Dataset loading and text cleaning.
The cleaning here is deliberately light. Detecting AI vs. human writing is a
stylometric problem (telling two writing styles apart), not a topic problem.
Function words, punctuation, and casing carry much of the signal, so unlike a
typical topic-classification pipeline we do not strip stopwords or punctuation.
We only normalize whitespace, which document parsers tend to mangle.
"""
from __future__ import annotations
import re
from pathlib import Path
import ftfy
import pandas as pd
PROJECT_ROOT = Path(__file__).resolve().parents[1]
TRAIN_DATA = PROJECT_ROOT / "data" / "training_data" / "train_data_with_labels.xlsx"
LABEL_NAMES = {0: "Human", 1: "AI"}
_WHITESPACE = re.compile(r"\s+")
def load_dataset(path: Path | str = TRAIN_DATA) -> pd.DataFrame:
"""Load the labeled passages and remove exact duplicates and empty rows.
The text is run through ftfy to repair mojibake. A large share of passages
contain double-encoded smart quotes (for example "don’t" for "don't");
left unrepaired these turn into garbage tokens and an encoding artifact the
classifier could exploit. Repairing first also lets us deduplicate passages
that differ only by encoding.
"""
df = pd.read_excel(path)
df = df.dropna(subset=["text", "label"])
df["text"] = df["text"].map(lambda t: ftfy.fix_text(str(t)))
df = df[df["text"].str.strip().astype(bool)]
df = df.drop_duplicates(subset="text").reset_index(drop=True)
df["label"] = df["label"].astype(int)
return df
def normalize_whitespace(text: str) -> str:
"""Collapse runs of whitespace to single spaces and trim the ends.
Punctuation, casing, and stopwords are left untouched on purpose.
"""
return _WHITESPACE.sub(" ", str(text)).strip()
def clean_text(text: str) -> str:
"""Repair encoding then normalize whitespace.
This is the single entry point the Streamlit app uses on user-supplied text
so it gets exactly the same treatment as the training data.
"""
return normalize_whitespace(ftfy.fix_text(str(text)))