HITESHCODER/Toxic_Comment_Detection_System
0
1# ==========================================================2# Imports3# ==========================================================4 5import gradio as gr6import pandas as pd7import numpy as np8import matplotlib.pyplot as plt9 10import joblib11 12import re13import string14import contractions15import emoji16 17import nltk18from nltk.tokenize import word_tokenize19from nltk.corpus import stopwords20from nltk.stem import WordNetLemmatizer21 22 23# ==========================================================24# Download NLTK Resources (Only First Time)25# ==========================================================26 27nltk.download("punkt")28nltk.download("punkt_tab")29nltk.download("stopwords")30nltk.download("wordnet")31nltk.download("omw-1.4")32 33 34# ==========================================================35# Load Saved Model36# ==========================================================37 38pipeline = joblib.load("pipeline.pkl")39 40# Load Thresholds41thresholds = joblib.load("thresholds.pkl")42 43 44# ==========================================================45# Labels46# ==========================================================47 48LABELS = [49 "Toxic",50 "Severe Toxic",51 "Obscene",52 "Threat",53 "Insult",54 "Identity Hate"55]56 57 58# ==========================================================59# NLP Objects60# ==========================================================61 62lemmatizer = WordNetLemmatizer()63 64stop_words = set(stopwords.words("english"))65 66for word in ["not", "no", "nor", "never"]:67 stop_words.discard(word)68 69 70# ==========================================================71# Text Preprocessing Function72# ==========================================================73 74def preprocess(text):75 76 # Convert to lowercase77 text = text.lower()78 79 # Expand contractions80 text = contractions.fix(text)81 82 # Remove HTML83 text = re.sub(r"<.*?>", "", text)84 85 # Remove URLs86 text = re.sub(r"http\S+|www\S+", "", text)87 88 # Remove Emails89 text = re.sub(r"\S+@\S+", "", text)90 91 # Remove @mentions92 text = re.sub(r"@\w+", "", text)93 94 # Remove hashtag symbol95 text = text.replace("#", "")96 97 # Remove emojis98 text = emoji.replace_emoji(text, replace="")99 100 # Remove numbers101 text = re.sub(r"\d+", "", text)102 103 # Remove punctuation104 text = text.translate(105 str.maketrans("", "", string.punctuation)106 )107 108 # Remove extra spaces109 text = re.sub(r"\s+", " ", text).strip()110 111 # Tokenize112 words = word_tokenize(text)113 114 # Remove stopwords + Lemmatization115 words = [116 117 lemmatizer.lemmatize(word, pos="v")118 119 for word in words120 121 if word not in stop_words122 123 ]124 125 return " ".join(words)126 127 128# ==========================================================129# Prediction Function130# ==========================================================131 132def predict_comment(user_comment):133 134 # Keep original comment135 original_comment = user_comment136 137 # Clean comment138 cleaned_comment = preprocess(user_comment)139 140 # Create dataframe (same format used during training)141 input_df = pd.DataFrame(142 {143 "clean_comment": [cleaned_comment]144 }145 )146 147 # Predict probabilities148 probabilities = pipeline.predict_proba(input_df)[0]149 150 # Apply thresholds151 predictions = (152 probabilities >= thresholds153 ).astype(int)154 155 # Overall confidence156 confidence = np.max(probabilities) * 100157 158 return (159 original_comment,160 cleaned_comment,161 probabilities,162 predictions,163 confidence164 )165 166def get_overall_status(predictions):167 168 if np.sum(predictions) == 0:169 170 return "🟢 NON TOXIC COMMENT"171 172 else:173 174 return "🔴 TOXIC COMMENT DETECTED"175 176 177def create_probability_table(probabilities, predictions):178 179 probability_df = pd.DataFrame({180 181 "Category": LABELS,182 183 "Probability (%)":184 np.round(probabilities * 100, 2),185 186 "Prediction":187 [188 "Positive" if pred == 1189 else "Negative"190 191 for pred in predictions192 ]193 194 })195 196 return probability_df197 198def create_probability_chart(probabilities):199 200 probabilities = probabilities * 100201 202 fig, ax = plt.subplots(figsize=(8,5))203 204 bars = ax.barh(205 206 LABELS,207 208 probabilities209 210 )211 212 ax.set_xlim(0,100)213 214 ax.set_xlabel("Probability (%)")215 216 ax.set_title("Toxicity Probability Distribution")217 218 for bar in bars:219 220 width = bar.get_width()221 222 ax.text(223 224 width + 1,225 226 bar.get_y() + bar.get_height()/2,227 228 f"{width:.1f}%",229 230 va="center"231 232 )233 234 plt.tight_layout()235 236 return fig237 238def generate_summary(probabilities, predictions):239 240 summary = []241 242 for label, prob, pred in zip(243 244 LABELS,245 246 probabilities,247 248 predictions249 250 ):251 252 if pred == 1:253 254 if prob >= 0.80:255 256 summary.append(257 258 f"• High confidence {label.lower()} detected ({prob*100:.1f}%)."259 260 )261 262 elif prob >= 0.50:263 264 summary.append(265 266 f"• Moderate confidence {label.lower()} detected ({prob*100:.1f}%)."267 268 )269 270 else:271 272 summary.append(273 274 f"• Low confidence {label.lower()} detected ({prob*100:.1f}%)."275 276 )277 278 if len(summary) == 0:279 280 summary.append(281 282 "• No toxic categories detected."283 284 )285 286 summary.append("")287 288 if np.sum(predictions) > 0:289 290 summary.append(291 292 "Recommendation: This comment should be reviewed before posting."293 294 )295 296 else:297 298 summary.append(299 300 "Recommendation: This comment appears safe."301 302 )303 304 return "\n".join(summary)305 306def analyze_comment(user_comment):307 308 (309 original_comment,310 311 cleaned_comment,312 313 probabilities,314 315 predictions,316 317 confidence318 319 ) = predict_comment(user_comment)320 321 status = get_overall_status(predictions)322 323 probability_table = create_probability_table(324 325 probabilities,326 327 predictions328 329 )330 331 chart = create_probability_chart(332 333 probabilities334 335 )336 337 summary = generate_summary(338 339 probabilities,340 341 predictions342 343 )344 345 confidence = f"{confidence:.2f}%"346 347 return (348 349 original_comment,350 351 cleaned_comment,352 353 status,354 355 confidence,356 357 probability_table,358 359 chart,360 361 summary362 363 )364 365 366css = """367footer {368 visibility: hidden;369}370 371.gradio-container {372 max-width: 1300px !important;373 margin: auto;374}375 376h1{377 text-align:center;378}379 380"""381 382# ==========================================================383# Gradio User Interface384# ==========================================================385 386with gr.Blocks(387 css=css,388 theme=gr.themes.Soft(389 primary_hue="blue",390 secondary_hue="slate"391 ),392 title="AI Toxic Comment Detection System"393) as demo:394 395 gr.Markdown(396 """397 # 🛡️ AI Toxic Comment Detection System398 399 Analyze comments using a Multi-Label Machine Learning Model.400 401 The model predicts the following six toxicity categories:402 403 - Toxic404 - Severe Toxic405 - Obscene406 - Threat407 - Insult408 - Identity Hate409 """410 )411 412 # =====================================================413 # User Input414 # =====================================================415 416 with gr.Row():417 418 comment_input = gr.Textbox(419 420 label="Enter Comment",421 422 placeholder="Type or paste a comment here...",423 424 lines=5425 426 )427 428 analyze_button = gr.Button(429 430 "Analyze Comment",431 432 variant="primary"433 434 )435 436 gr.Markdown("---")437 438 # =====================================================439 # Original & Cleaned Comment440 # =====================================================441 442 with gr.Row():443 444 original_output = gr.Textbox(445 446 label="Original Comment",447 448 interactive=False,449 450 lines=4451 452 )453 454 cleaned_output = gr.Textbox(455 456 label="Preprocessed Comment",457 458 interactive=False,459 460 lines=4461 462 )463 464 # =====================================================465 # Overall Prediction466 # =====================================================467 468 with gr.Row():469 470 status_output = gr.Textbox(471 472 label="Overall Prediction",473 474 interactive=False475 476 )477 478 confidence_output = gr.Textbox(479 480 label="Overall Confidence",481 482 interactive=False483 484 )485 486 gr.Markdown("---")487 488 # =====================================================489 # Prediction Table490 # =====================================================491 492 probability_table = gr.Dataframe(493 494 headers=[495 496 "Category",497 498 "Probability (%)",499 500 "Prediction"501 502 ],503 504 interactive=False,505 506 label="Prediction Details"507 508 )509 510 gr.Markdown("---")511 512 # =====================================================513 # Probability Graph514 # =====================================================515 516 probability_plot = gr.Plot(517 518 label="Category Probability Distribution"519 520 )521 522 gr.Markdown("---")523 524 # =====================================================525 # AI Summary526 # =====================================================527 528 summary_output = gr.Textbox(529 530 label="AI Analysis Summary",531 532 interactive=False,533 534 lines=10535 536 )537 538 # =====================================================539 # Button Click Event540 # =====================================================541 542 analyze_button.click(543 544 fn=analyze_comment,545 546 inputs=comment_input,547 548 outputs=[549 550 original_output,551 552 cleaned_output,553 554 status_output,555 556 confidence_output,557 558 probability_table,559 560 probability_plot,561 562 summary_output563 564 ]565 566 )567 568# ==========================================================569# Launch App570# ==========================================================571 572if __name__ == "__main__":573 demo.launch(debug=True)574 