scmlewis commited on
Commit
2c3b426
·
verified ·
1 Parent(s): 0fdd881

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -151
app.py CHANGED
@@ -2,38 +2,11 @@ import os
2
  import gradio as gr
3
  import requests
4
  import json
5
- from datetime import datetime
6
 
7
  GROQ_API_KEY = os.getenv("GROQ_API_KEY")
8
  GROQ_COMPLETION_URL = "https://api.groq.com/openai/v1/chat/completions"
9
  GROQ_MODEL = "llama-3.1-8b-instant"
10
 
11
- # Dummy sender risk DB
12
- SENDER_REPUTATION = {
13
- "it@company.com": "Trusted",
14
- "accounts@supplier.com": "Trusted",
15
- "spammer@promo.com": "Suspicious",
16
- "unknown@phish.com": "Flagged"
17
- }
18
-
19
- # In-memory structures
20
- classification_history = []
21
- analytics_counter = {}
22
-
23
- default_categories = ["Support Request", "Sales Inquiry", "Finance/Billing", "Urgent Incident", "Spam/Marketing"]
24
-
25
- default_templates = [
26
- "Thank you for your email. We are looking into your request and will reply shortly.",
27
- "We have received your billing inquiry and will review your account information.",
28
- "Your support request has been escalated to our technical team."
29
- ]
30
-
31
- def get_sender(email_txt):
32
- for line in email_txt.splitlines():
33
- if line.lower().startswith("from:"):
34
- return line.split(":",1)[-1].strip()
35
- return ""
36
-
37
  def groq_completion(prompt, sys_prompt=None):
