Spaces:
Sleeping
Sleeping
| import random | |
| from typing import Dict, Any, Tuple | |
| # Sample emails dataset | |
| EMAILS = [ | |
| # Easy - Obvious spam | |
| {"subject": "YOU WON $1,000,000!!!", "body": "Click here to claim your prize money now!", "sender": "prize@randomsite.xyz", "label": "spam", "difficulty": "easy"}, | |
| {"subject": "FREE iPhone 15 for you!", "body": "Congratulations! You have been selected. Send your details.", "sender": "free@giveaway123.com", "label": "spam", "difficulty": "easy"}, | |
| {"subject": "URGENT: Make money fast", "body": "Work from home earn 50000 per day no experience needed.", "sender": "jobs@quickmoney.tk", "label": "spam", "difficulty": "easy"}, | |
| # Medium - Newsletter vs Promotion | |
| {"subject": "Your weekly newsletter", "body": "Here are this week's top stories in technology and science.", "sender": "newsletter@techdigest.com", "label": "important", "difficulty": "medium"}, | |
| {"subject": "50% OFF this weekend only!", "body": "Shop now and save big on electronics. Limited time offer.", "sender": "deals@amazon.com", "label": "promotion", "difficulty": "medium"}, | |
| {"subject": "Your order has been shipped", "body": "Your recent order #12345 has been dispatched. Track here.", "sender": "orders@flipkart.com", "label": "important", "difficulty": "medium"}, | |
| # Hard - Phishing disguised as bank | |
| {"subject": "Your SBI account is suspended", "body": "Dear customer, your account is suspended. Login immediately at sbi-secure-login.xyz", "sender": "support@sbi-alerts.net", "label": "spam", "difficulty": "hard"}, | |
| {"subject": "Action required: Verify your UPI", "body": "Your UPI ID needs verification. Click here to verify now or service will stop.", "sender": "noreply@paytm-secure.org", "label": "spam", "difficulty": "hard"}, | |
| {"subject": "Meeting rescheduled to 3pm", "body": "Hi, just wanted to let you know the team meeting is moved to 3pm today.", "sender": "manager@company.com", "label": "important", "difficulty": "hard"}, | |
| ] | |
| CATEGORIES = ["spam", "important", "promotion"] | |
| class EmailSortingEnv: | |
| def __init__(self): | |
| self.current_email = None | |
| self.current_step = 0 | |
| self.max_steps = 10 | |
| self.total_reward = 0.0 | |
| self.done = False | |
| self.history = [] | |
| def reset(self) -> Dict[str, Any]: | |
| """Reset environment to start a new episode.""" | |
| self.current_step = 0 | |
| self.total_reward = 0.0 | |
| self.done = False | |
| self.history = [] | |
| self.current_email = random.choice(EMAILS) | |
| return self.state() | |
| def state(self) -> Dict[str, Any]: | |
| """Return current state of the environment.""" | |
| if self.current_email is None: | |
| self.reset() | |
| return { | |
| "email": { | |
| "subject": self.current_email["subject"], | |
| "body": self.current_email["body"], | |
| "sender": self.current_email["sender"] | |
| }, | |
| "step": self.current_step, | |
| "max_steps": self.max_steps, | |
| "total_reward": round(self.total_reward, 2), | |
| "done": self.done, | |
| "valid_actions": CATEGORIES | |
| } | |
| def step(self, action: str) -> Tuple[Dict[str, Any], float, bool, Dict]: | |
| """ | |
| Take a step: classify the email. | |
| action: one of 'spam', 'important', 'promotion' | |
| Returns: (next_state, reward, done, info) | |
| """ | |
| if self.done: | |
| return self.state(), 0.0, True, {"error": "Episode already done. Call reset()."} | |
| if action not in CATEGORIES: | |
| reward = -0.2 | |
| info = {"error": f"Invalid action. Choose from {CATEGORIES}"} | |
| else: | |
| correct_label = self.current_email["label"] | |
| difficulty = self.current_email["difficulty"] | |
| if action == correct_label: | |
| # Reward based on difficulty | |
| if difficulty == "easy": | |
| reward = 0.5 | |
| elif difficulty == "medium": | |
| reward = 0.75 | |
| else: # hard | |
| reward = 1.0 | |
| info = {"result": "correct", "difficulty": difficulty} | |
| else: | |
| # Penalty | |
| if difficulty == "easy": | |
| reward = -0.5 | |
| elif difficulty == "medium": | |
| reward = -0.3 | |
| else: | |
| reward = -0.1 | |
| info = {"result": "wrong", "correct_label": correct_label, "difficulty": difficulty} | |
| self.total_reward += reward | |
| self.current_step += 1 | |
| self.history.append({ | |
| "step": self.current_step, | |
| "email_subject": self.current_email["subject"], | |
| "action": action, | |
| "reward": reward | |
| }) | |
| # Move to next email | |
| if self.current_step >= self.max_steps: | |
| self.done = True | |
| else: | |
| self.current_email = random.choice(EMAILS) | |
| return self.state(), round(reward, 2), self.done, info | |
| # For testing - run this file directly | |
| if __name__ == "__main__": | |
| env = EmailSortingEnv() | |
| state = env.reset() | |
| print("=== Email Sorting Environment Test ===") | |
| print(f"Email: {state['email']['subject']}") | |
| print(f"From: {state['email']['sender']}") | |
| next_state, reward, done, info = env.step("spam") | |
| print(f"\nAction: spam") | |
| print(f"Reward: {reward}") | |
| print(f"Result: {info}") | |
| print("\nenv.py is working correctly!") |