Spaces:
Sleeping
Sleeping
Surya8663
commited on
Commit
·
4ded330
0
Parent(s):
Final version, database correctly ignored
Browse files- .gitignore +7 -0
- .gradio/certificate.pem +31 -0
- .gradio/flagged/dataset1.csv +2 -0
- app.py +8 -0
- backend/app.py +107 -0
- backend/check_env.py +9 -0
- backend/compare_models.py +46 -0
- backend/credential.env +2 -0
- backend/database.py +56 -0
- backend/gmail_fetcher.py +100 -0
- backend/gradio_app.py +52 -0
- data/emails_sample.csv +170 -0
- deploy.sh +28 -0
- predicted_emails.csv +9 -0
- requirements.txt +87 -0
.gitignore
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.venv/
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.pyc
|
| 4 |
+
.env
|
| 5 |
+
token.json
|
| 6 |
+
credentials.json
|
| 7 |
+
email_sorter.db
|
.gradio/certificate.pem
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN CERTIFICATE-----
|
| 2 |
+
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
|
| 31 |
+
-----END CERTIFICATE-----
|
.gradio/flagged/dataset1.csv
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
subject,body,output 0,output 1,timestamp
|
| 2 |
+
Team Standup Reminder,Please join the daily standup meeting at 10 AM,Personal,0.3250395441164229,2025-10-02 14:26:46.167232
|
app.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file should be in: your_project_root/app.py
|
| 2 |
+
|
| 3 |
+
from backend.app import app
|
| 4 |
+
|
| 5 |
+
# The 'app' variable needs to be accessible at the top level for Hugging Face.
|
| 6 |
+
# The launch block is good practice and lets you run this file locally.
|
| 7 |
+
if __name__ == "__main__":
|
| 8 |
+
app.launch()
|
backend/app.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# backend/app.py (NEW VERSION USING A PRE-TRAINED MODEL)
|
| 2 |
+
|
| 3 |
+
from transformers import pipeline
|
| 4 |
+
import gradio as gr
|
| 5 |
+
import pandas as pd
|
| 6 |
+
from gmail_fetcher import fetch_latest_emails
|
| 7 |
+
import database
|
| 8 |
+
|
| 9 |
+
# --- This is the core change ---
|
| 10 |
+
# 1. We load a pre-trained "zero-shot-classification" pipeline from Hugging Face.
|
| 11 |
+
# The first time this code runs, it will automatically download the model (approx. 1.6GB).
|
| 12 |
+
print("Loading zero-shot classification model...")
|
| 13 |
+
classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
|
| 14 |
+
print("Model loaded successfully.")
|
| 15 |
+
# -----------------------------
|
| 16 |
+
|
| 17 |
+
database.init_db()
|
| 18 |
+
|
| 19 |
+
# --- These are the labels we want to sort emails into ---
|
| 20 |
+
# You can change or add to this list!
|
| 21 |
+
POSSIBLE_LABELS = ["Work", "Promotions", "Personal", "Spam", "Important"]
|
| 22 |
+
email_storage = {}
|
| 23 |
+
|
| 24 |
+
def predict_and_save_emails(df):
|
| 25 |
+
"""Takes a DataFrame of emails, classifies them, and saves to DB."""
|
| 26 |
+
if df.empty:
|
| 27 |
+
return pd.DataFrame({"Message": ["No emails to process."]})
|
| 28 |
+
|
| 29 |
+
# Get the text content for classification
|
| 30 |
+
sequences = (df['Subject'] + " " + df['Body']).tolist()
|
| 31 |
+
|
| 32 |
+
print(f"Classifying {len(sequences)} emails...")
|
| 33 |
+
# Use the zero-shot pipeline. It's powerful but can be slow on CPU for many emails.
|
| 34 |
+
predictions = classifier(sequences, candidate_labels=POSSIBLE_LABELS)
|
| 35 |
+
print("Classification complete.")
|
| 36 |
+
|
| 37 |
+
# Extract the top label and score for each prediction
|
| 38 |
+
pred_labels = [pred['labels'][0] for pred in predictions]
|
| 39 |
+
pred_scores = [pred['scores'][0] for pred in predictions]
|
| 40 |
+
|
| 41 |
+
# Add results to the DataFrame
|
| 42 |
+
df['predicted_folder'] = pred_labels
|
| 43 |
+
df['confidence'] = pred_scores
|
| 44 |
+
|
| 45 |
+
# Save to the database
|
| 46 |
+
database.add_email_records(df)
|
| 47 |
+
print(f"Saved {len(df)} records to the database.")
|
| 48 |
+
|
| 49 |
+
# Format for display
|
| 50 |
+
df_display = df.copy()
|
| 51 |
+
df_display['confidence'] = [f"{score:.2%}" for score in pred_scores]
|
| 52 |
+
return df_display[["From", "Subject", "predicted_folder", "confidence"]]
|
| 53 |
+
|
| 54 |
+
def fetch_and_classify_emails():
|
| 55 |
+
"""Fetches emails from Gmail and triggers the classification."""
|
| 56 |
+
emails = fetch_latest_emails()
|
| 57 |
+
if not emails:
|
| 58 |
+
email_storage.clear()
|
| 59 |
+
return pd.DataFrame({"From": ["No new emails found or an error occurred."], "Subject": [""]})
|
| 60 |
+
|
| 61 |
+
df = pd.DataFrame(emails)
|
| 62 |
+
return predict_and_save_emails(df)
|
| 63 |
+
|
| 64 |
+
# --- History & Feedback Functions (Unchanged) ---
|
| 65 |
+
def show_history():
|
| 66 |
+
records, columns = database.get_all_emails()
|
| 67 |
+
if not records:
|
| 68 |
+
return pd.DataFrame({"Message": ["No history found."]})
|
| 69 |
+
history_df = pd.DataFrame(records, columns=columns)
|
| 70 |
+
return history_df
|
| 71 |
+
|
| 72 |
+
def save_feedback_and_refresh(record_id, corrected_label):
|
| 73 |
+
if not record_id or not corrected_label:
|
| 74 |
+
return show_history(), "Please enter a Record ID and a correct label first."
|
| 75 |
+
|
| 76 |
+
record_id_int = int(record_id)
|
| 77 |
+
database.update_feedback(record_id_int, corrected_label)
|
| 78 |
+
|
| 79 |
+
return show_history(), f"Success! Record {record_id_int} updated."
|
| 80 |
+
|
| 81 |
+
# --- Build the Gradio Interface (Unchanged) ---
|
| 82 |
+
with gr.Blocks(theme=gr.themes.Soft()) as app:
|
| 83 |
+
gr.Markdown("## 📧 Smart Email Sorter (Zero-Shot Model)")
|
| 84 |
+
|
| 85 |
+
with gr.Tab("Fetch & Classify Gmail"):
|
| 86 |
+
predict_gmail_btn = gr.Button("Fetch and Classify Latest Emails", variant="primary")
|
| 87 |
+
email_display = gr.Dataframe(headers=["From", "Subject", "predicted_folder", "confidence"], label="Fetched & Classified Emails", wrap=True)
|
| 88 |
+
predict_gmail_btn.click(fn=fetch_and_classify_emails, outputs=email_display, show_progress="full")
|
| 89 |
+
|
| 90 |
+
with gr.Tab("History & Feedback"):
|
| 91 |
+
gr.Markdown("### Prediction History & Feedback")
|
| 92 |
+
gr.Markdown("To correct a prediction, find its `id` in the table, then enter it into the textbox below.")
|
| 93 |
+
with gr.Row():
|
| 94 |
+
record_id_input = gr.Number(label="Enter Record ID to Correct")
|
| 95 |
+
feedback_label = gr.Dropdown(label="Correct Folder", choices=POSSIBLE_LABELS)
|
| 96 |
+
with gr.Row():
|
| 97 |
+
submit_feedback_btn = gr.Button("Submit Correction", variant="primary")
|
| 98 |
+
refresh_history_btn = gr.Button("Refresh History")
|
| 99 |
+
feedback_status = gr.Markdown("")
|
| 100 |
+
history_df = gr.Dataframe(label="All Saved Predictions", wrap=True)
|
| 101 |
+
app.load(fn=show_history, outputs=history_df)
|
| 102 |
+
refresh_history_btn.click(fn=show_history, outputs=history_df)
|
| 103 |
+
submit_feedback_btn.click(
|
| 104 |
+
fn=save_feedback_and_refresh,
|
| 105 |
+
inputs=[record_id_input, feedback_label],
|
| 106 |
+
outputs=[history_df, feedback_status]
|
| 107 |
+
)
|
backend/check_env.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# backend/check_env.py
|
| 2 |
+
import sys
|
| 3 |
+
import gradio
|
| 4 |
+
|
| 5 |
+
print("--- Environment Diagnostics ---")
|
| 6 |
+
print(f"Python Executable Path: {sys.executable}")
|
| 7 |
+
print(f"Gradio Library Version: {gradio.__version__}")
|
| 8 |
+
print(f"Gradio Library Path: {gradio.__file__}")
|
| 9 |
+
print("---------------------------")
|
backend/compare_models.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import joblib
|
| 2 |
+
from transformers import DistilBertTokenizerFast, DistilBertForSequenceClassification
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
# -----------------------------
|
| 6 |
+
# 1️⃣ Load baseline TF-IDF model
|
| 7 |
+
# -----------------------------
|
| 8 |
+
baseline_model = joblib.load("models/baseline_folder_clf.pkl")
|
| 9 |
+
|
| 10 |
+
# -----------------------------
|
| 11 |
+
# 2️⃣ Load transformer model
|
| 12 |
+
# -----------------------------
|
| 13 |
+
model_path = "models/transformer"
|
| 14 |
+
tokenizer = DistilBertTokenizerFast.from_pretrained(model_path)
|
| 15 |
+
model = DistilBertForSequenceClassification.from_pretrained(model_path)
|
| 16 |
+
le = joblib.load(f"{model_path}/le.pkl")
|
| 17 |
+
model.eval()
|
| 18 |
+
|
| 19 |
+
# -----------------------------
|
| 20 |
+
# 3️⃣ Sample emails for testing
|
| 21 |
+
# -----------------------------
|
| 22 |
+
test_emails = [
|
| 23 |
+
{"subject": "Team Standup Reminder", "body": "Please join the daily standup meeting at 10 AM."},
|
| 24 |
+
{"subject": "50% Off on Shoes", "body": "Grab the latest offer on sneakers."},
|
| 25 |
+
{"subject": "Mom's Birthday", "body": "Don't forget to call mom today."},
|
| 26 |
+
]
|
| 27 |
+
|
| 28 |
+
# -----------------------------
|
| 29 |
+
# 4️⃣ Compare predictions
|
| 30 |
+
# -----------------------------
|
| 31 |
+
for email in test_emails:
|
| 32 |
+
text = email["subject"] + " " + email["body"]
|
| 33 |
+
|
| 34 |
+
# Baseline prediction
|
| 35 |
+
baseline_pred = baseline_model.predict([text])[0]
|
| 36 |
+
|
| 37 |
+
# Transformer prediction
|
| 38 |
+
inputs = tokenizer(text, truncation=True, padding=True, return_tensors="pt")
|
| 39 |
+
with torch.no_grad():
|
| 40 |
+
outputs = model(**inputs)
|
| 41 |
+
pred_id = torch.argmax(outputs.logits, dim=1).item()
|
| 42 |
+
transformer_pred = le.inverse_transform([pred_id])[0]
|
| 43 |
+
|
| 44 |
+
print(f"\nEmail: {text}")
|
| 45 |
+
print(f"Baseline prediction: {baseline_pred}")
|
| 46 |
+
print(f"Transformer prediction: {transformer_pred}")
|
backend/credential.env
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
GMAIL_USER="iamsurya195@gmail.com"
|
| 2 |
+
GMAIL_PASSWORD="acqy dxst pwkl aymz"
|
backend/database.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# backend/database.py (ROBUST VERSION)
|
| 2 |
+
import sqlite3
|
| 3 |
+
from datetime import datetime
|
| 4 |
+
|
| 5 |
+
DB_NAME = "email_sorter.db"
|
| 6 |
+
|
| 7 |
+
def init_db():
|
| 8 |
+
"""Initializes the database using a context manager for safety."""
|
| 9 |
+
with sqlite3.connect(DB_NAME) as conn:
|
| 10 |
+
cursor = conn.cursor()
|
| 11 |
+
cursor.execute('''
|
| 12 |
+
CREATE TABLE IF NOT EXISTS emails (
|
| 13 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 14 |
+
timestamp TEXT NOT NULL,
|
| 15 |
+
email_from TEXT,
|
| 16 |
+
subject TEXT,
|
| 17 |
+
body TEXT,
|
| 18 |
+
predicted_folder TEXT,
|
| 19 |
+
confidence REAL,
|
| 20 |
+
user_feedback TEXT
|
| 21 |
+
)
|
| 22 |
+
''')
|
| 23 |
+
print("Database initialized successfully.")
|
| 24 |
+
|
| 25 |
+
def add_email_records(records_df):
|
| 26 |
+
"""Adds multiple email records from a pandas DataFrame using a context manager."""
|
| 27 |
+
with sqlite3.connect(DB_NAME) as conn:
|
| 28 |
+
records_df['timestamp'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 29 |
+
records_df['user_feedback'] = None
|
| 30 |
+
|
| 31 |
+
df_to_save = records_df.rename(columns={
|
| 32 |
+
'From': 'email_from',
|
| 33 |
+
'Subject': 'subject',
|
| 34 |
+
'Body': 'body'
|
| 35 |
+
})
|
| 36 |
+
|
| 37 |
+
db_columns = ['timestamp', 'email_from', 'subject', 'body', 'predicted_folder', 'confidence', 'user_feedback']
|
| 38 |
+
df_to_save = df_to_save[[col for col in db_columns if col in df_to_save.columns]]
|
| 39 |
+
|
| 40 |
+
df_to_save.to_sql('emails', conn, if_exists='append', index=False)
|
| 41 |
+
|
| 42 |
+
def get_all_emails():
|
| 43 |
+
"""Fetches all email records using a context manager."""
|
| 44 |
+
with sqlite3.connect(DB_NAME) as conn:
|
| 45 |
+
cursor = conn.cursor()
|
| 46 |
+
cursor.execute("SELECT id, timestamp, email_from, subject, predicted_folder, confidence, user_feedback FROM emails ORDER BY timestamp DESC")
|
| 47 |
+
records = cursor.fetchall()
|
| 48 |
+
columns = [description[0] for description in cursor.description]
|
| 49 |
+
return records, columns
|
| 50 |
+
|
| 51 |
+
def update_feedback(record_id, corrected_label):
|
| 52 |
+
"""Updates the user_feedback for a specific record using a context manager."""
|
| 53 |
+
with sqlite3.connect(DB_NAME) as conn:
|
| 54 |
+
cursor = conn.cursor()
|
| 55 |
+
cursor.execute("UPDATE emails SET user_feedback = ? WHERE id = ?", (corrected_label, record_id))
|
| 56 |
+
print(f"Updated record ID {record_id} with feedback: {corrected_label}")
|
backend/gmail_fetcher.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import imaplib
|
| 2 |
+
import email
|
| 3 |
+
from email.header import decode_header
|
| 4 |
+
import os
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
+
from bs4 import BeautifulSoup # A library for parsing HTML
|
| 7 |
+
|
| 8 |
+
# Load the environment variables from your .env file
|
| 9 |
+
load_dotenv()
|
| 10 |
+
|
| 11 |
+
def fetch_latest_emails(num_emails=10):
|
| 12 |
+
try:
|
| 13 |
+
# Get credentials securely from the .env file
|
| 14 |
+
username = os.getenv("GMAIL_USER")
|
| 15 |
+
password = os.getenv("GMAIL_PASSWORD")
|
| 16 |
+
|
| 17 |
+
if not username or not password:
|
| 18 |
+
print("Error: GMAIL_USER and GMAIL_PASSWORD must be set in the .env file.")
|
| 19 |
+
return []
|
| 20 |
+
|
| 21 |
+
# Connect to Gmail's server
|
| 22 |
+
mail = imaplib.IMAP4_SSL("imap.gmail.com")
|
| 23 |
+
mail.login(username, password)
|
| 24 |
+
mail.select("inbox")
|
| 25 |
+
|
| 26 |
+
# Search for all emails and get their IDs
|
| 27 |
+
result, data = mail.search(None, "ALL")
|
| 28 |
+
mail_ids = data[0].split()
|
| 29 |
+
|
| 30 |
+
emails = []
|
| 31 |
+
# Fetch the most recent emails based on num_emails
|
| 32 |
+
for i in mail_ids[-num_emails:]:
|
| 33 |
+
result, data = mail.fetch(i, "(RFC822)")
|
| 34 |
+
raw_email = data[0][1]
|
| 35 |
+
msg = email.message_from_bytes(raw_email)
|
| 36 |
+
|
| 37 |
+
# Decode the subject line safely
|
| 38 |
+
subject, encoding = decode_header(msg["Subject"])[0]
|
| 39 |
+
if isinstance(subject, bytes):
|
| 40 |
+
subject = subject.decode(encoding or "utf-8", errors="ignore")
|
| 41 |
+
|
| 42 |
+
# Get the sender's address
|
| 43 |
+
from_ = msg.get("From", "")
|
| 44 |
+
|
| 45 |
+
# --- Improved Body Parsing ---
|
| 46 |
+
body = ""
|
| 47 |
+
if msg.is_multipart():
|
| 48 |
+
for part in msg.walk():
|
| 49 |
+
content_type = part.get_content_type()
|
| 50 |
+
content_disposition = str(part.get("Content-Disposition"))
|
| 51 |
+
|
| 52 |
+
# Skip attachments
|
| 53 |
+
if "attachment" not in content_disposition:
|
| 54 |
+
if content_type == "text/plain":
|
| 55 |
+
try:
|
| 56 |
+
body = part.get_payload(decode=True).decode()
|
| 57 |
+
break # Found plain text, stop searching
|
| 58 |
+
except:
|
| 59 |
+
continue
|
| 60 |
+
elif content_type == "text/html":
|
| 61 |
+
# If we only find HTML, parse it to get clean text
|
| 62 |
+
try:
|
| 63 |
+
html_body = part.get_payload(decode=True).decode()
|
| 64 |
+
soup = BeautifulSoup(html_body, "html.parser")
|
| 65 |
+
body = soup.get_text()
|
| 66 |
+
except:
|
| 67 |
+
continue
|
| 68 |
+
else:
|
| 69 |
+
# For non-multipart emails, just get the payload
|
| 70 |
+
try:
|
| 71 |
+
body = msg.get_payload(decode=True).decode()
|
| 72 |
+
except:
|
| 73 |
+
body = ""
|
| 74 |
+
|
| 75 |
+
emails.append({
|
| 76 |
+
"From": from_,
|
| 77 |
+
"Subject": subject,
|
| 78 |
+
"Body": body.strip()
|
| 79 |
+
})
|
| 80 |
+
|
| 81 |
+
mail.logout()
|
| 82 |
+
# Return emails in reverse order to show the newest one first
|
| 83 |
+
return emails[::-1]
|
| 84 |
+
|
| 85 |
+
except Exception as e:
|
| 86 |
+
print(f"An error occurred while fetching emails: {e}")
|
| 87 |
+
return []
|
| 88 |
+
|
| 89 |
+
# NEW, ROBUST CODE for the end of gmail_fetcher.py
|
| 90 |
+
if __name__ == "__main__":
|
| 91 |
+
latest_emails = fetch_latest_emails()
|
| 92 |
+
if latest_emails:
|
| 93 |
+
print(f"Successfully fetched {len(latest_emails)} emails.")
|
| 94 |
+
for e in latest_emails:
|
| 95 |
+
# Safely encode and decode each part to prevent crashes in the terminal
|
| 96 |
+
safe_from = e['From'].encode('utf-8', 'replace').decode('utf-8')
|
| 97 |
+
safe_subject = e['Subject'].encode('utf-8', 'replace').decode('utf-8')
|
| 98 |
+
safe_body = e['Body'][:100].encode('utf-8', 'replace').decode('utf-8')
|
| 99 |
+
|
| 100 |
+
print(f"From: {safe_from}\nSubject: {safe_subject}\nBody: {safe_body}...\n")
|
backend/gradio_app.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import torch
|
| 3 |
+
from transformers import DistilBertTokenizerFast, DistilBertForSequenceClassification
|
| 4 |
+
import joblib
|
| 5 |
+
import gradio as gr
|
| 6 |
+
|
| 7 |
+
# -----------------------------
|
| 8 |
+
# Load trained transformer
|
| 9 |
+
# -----------------------------
|
| 10 |
+
model_path = "./models/transformer"
|
| 11 |
+
model = DistilBertForSequenceClassification.from_pretrained(model_path)
|
| 12 |
+
tokenizer = DistilBertTokenizerFast.from_pretrained(model_path)
|
| 13 |
+
le = joblib.load(f"{model_path}/le.pkl")
|
| 14 |
+
model.eval()
|
| 15 |
+
|
| 16 |
+
# -----------------------------
|
| 17 |
+
# Prediction function for CSV
|
| 18 |
+
# -----------------------------
|
| 19 |
+
def predict_csv(file):
|
| 20 |
+
df = pd.read_csv(file.name)
|
| 21 |
+
if 'subject' not in df.columns or 'body' not in df.columns:
|
| 22 |
+
return "CSV must have 'subject' and 'body' columns."
|
| 23 |
+
|
| 24 |
+
texts = df['subject'] + " " + df['body']
|
| 25 |
+
predictions = []
|
| 26 |
+
|
| 27 |
+
for text in texts:
|
| 28 |
+
inputs = tokenizer(text, truncation=True, padding=True, return_tensors="pt")
|
| 29 |
+
with torch.no_grad():
|
| 30 |
+
outputs = model(**inputs)
|
| 31 |
+
pred_id = torch.argmax(outputs.logits, dim=1).item()
|
| 32 |
+
pred_label = le.inverse_transform([pred_id])[0]
|
| 33 |
+
predictions.append(pred_label)
|
| 34 |
+
|
| 35 |
+
df['predicted_folder'] = predictions
|
| 36 |
+
return df # Gradio will display as a table
|
| 37 |
+
|
| 38 |
+
# -----------------------------
|
| 39 |
+
# Gradio interface
|
| 40 |
+
# -----------------------------
|
| 41 |
+
iface = gr.Interface(
|
| 42 |
+
fn=predict_csv,
|
| 43 |
+
inputs=gr.File(label="Upload CSV"),
|
| 44 |
+
outputs=gr.Dataframe(label="Predicted Folders"),
|
| 45 |
+
title="Smart Email Sorter (Transformer) - CSV Upload",
|
| 46 |
+
description="Upload a CSV with 'subject' and 'body' columns to predict email folders."
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
# -----------------------------
|
| 50 |
+
# Launch
|
| 51 |
+
# -----------------------------
|
| 52 |
+
iface.launch(share=True)
|
data/emails_sample.csv
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
subject,body,folder
|
| 2 |
+
Team Standup Reminder,"Please join the daily standup meeting at 10 AM.",Work
|
| 3 |
+
Project Deadline,"Final submission for the AI project is due tomorrow.",Work
|
| 4 |
+
Meeting Invitation,"You are invited to the client meeting at 2 PM.",Work
|
| 5 |
+
Code Review,"Please review the latest PR in GitHub.",Work
|
| 6 |
+
Performance Review,"Your annual performance review is scheduled for Friday.",Work
|
| 7 |
+
50% Off on Sneakers,"Grab the latest offer on sneakers before it ends.",Promotions
|
| 8 |
+
Black Friday Sale,"Don’t miss our Black Friday deals this weekend.",Promotions
|
| 9 |
+
New Arrivals: Electronics,"Check out our newest gadgets now.",Promotions
|
| 10 |
+
Holiday Discounts,"Save big on your holiday shopping today.",Promotions
|
| 11 |
+
Summer Sale,"Up to 70% off on summer collection.",Promotions
|
| 12 |
+
Mom's Birthday,"Don’t forget to call mom today.",Personal
|
| 13 |
+
Dad’s Anniversary,"Wish your dad a happy anniversary.",Personal
|
| 14 |
+
Friend’s Wedding,"Join us for John and Emily’s wedding this Saturday.",Personal
|
| 15 |
+
Grocery Reminder,"Buy milk, eggs, and bread on your way home.",Personal
|
| 16 |
+
Doctor Appointment,"Remember your check-up tomorrow at 3 PM.",Personal
|
| 17 |
+
Your Amazon Order,"Your order has been shipped and will arrive soon.",Updates
|
| 18 |
+
Flight Confirmation,"Your flight booking has been confirmed.",Updates
|
| 19 |
+
Package Delivered,"Your package has been delivered to your address.",Updates
|
| 20 |
+
Account Update,"Your account password was changed successfully.",Updates
|
| 21 |
+
Subscription Renewal,"Your subscription will renew on the 5th of next month.",Updates
|
| 22 |
+
Workshop Registration,"You are registered for the AI workshop on Saturday.",Work
|
| 23 |
+
Promo Code Inside,"Use code SAVE20 to get a discount today.",Promotions
|
| 24 |
+
Birthday Wishes,"Happy Birthday! Wishing you a wonderful year ahead.",Personal
|
| 25 |
+
System Maintenance,"Scheduled maintenance will occur this Sunday at midnight.",Updates
|
| 26 |
+
Weekly Report,Please submit your weekly report by Friday.,Work
|
| 27 |
+
Team Meeting,The design team meeting is scheduled at 3 PM.,Work
|
| 28 |
+
Password Reset,Click here to reset your account password.,Updates
|
| 29 |
+
Flight Reminder,Your flight to New York is tomorrow at 9 AM.,Updates
|
| 30 |
+
Birthday Party,You're invited to Jake's birthday party this Saturday.,Personal
|
| 31 |
+
Gym Membership,Renew your gym membership for the next month.,Personal
|
| 32 |
+
Discount on Laptops,Get up to 30% off on selected laptops.,Promotions
|
| 33 |
+
Black Friday Deals,Don't miss our Black Friday sale!,Promotions
|
| 34 |
+
Doctor Appointment,Your appointment with Dr. Smith is confirmed.,Personal
|
| 35 |
+
Project Update,The project documentation has been uploaded.,Work
|
| 36 |
+
Invoice #67890,Invoice has been processed and attached.,Updates
|
| 37 |
+
Conference Registration,Register now for the AI conference 2025.,Work
|
| 38 |
+
Holiday Plans,Let's plan our holiday trip for next month.,Personal
|
| 39 |
+
Subscription Renewal,Your magazine subscription will expire soon.,Updates
|
| 40 |
+
Flash Sale,Summer flash sale: up to 50% off!,Promotions
|
| 41 |
+
Client Feedback,Client has approved the latest design draft.,Work
|
| 42 |
+
Dinner Plans,Are you free for dinner tomorrow evening?,Personal
|
| 43 |
+
Amazon Promotion,Exclusive Amazon deals just for you!,Promotions
|
| 44 |
+
Password Change,Your password was changed successfully.,Updates
|
| 45 |
+
Meeting Agenda,Here is the agenda for tomorrow's meeting.,Work
|
| 46 |
+
Family Gathering,Family dinner at Mom's place this weekend.,Personal
|
| 47 |
+
Coupon Offer,Use code SAVE20 for instant discount.,Promotions
|
| 48 |
+
Event Reminder,Reminder: Webinar starts at 5 PM today.,Updates
|
| 49 |
+
Presentation Slides,Slides for Monday's presentation are ready.,Work
|
| 50 |
+
Weekend Sale,Weekend sale: shoes and bags up to 40% off!,Promotions
|
| 51 |
+
Travel Itinerary,Your travel itinerary has been emailed.,Updates
|
| 52 |
+
Birthday Reminder,Don't forget Sarah's birthday next week.,Personal
|
| 53 |
+
Product Launch,New product launch scheduled for next week.,Promotions
|
| 54 |
+
Meeting Notes,Notes from yesterday's client meeting.,Work
|
| 55 |
+
Doctor Checkup,Time for your annual health checkup.,Personal
|
| 56 |
+
Project Deadline Reminder,The project report is due by Friday,Work
|
| 57 |
+
Team Lunch,Join us for lunch at 1 PM,Work
|
| 58 |
+
Meeting Rescheduled,The meeting has been moved to 3 PM,Work
|
| 59 |
+
Client Feedback,The client has approved the design,Work
|
| 60 |
+
Invoice Received,Please review the attached invoice,Work
|
| 61 |
+
Salary Slip,Your salary slip for September is attached,Work
|
| 62 |
+
Weekly Report,Submit your weekly progress report,Work
|
| 63 |
+
Performance Review,Your performance review is scheduled for Monday,Work
|
| 64 |
+
Task Assignment,New tasks have been assigned to you,Work
|
| 65 |
+
Budget Approval,The budget for Q4 has been approved,Work
|
| 66 |
+
Happy Birthday,Wish you a very happy birthday,Personal
|
| 67 |
+
Dinner Tonight,Are you free for dinner tonight?,Personal
|
| 68 |
+
Call Mom,Don’t forget to call mom today,Personal
|
| 69 |
+
Friend’s Wedding,We are invited to a friend’s wedding,Personal
|
| 70 |
+
Gym Session,Reminder for your gym session at 6 PM,Personal
|
| 71 |
+
Vacation Plan,Let's plan the vacation for December,Personal
|
| 72 |
+
Book Club,Book club meeting is scheduled this Friday,Personal
|
| 73 |
+
Doctor Appointment,Your doctor appointment is confirmed,Personal
|
| 74 |
+
Car Service,Reminder for car service next week,Personal
|
| 75 |
+
Movie Night,Do you want to watch a movie tonight?,Personal
|
| 76 |
+
Flash Sale,Sneakers at 50% off this weekend,Promotions
|
| 77 |
+
Limited Offer,Buy one get one free on all shirts,Promotions
|
| 78 |
+
Mega Discount,Get up to 70% off on electronics,Promotions
|
| 79 |
+
Holiday Sale,Special discounts for the holiday season,Promotions
|
| 80 |
+
Coupon Code,Use code SAVE20 for 20% off,Promotions
|
| 81 |
+
Clearance Sale,Clearance sale on all winter clothes,Promotions
|
| 82 |
+
Free Shipping,Free shipping for orders above $50,Promotions
|
| 83 |
+
Weekend Deals,Exclusive weekend deals available now,Promotions
|
| 84 |
+
New Arrivals,Check out new arrivals this week,Promotions
|
| 85 |
+
Special Offer,Special offer ends tonight,Promotions
|
| 86 |
+
Amazon Order,Your order has been shipped,Updates
|
| 87 |
+
Delivery Confirmation,Your package has been delivered,Updates
|
| 88 |
+
Password Reset,Click the link to reset your password,Updates
|
| 89 |
+
Subscription Renewal,Your subscription is due for renewal,Updates
|
| 90 |
+
Account Alert,Unusual activity detected in your account,Updates
|
| 91 |
+
Flight Ticket,Your flight booking is confirmed,Updates
|
| 92 |
+
Event Reminder,Reminder: Webinar starts at 5 PM,Updates
|
| 93 |
+
Appointment Confirmation,Your appointment is confirmed,Updates
|
| 94 |
+
Service Update,Service will be down for maintenance tonight,Updates
|
| 95 |
+
System Notification,Your system password will expire soon,Updates
|
| 96 |
+
Facebook Notification,You have 3 new friend requests,Social
|
| 97 |
+
Instagram Like,Someone liked your post,Social
|
| 98 |
+
Twitter Mention,You were mentioned in a tweet,Social
|
| 99 |
+
LinkedIn Message,You have a new LinkedIn message,Social
|
| 100 |
+
YouTube Comment,Someone commented on your video,Social
|
| 101 |
+
Snapchat Snap,You received a new snap,Social
|
| 102 |
+
TikTok Follower,You have a new follower on TikTok,Social
|
| 103 |
+
Reddit Reply,Your comment received a reply,Social
|
| 104 |
+
Pinterest Pin,Your pin has been saved by someone,Social
|
| 105 |
+
WhatsApp Message,You have a new message on WhatsApp,Social
|
| 106 |
+
Meeting Agenda,Please review the agenda before the meeting,Work
|
| 107 |
+
Client Call,Your client call is scheduled for tomorrow,Work
|
| 108 |
+
Project Update,Project milestones updated in the tracker,Work
|
| 109 |
+
Team Outing,Team outing planned for Friday evening,Work
|
| 110 |
+
Budget Review,Please review the updated budget,Work
|
| 111 |
+
Training Session,Mandatory training session tomorrow,Work
|
| 112 |
+
Task Reminder,Reminder: Complete the assigned task,Work
|
| 113 |
+
Presentation Slides,Slides for Monday presentation attached,Work
|
| 114 |
+
Conference Registration,Register for the upcoming conference,Work
|
| 115 |
+
Report Submission,Submit your quarterly report,Work
|
| 116 |
+
Family Reunion,Don’t forget the family reunion this weekend,Personal
|
| 117 |
+
Grocery Shopping,Remember to buy groceries,Personal
|
| 118 |
+
Birthday Party,You are invited to a birthday party,Personal
|
| 119 |
+
Yoga Class,Your yoga class starts at 7 AM,Personal
|
| 120 |
+
Friend Call,Call your friend in the evening,Personal
|
| 121 |
+
Music Concert,Tickets booked for the concert,Personal
|
| 122 |
+
Weekend Trip,Plan for the weekend trip,Personal
|
| 123 |
+
Pet Vaccination,Your pet vaccination appointment is scheduled,Personal
|
| 124 |
+
Home Repair,Plumber will arrive tomorrow,Personal
|
| 125 |
+
Car Insurance,Car insurance renewal due next month,Personal
|
| 126 |
+
Special Discount,Limited time special discount on electronics,Promotions
|
| 127 |
+
Summer Sale,Hot summer sale starts now,Promotions
|
| 128 |
+
Flash Offer,Flash offer: 30% off on all items,Promotions
|
| 129 |
+
Deal of the Day,Grab the deal of the day now,Promotions
|
| 130 |
+
Promo Code,Use code EXTRA10 to get 10% off,Promotions
|
| 131 |
+
Buy Now,Limited stock available,Promotions
|
| 132 |
+
Seasonal Sale,Seasonal sale ending soon,Promotions
|
| 133 |
+
Discount Voucher,Your discount voucher is valid for one week,Promotions
|
| 134 |
+
Clearance Offer,Clearance offer on all items,Promotions
|
| 135 |
+
Exclusive Offer,Exclusive offer for loyal customers,Promotions
|
| 136 |
+
Package Shipped,Your package is on the way,Updates
|
| 137 |
+
Delivery Scheduled,Delivery scheduled for tomorrow,Updates
|
| 138 |
+
Tracking Info,Track your shipment online,Updates
|
| 139 |
+
Subscription Confirmation,Your subscription has been confirmed,Updates
|
| 140 |
+
Account Update,Your account details have been updated,Updates
|
| 141 |
+
Flight Reminder,Reminder: Flight departs at 6 PM,Updates
|
| 142 |
+
Service Notification,Service update: New features added,Updates
|
| 143 |
+
System Alert,Alert: Software update required,Updates
|
| 144 |
+
Payment Confirmation,Payment received successfully,Updates
|
| 145 |
+
Security Alert,Unusual login detected,Updates
|
| 146 |
+
Friend Request,You have a new friend request,Social
|
| 147 |
+
Post Like,Someone liked your social media post,Social
|
| 148 |
+
New Message,You received a new message on Messenger,Social
|
| 149 |
+
Comment Reply,Someone replied to your comment,Social
|
| 150 |
+
Follower Alert,You have a new follower,Social
|
| 151 |
+
Video Like,Someone liked your uploaded video,Social
|
| 152 |
+
Event Invite,You are invited to an event,Social
|
| 153 |
+
Group Message,New message in your group,Social
|
| 154 |
+
Snap Notification,You have a new snap,Social
|
| 155 |
+
Story View,Someone viewed your story,Social
|
| 156 |
+
Newsletter Update,Company newsletter: October edition,Updates
|
| 157 |
+
Payment Reminder,Reminder: Pay your utility bill,Updates
|
| 158 |
+
Appointment Reminder,Doctor appointment reminder,Updates
|
| 159 |
+
Workshop Invite,Invitation to workshop tomorrow,Work
|
| 160 |
+
Project Kickoff,Project kickoff meeting scheduled,Work
|
| 161 |
+
Client Feedback Request,Please provide feedback for client project,Work
|
| 162 |
+
Team Celebration,Team celebration planned for Friday,Work
|
| 163 |
+
Training Reminder,Reminder: Complete online training session,Work
|
| 164 |
+
Weekly Sync,Weekly team sync scheduled,Work
|
| 165 |
+
Monthly Report,Monthly report submission due,Work
|
| 166 |
+
Birthday Reminder,Wish your colleague a happy birthday,Personal
|
| 167 |
+
Dinner Invitation,Dinner at my place tonight,Personal
|
| 168 |
+
Weekend Plans,Plan your weekend activities,Personal
|
| 169 |
+
Concert Tickets,Tickets booked for music concert,Personal
|
| 170 |
+
Yoga Reminder,Yoga class starts at 6 AM,Personal
|
deploy.sh
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# This is a shell script to automate the deployment process to Hugging Face.
|
| 4 |
+
# The 'echo' commands just print messages to the terminal so we can see the progress.
|
| 5 |
+
|
| 6 |
+
echo "-------------------------------------"
|
| 7 |
+
echo "Starting deployment to Hugging Face..."
|
| 8 |
+
echo "-------------------------------------"
|
| 9 |
+
|
| 10 |
+
# Step 1: Add all new and changed files to Git
|
| 11 |
+
echo "=> Adding all files..."
|
| 12 |
+
git add .
|
| 13 |
+
|
| 14 |
+
# Step 2: Commit the changes with a message.
|
| 15 |
+
# You can change the message in the quotes below each time if you want.
|
| 16 |
+
echo "=> Committing files..."
|
| 17 |
+
git commit -m "Update and deploy application"
|
| 18 |
+
|
| 19 |
+
# Step 3: Push the code to the Hugging Face Space.
|
| 20 |
+
# This assumes your remote is named 'space' and your local branch is 'master'.
|
| 21 |
+
# It pushes your local 'master' branch to the 'main' branch on Hugging Face.
|
| 22 |
+
echo "=> Pushing to Hugging Face..."
|
| 23 |
+
git push --force space master:main
|
| 24 |
+
|
| 25 |
+
echo "-------------------------------------"
|
| 26 |
+
echo "✅ Deployment script finished."
|
| 27 |
+
echo "Check your Hugging Face Space for the build status."
|
| 28 |
+
echo "-------------------------------------"
|
predicted_emails.csv
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
subject,body,predicted_folder
|
| 2 |
+
Team Standup Reminder,Please join the daily standup meeting at 10 AM.,Work
|
| 3 |
+
50% Off on Shoes,Grab the latest offer on sneakers.,Promotions
|
| 4 |
+
Mom's Birthday,Don't forget to call mom today.,Personal
|
| 5 |
+
Your Amazon Order,Your order has been shipped.,Updates
|
| 6 |
+
Project Deadline,Reminder: Submit the project by tomorrow.,Work
|
| 7 |
+
Weekend Plans,Are we still on for the hiking trip this weekend?,Personal
|
| 8 |
+
Invoice #12345,Your invoice has been generated and attached.,Updates
|
| 9 |
+
Dinner Invitation,Join us for dinner at 7 PM tonight.,Personal
|
requirements.txt
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
accelerate==1.10.1
|
| 2 |
+
aiofiles==24.1.0
|
| 3 |
+
aiohappyeyeballs==2.6.1
|
| 4 |
+
aiohttp==3.12.15
|
| 5 |
+
aiosignal==1.4.0
|
| 6 |
+
annotated-types==0.7.0
|
| 7 |
+
anyio==4.11.0
|
| 8 |
+
attrs==25.3.0
|
| 9 |
+
audioop-lts==0.2.2
|
| 10 |
+
beautifulsoup4==4.14.2
|
| 11 |
+
Brotli==1.1.0
|
| 12 |
+
certifi==2025.8.3
|
| 13 |
+
charset-normalizer==3.4.3
|
| 14 |
+
click==8.3.0
|
| 15 |
+
colorama==0.4.6
|
| 16 |
+
datasets==4.1.1
|
| 17 |
+
dill==0.4.0
|
| 18 |
+
fastapi==0.118.0
|
| 19 |
+
ffmpy==0.6.1
|
| 20 |
+
filelock==3.19.1
|
| 21 |
+
frozenlist==1.7.0
|
| 22 |
+
fsspec==2025.9.0
|
| 23 |
+
gradio==5.48.0
|
| 24 |
+
gradio_client==1.13.3
|
| 25 |
+
groovy==0.1.2
|
| 26 |
+
h11==0.16.0
|
| 27 |
+
httpcore==1.0.9
|
| 28 |
+
httpx==0.28.1
|
| 29 |
+
huggingface-hub==0.35.3
|
| 30 |
+
idna==3.10
|
| 31 |
+
Jinja2==3.1.6
|
| 32 |
+
joblib==1.5.2
|
| 33 |
+
markdown-it-py==4.0.0
|
| 34 |
+
MarkupSafe==3.0.3
|
| 35 |
+
mdurl==0.1.2
|
| 36 |
+
mpmath==1.3.0
|
| 37 |
+
multidict==6.6.4
|
| 38 |
+
multiprocess==0.70.16
|
| 39 |
+
networkx==3.5
|
| 40 |
+
numpy==2.3.3
|
| 41 |
+
orjson==3.11.3
|
| 42 |
+
packaging==25.0
|
| 43 |
+
pandas==2.3.3
|
| 44 |
+
pillow==11.3.0
|
| 45 |
+
propcache==0.3.2
|
| 46 |
+
psutil==7.1.0
|
| 47 |
+
pyarrow==21.0.0
|
| 48 |
+
pydantic==2.11.9
|
| 49 |
+
pydantic_core==2.33.2
|
| 50 |
+
pydub==0.25.1
|
| 51 |
+
Pygments==2.19.2
|
| 52 |
+
python-dateutil==2.9.0.post0
|
| 53 |
+
python-dotenv==1.1.1
|
| 54 |
+
python-multipart==0.0.20
|
| 55 |
+
pytz==2025.2
|
| 56 |
+
PyYAML==6.0.3
|
| 57 |
+
regex==2025.9.18
|
| 58 |
+
requests==2.32.5
|
| 59 |
+
rich==14.1.0
|
| 60 |
+
ruff==0.13.2
|
| 61 |
+
safehttpx==0.1.6
|
| 62 |
+
safetensors==0.6.2
|
| 63 |
+
scikit-learn==1.7.2
|
| 64 |
+
scipy==1.16.2
|
| 65 |
+
semantic-version==2.10.0
|
| 66 |
+
setuptools==65.5.0
|
| 67 |
+
shellingham==1.5.4
|
| 68 |
+
six==1.17.0
|
| 69 |
+
sniffio==1.3.1
|
| 70 |
+
soupsieve==2.8
|
| 71 |
+
starlette==0.48.0
|
| 72 |
+
sympy==1.14.0
|
| 73 |
+
threadpoolctl==3.6.0
|
| 74 |
+
tokenizers==0.22.1
|
| 75 |
+
tomlkit==0.13.3
|
| 76 |
+
torch==2.8.0
|
| 77 |
+
tqdm==4.67.1
|
| 78 |
+
transformers==4.56.2
|
| 79 |
+
typer==0.19.2
|
| 80 |
+
typing-inspection==0.4.2
|
| 81 |
+
typing_extensions==4.15.0
|
| 82 |
+
tzdata==2025.2
|
| 83 |
+
urllib3==2.5.0
|
| 84 |
+
uvicorn==0.37.0
|
| 85 |
+
websockets==15.0.1
|
| 86 |
+
xxhash==3.5.0
|
| 87 |
+
yarl==1.20.1
|