38
  headers = {
39
  "Authorization": f"Bearer {GROQ_API_KEY}",
@@ -42,7 +15,7 @@ def groq_completion(prompt, sys_prompt=None):
42
  body = {
43
  "model": GROQ_MODEL,
44
  "messages": [
45
- {"role": "system", "content": sys_prompt or "You are a helpful business email assistant."},
46
  {"role": "user", "content": prompt}
47
  ],
48
  "temperature": 0.3,
@@ -58,21 +31,19 @@ def groq_completion(prompt, sys_prompt=None):
58
  print("Groq API response:", response.text)
59
  return "Error"
60
 
61
- def email_classifier_router(email_txt, categories, templates):
62
- sender = get_sender(email_txt)
63
- sender_score = SENDER_REPUTATION.get(sender,"Unknown")
64
- category_prompt = f"Categories (choose one or suggest new): {', '.join(categories)}\n"
65
- template_list = "\n".join([f"- {t}" for t in templates])
66
  prompt = (
67
- f"{category_prompt}"
68
- "Extract:\n"
69
- "- Category\n- Priority\n- Suggested Recipient\n- Professional draft response\n"
70
- "- Summary (one sentence)\n- Action Items (numbered list)\n- Entities: invoice numbers, dates, customer names if present.\n"
71
- "Format as single compact JSON dictionary.\n"
72
- '{"Category":"...", "Priority":"...", "Suggested Recipient":"...", "Draft Response":"...", "Summary":"...", "Action Items":["..."], "Entities":{"Invoice":"","Date":"","Customer":""}}\n\n'
73
- f"{email_txt}\n"
74
- "If reply, you may use these reply templates as inspiration:\n"
75
- f"{template_list}"
 
 
76
  )
77
  raw_result = groq_completion(prompt)
78
  try:
@@ -85,117 +56,29 @@ def email_classifier_router(email_txt, categories, templates):
85
  "Suggested Recipient": "Error",
86
  "Draft Response": raw_result,
87
  "Summary": "Error",
88
- "Action Items": ["Error"],
89
- "Entities": {"Invoice":"", "Date":"", "Customer":""}
90
  }
91
- # Store in history & update analytics
92
- now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
93
- entry = {
94
- "datetime": now,
95
- "email": email_txt,
96
- "category": output.get("Category",""),
97
- "priority": output.get("Priority",""),
98
- "summary": output.get("Summary",""),
99
- "draft": output.get("Draft Response",""),
100
- "recipient": output.get("Suggested Recipient",""),
101
- "entities": output.get("Entities",{}),
102
- "actions": output.get("Action Items",[]),
103
- "sender": sender,
104
- "risk": sender_score
105
- }
106
- classification_history.append(entry)
107
- analytics_counter[output.get("Category","Other")] = analytics_counter.get(output.get("Category","Other"),0)+1
108
- return entry
109
-
110
- def show_history():
111
- res = []
112
- for entry in reversed(classification_history):
113
- block = gr.Group()
114
- summary = entry['summary']
115
- txt = f"**Category:** {entry['category']} \n**Priority:** {entry['priority']} \n{summary}"
116
- btns = gr.Row()
117
- block.append(gr.Markdown(txt))
118
- block.append(btns)
119
- res.append(block)
120
- return res
121
-
122
- def copy_email(entry_idx):
123
- if 0 <= entry_idx < len(classification_history):
124
- return classification_history[entry_idx]['email']
125
- return ""
126
-
127
- def load_email(entry_idx):
128
- if 0 <= entry_idx < len(classification_history):
129
- return classification_history[entry_idx]['email']
130
- return ""
131
-
132
- def clear_history():
133
- classification_history.clear()
134
- analytics_counter.clear()
135
- return gr.update(visible=True)
136
 
137
  with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
138
- # Editable categories and template management
139
- with gr.Row():
140
- gr.Markdown("📝 **Manage Categories and Reply Templates**")
141
- categories_box = gr.Textbox(label="Categories (comma separated)", value=", ".join(default_categories))
142
- templates_box = gr.Textbox(label="Reply Templates (one per line)", value="\n".join(default_templates), lines=3)
143
-
144
- gr.Markdown("## 📨 Classify & Reply to Emails")
145
- email_box = gr.Textbox(lines=8, label="Paste the entire raw email")
146
- classify_btn = gr.Button("Classify Email", variant="primary")
147
-
148
- results = gr.JSON(label="Classification + Extraction Results")
149
- sender_risk = gr.Textbox(label="Sender Risk Score", interactive=False)
150
- entities = gr.JSON(label="Extracted Entities")
 
151
 
152
- # Template suggester
153
- template_select = gr.Dropdown(choices=default_templates, label="Insert Reply Template")
154
- insert_btn = gr.Button("Insert Template into Draft")
155
-
156
- # History display
157
- gr.Markdown("### 🕒 Classification History")
158
- history_output = gr.Markdown()
159
- clear_btn = gr.Button("Clear History")
160
-
161
- # Basic Analytics
162
- analytics = gr.Markdown(label="Simple Analytics")
163
-
164
- def classify(email, cats, tmps):
165
- cat_list = [c.strip() for c in cats.split(",")]
166
- tmpl_list = [t.strip() for t in tmps.split("\n") if t.strip()]
167
- entry = email_classifier_router(email, cat_list, tmpl_list)
168
- return (entry, entry["risk"], entry["entities"], render_history(classification_history), render_analytics(analytics_counter))
169
-
170
- def render_history(history):
171
- # Render HTML for cards
172
- res = ""
173
- for idx, h in enumerate(reversed(history)):
174
- summary = h['summary']
175
- res += f"""<div style="border:1px solid #333;margin:5px;padding:8px;">
176
- <b>{h['datetime']}</b> <br>
177
- <b>Category:</b> <span style='background:#448; color:white; border-radius:4px; padding:2px 8px;'>{h['category']}</span>
178
- <b>Priority:</b> <span style='background:#aa4; color:black; border-radius:4px; padding:2px 8px;'>{h['priority']}</span>
179
- <br>{summary[:120]}
180
- <br>
181
- <button onclick="navigator.clipboard.writeText({json.dumps(h['draft'])})">Copy Email</button>
182
- <button onclick="navigator.clipboard.writeText({json.dumps(h['email'])})">Load</button>
183
- </div>"""
184
- return res
185
-
186
- def render_analytics(counter):
187
- res = "**Category Counts:**<br>"
188
- for k, v in counter.items():
189
- res += f"{k}: <b>{v}</b><br>"
190
- return res
191
-
192
- classify_btn.click(
193
- classify,
194
- inputs=[email_box, categories_box, templates_box],
195
- outputs=[results, sender_risk, entities, history_output, analytics]
196
- )
197
- clear_btn.click(clear_history, None, history_output)
198
- insert_btn.click(lambda t, d: d + "\n" + t, [template_select, email_box], email_box)
199
 
200
- if __name__ == "__main__":
201
- demo.launch()
 
 
2
  import gradio as gr
3
  import requests
4
  import json
 
5
 
6
  GROQ_API_KEY = os.getenv("GROQ_API_KEY")
7
  GROQ_COMPLETION_URL = "https://api.groq.com/openai/v1/chat/completions"
8
  GROQ_MODEL = "llama-3.1-8b-instant"
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  def groq_completion(prompt, sys_prompt=None):
11
  headers = {
12
  "Authorization": f"Bearer {GROQ_API_KEY}",
 
15
  body = {
16
  "model": GROQ_MODEL,
17
  "messages": [
18
+ {"role": "system", "content": sys_prompt or "You are a fast and reliable business email assistant."},
19
  {"role": "user", "content": prompt}
20
  ],
21
  "temperature": 0.3,
 
31
  print("Groq API response:", response.text)
32
  return "Error"
33
 
34
+ def email_classifier_router(raw_email):
 
 
 
 
35
  prompt = (
36
+ "Return ONLY compact JSON for analysis and response.\n"
37
+ "Given the business email below, extract:\n"
38
+ "- Category (Support Request, Sales Inquiry, Finance/Billing, Urgent Incident, Spam/Marketing)\n"
39
+ "- Priority (Low, Medium, High)\n"
40
+ "- Suggested Recipient (department or address)\n"
41
+ "- Professional draft reply\n"
42
+ "- Summary (one sentence)\n"
43
+ "- Action Items (numbered list)\n\n"
44
+ "Format:\n"
45
+ '{"Category":"...", "Priority":"...", "Suggested Recipient":"...", "Draft Response":"...", "Summary":"...", "Action Items":["...","..."]}\n\n'
46
+ f"{raw_email}"
47
  )
48
  raw_result = groq_completion(prompt)
49
  try:
 
56
  "Suggested Recipient": "Error",
57
  "Draft Response": raw_result,
58
  "Summary": "Error",
59
+ "Action Items": ["Error"]
 
60
  }
61
+ return output
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
64
+ gr.Markdown("## 📨 AI Email Classifier & Router\nEasily classify, route, and summarize business emails.")
65
+
66
+ with gr.Row(equal_height=True):
67
+ gr.Markdown("**Load an example:**")
68
+ ex1 = "From: help@company.com\nSubject: Unable to Login\nHi, I can't access my dashboard. Can you help?"
69
+ ex2 = "From: sales@prospect.com\nSubject: Inquiry about pricing\nHi, Can you send over your latest pricing for enterprise?"
70
+ ex3 = "From: accounts@supplier.com\nSubject: Invoice #2024-00123 Due Date Reminder\nDear Valued Client, This is a reminder invoice #2024-00123 for $1,500.00 is due..."
71
+ ex4 = "From: it@company.com\nSubject: Server Down Alert\nURGENT: Database server unreachable since 3AM. Needs escalation."
72
+ ex5 = "From: spammer@promo.com\nSubject: BIG SALE!!!\nDon't miss our special offers!"
73
+ support_button = gr.Button("Support Request")
74
+ sales_button = gr.Button("Sales Inquiry")
75
+ finance_button = gr.Button("Finance / Billing")
76
+ urgent_button = gr.Button("Urgent Incident")
77
+ spam_button = gr.Button("Spam / Marketing")
78
 
79
+ email_box = gr.Textbox(lines=8, label="Paste the entire raw email (including lines like 'From:', 'Subject:', etc.)", elem_id='email_box')
80
+ classify_btn = gr.Button("Classify Email", elem_id='classify_btn', variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
+ with gr.Column():
83
+ gr.Markdown("### ✅ Classification Results")
84
+ category = gr.Textbox(label="Category", elem_id='category