Spaces:
Sleeping
Sleeping
File size: 6,603 Bytes
f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 f74885f cd175e4 b73aaf7 cd175e4 b73aaf7 cd175e4 b73aaf7 cd175e4 b73aaf7 cd175e4 92a72e3 cd175e4 8cabe9f cd175e4 f74885f cd175e4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | import os
import json
from openai import OpenAI
from env import EmailSortingEnv
# ============================================
# SETUP β Read environment variables
# ============================================
API_BASE_URL = os.environ.get("API_BASE_URL", "https://api.openai.com/v1")
MODEL_NAME = os.environ.get("MODEL_NAME", "gpt-4o-mini")
HF_TOKEN = os.environ.get("HF_TOKEN", "")
# Initialize OpenAI client
client = OpenAI(
base_url=API_BASE_URL,
api_key=HF_TOKEN if HF_TOKEN else "dummy-key"
)
# ============================================
# AI AGENT β Asks LLM to classify email
# ============================================
def ask_llm_to_classify(email: dict) -> str:
"""
Send email to LLM and get classification.
Returns: 'spam', 'important', or 'promotion'
"""
prompt = f"""You are an email classification assistant.
Classify the following email into exactly ONE of these categories:
- spam: unwanted, scam, phishing, prize winning, fake offers
- important: work emails, order updates, bank alerts from real banks, newsletters
- promotion: genuine sale offers, discount emails from real shops
Email Details:
Subject: {email['subject']}
From: {email['sender']}
Body: {email['body']}
Reply with ONLY one word β either: spam, important, or promotion
Do not explain. Just one word."""
try:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[
{
"role": "system",
"content": "You are an email classifier. Reply with only one word: spam, important, or promotion."
},
{
"role": "user",
"content": prompt
}
],
max_tokens=10,
temperature=0.0
)
# Extract the answer
answer = response.choices[0].message.content.strip().lower()
# Clean up answer β only keep valid categories
if "spam" in answer:
return "spam"
elif "promotion" in answer:
return "promotion"
elif "important" in answer:
return "important"
else:
return "spam" # Default fallback
except Exception as e:
print(f"LLM Error: {e}")
# Fallback to simple rule-based classification
return fallback_classify(email)
def fallback_classify(email: dict) -> str:
"""
Simple rule-based fallback if LLM fails.
"""
subject = email["subject"].lower()
body = email["body"].lower()
sender = email["sender"].lower()
spam_keywords = ["won", "free", "prize", "urgent", "money",
"congratulations", "claim", "earn", "selected",
"suspended", "verify", "action required"]
promo_keywords = ["off", "sale", "deal", "discount", "shop",
"offer", "save", "limited time"]
spam_score = sum(1 for kw in spam_keywords if kw in subject or kw in body)
promo_score = sum(1 for kw in promo_keywords if kw in subject or kw in body)
suspicious_domain = any(d in sender for d in [".xyz", ".tk", "-secure", "-alert"])
if spam_score >= 2 or suspicious_domain:
return "spam"
elif promo_score >= 2:
return "promotion"
else:
return "important"
# ============================================
# MAIN INFERENCE LOOP
# ============================================
def run_inference():
"""
Main function β runs the AI agent for one full episode.
"""
print("=" * 50)
print("Email Sorting Environment β Inference Script")
print("=" * 50)
print(f"Model: {MODEL_NAME}")
print(f"API Base: {API_BASE_URL}")
print("=" * 50)
# Initialize environment
env = EmailSortingEnv()
state = env.reset()
print(f"\nStarting episode β max {state['max_steps']} steps\n")
step_results = []
print(f"[START] task=email_sorting", flush=True)
# Run until episode is done
while not state["done"]:
current_step = state["step"] + 1
email = state["email"]
print(f"Subject: {email['subject']}")
print(f"From: {email['sender']}")
# Ask AI to classify
action = ask_llm_to_classify(email)
# Take step in environment
next_state, reward, done, info = env.step(action)
result = info.get("result", "N/A")
print(f"[STEP] step={current_step} action={action} reward={reward} result={result}", flush=True)
step_results.append({
"step": current_step,
"subject": email["subject"],
"action": action,
"reward": reward,
"result": result
})
state = next_state
# ============================================
# FINAL RESULTS
# ============================================
total_reward = state["total_reward"]
total_steps = state["step"]
correct_count = sum(1 for r in step_results if r["result"] == "correct")
print("\n" + "=" * 50)
print("EPISODE COMPLETE")
print("=" * 50)
print(f"Total Steps: {total_steps}")
print(f"Correct: {correct_count}/{total_steps}")
print(f"Accuracy: {round(correct_count/total_steps*100, 1)}%")
print(f"Total Reward: {total_reward}")
print("=" * 50)
results = {
"model": MODEL_NAME,
"total_steps": total_steps,
"correct": correct_count,
"accuracy": round(correct_count / total_steps * 100, 1),
"total_reward": total_reward,
"step_details": step_results
}
score = round(correct_count / total_steps, 4) if total_steps > 0 else 0.0
print(f"[END] task=email_sorting score={score} steps={total_steps}", flush=True)
return results
# ============================================
# RUN GRADERS ALSO
# ============================================
def run_with_graders():
"""Run inference + all graders and show combined score."""
from graders import run_all_graders
print("\n--- Running Inference ---\n")
inference_results = run_inference()
print("\n--- Running Graders ---\n")
grader_results = run_all_graders()
print("\n" + "=" * 50)
print("FINAL COMBINED RESULTS")
print("=" * 50)
print(f"Inference Accuracy: {inference_results['accuracy']}%")
print(f"Grader Average Score: {grader_results['average_score']}")
print("=" * 50)
# ============================================
# ENTRY POINT
# ============================================
if __name__ == "__main__":
run_with_graders()
|