ScamShield-nlp / app.py
swara242's picture
Update app.py
7dd30f3 verified
Raw
History Blame Contribute Delete
6.37 kB
"""ScamShield NLP — Hugging Face Space entry point.
A pure-inference Gradio app exposing the trained calibrated Linear SVM.
Two ways to use it:
1. Web UI — type/paste a message and click "Analyze".
2. HTTP API — the same function is exposed through the Gradio API.
"""
import gradio as gr
import spaces
from predictor import ScamPredictor
# ---------------------------------------------------------
# Model
# ---------------------------------------------------------
predictor = ScamPredictor()
# ---------------------------------------------------------
# Configuration
# ---------------------------------------------------------
MAX_MESSAGE_LENGTH = 20000
TITLE = "ScamShield NLP"
DESCRIPTION = (
"Classifies a text message as **SCAM** or **LEGITIMATE** using a "
"**calibrated Linear SVM** trained on the ScamShield corpus "
"(TF-IDF features, n-grams 1–2). Returns a calibrated scam probability "
"(confidence) and a risk level."
)
# ---------------------------------------------------------
# Example messages
# ---------------------------------------------------------
EXAMPLES = [
["Congratulations! You have won a prize. Click this link now."],
[
"Dear customer, your account will be locked. "
"Verify now: http://bit.ly/fake"
],
[
"URGENT: Your parcel could not be delivered. "
"Pay $2 to reschedule: https://short.link/x"
],
["Hi, the meeting is moved to 4pm tomorrow. See you then."],
[
"Your OTP for verification is 482913. "
"Do not share it with anyone."
],
[
"Reminder: your subscription renews on the 28th. "
"Manage settings here."
],
]
# ---------------------------------------------------------
# Analyze function
# ---------------------------------------------------------
@spaces.GPU
def analyze(message: str) -> dict:
"""Validate input, then run inference with detailed error logging."""
import traceback
try:
# ---------------------------------------------
# Validate input
# ---------------------------------------------
if message is None or not str(message).strip():
raise gr.Error("Message cannot be empty.")
message = str(message)
if len(message) > MAX_MESSAGE_LENGTH:
raise gr.Error(
f"Message too long (max {MAX_MESSAGE_LENGTH} characters)."
)
# ---------------------------------------------
# Run model prediction
# ---------------------------------------------
print("=" * 60)
print("ANALYZE REQUEST")
print(f"Message: {message}")
print("=" * 60)
result = predictor.predict(message)
# ---------------------------------------------
# Success logging
# ---------------------------------------------
print("=" * 60)
print(f"SUCCESS: {result}")
print("=" * 60)
return result
except gr.Error:
# Keep Gradio validation errors readable.
raise
except Exception as e:
# ---------------------------------------------
# Detailed diagnostic logging
# ---------------------------------------------
error_msg = (
f"{type(e).__name__}: {e}\n"
f"{traceback.format_exc()}"
)
print("=" * 60)
print("ERROR DURING ANALYSIS")
print(error_msg)
print("=" * 60)
# Show a shorter message to the UI while keeping
# the complete traceback in Hugging Face logs.
raise gr.Error(
f"Analysis failed: {type(e).__name__}: {e}"
)
# ---------------------------------------------------------
# Gradio UI
# ---------------------------------------------------------
with gr.Blocks(
title=TITLE,
theme=gr.themes.Soft()
) as demo:
# ---------------------------------------------
# Header
# ---------------------------------------------
gr.Markdown(f"# {TITLE}")
gr.Markdown(DESCRIPTION)
# ---------------------------------------------
# Main layout
# ---------------------------------------------
with gr.Row():
# -----------------------------------------
# Input
# -----------------------------------------
with gr.Column(scale=3):
message_input = gr.Textbox(
label="Message",
lines=5,
placeholder=(
"Paste the SMS, email or chat message "
"to classify…"
),
)
analyze_button = gr.Button(
"Analyze",
variant="primary"
)
# -----------------------------------------
# Output
# -----------------------------------------
with gr.Column(scale=2):
result_output = gr.JSON(
label="Result"
)
# ---------------------------------------------
# Analyze button
# ---------------------------------------------
analyze_button.click(
analyze,
inputs=message_input,
outputs=result_output,
api_name="predict",
)
# ---------------------------------------------
# Enter / Submit
# ---------------------------------------------
message_input.submit(
analyze,
inputs=message_input,
outputs=result_output,
)
# ---------------------------------------------
# Examples + Model information
# ---------------------------------------------
gr.Markdown(
"""
### Example messages
Click an example to load it, then press **Analyze**.
### Model
`CalibratedClassifierCV(LinearSVC)` over
`TfidfVectorizer` (10,000 features, n-gram 1–2)
**Held-out test set:**
- Accuracy: **96.91%**
- Precision: **96.64%**
- Recall: **94.99%**
- F1: **95.81%**
"""
)
# ---------------------------------------------
# Example messages
# ---------------------------------------------
gr.Examples(
examples=EXAMPLES,
inputs=message_input,
outputs=result_output,
)
# ---------------------------------------------------------
# Launch
# ---------------------------------------------------------
if __name__ == "__main__":
demo.launch()