DevNumb commited on
Commit
ae350fd
·
verified ·
1 Parent(s): c50f44a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +292 -8
app.py CHANGED
@@ -1,17 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  === COORDINATION SUMMARY ===
2
- Production line downtime reported requiring immediate technical intervention.
3
 
4
  === DEPARTMENTS INVOLVED ===
5
- • Production – technical inspection
6
- • Administration – approval of maintenance budget
7
 
8
  === RECOMMENDED ACTION PLAN ===
9
- 1. Inspect equipment
10
- 2. Log maintenance ticket
11
- 3. Schedule repair within 24 hours
12
 
13
  === PRIORITY LEVEL ===
14
- High Direct operational impact
15
 
16
  === FOLLOW-UP ===
17
- Daily status update until resolution
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import os
4
+ import base64
5
+ import io
6
+ import datetime
7
+ from PIL import Image
8
+
9
+ # =========================================================
10
+ # ENV CONFIG
11
+ # =========================================================
12
+
13
+ OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
14
+ BREVO_API_KEY = os.getenv("BREVO_API_KEY")
15
+ BREVO_FROM_EMAIL = os.getenv("BREVO_FROM_EMAIL", "noreply@company.com")
16
+ DEFAULT_REPORT_EMAIL = os.getenv("REPORT_EMAIL", "")
17
+
18
+ conversation_history = []
19
+ current_report_email = DEFAULT_REPORT_EMAIL
20
+
21
+ # =========================================================
22
+ # DEPARTMENTS
23
+ # =========================================================
24
+
25
+ departments = {
26
+ "administration": {
27
+ "name": "Administration",
28
+ "email": os.getenv("ADMIN_EMAIL", "")
29
+ },
30
+ "production": {
31
+ "name": "Production",
32
+ "email": os.getenv("PRODUCTION_EMAIL", "")
33
+ },
34
+ "magazine": {
35
+ "name": "Magazine Management",
36
+ "email": os.getenv("MAGAZINE_EMAIL", "")
37
+ }
38
+ }
39
+
40
+ # =========================================================
41
+ # EMAIL (BREVO)
42
+ # =========================================================
43
+
44
+ def send_email_brevo_api(to_email, subject, html):
45
+ if not BREVO_API_KEY:
46
+ return "❌ Brevo API key missing"
47
+
48
+ r = requests.post(
49
+ "https://api.brevo.com/v3/smtp/email",
50
+ headers={
51
+ "accept": "application/json",
52
+ "content-type": "application/json",
53
+ "api-key": BREVO_API_KEY
54
+ },
55
+ json={
56
+ "sender": {
57
+ "name": "AI Coordination System",
58
+ "email": BREVO_FROM_EMAIL
59
+ },
60
+ "to": [{"email": to_email}],
61
+ "subject": subject,
62
+ "htmlContent": html
63
+ },
64
+ timeout=20
65
+ )
66
+
67
+ return "✅ Email sent" if r.status_code == 201 else f"❌ {r.text}"
68
+
69
+
70
+ # =========================================================
71
+ # LLM ANALYSIS (PROFESSIONAL VERSION)
72
+ # =========================================================
73
+
74
+ SYSTEM_PROMPT = """
75
+ You are an Enterprise Operations Coordination Assistant.
76
+
77
+ Your role:
78
+ - Analyze inter-department requests
79
+ - Write formally and professionally
80
+ - Be concise, structured, executive-style
81
+ - No emojis
82
+ - No casual language
83
+ - Provide actionable steps only
84
+
85
+ Always follow the exact output structure requested.
86
+ """
87
+
88
+ def call_llm(messages):
89
+ r = requests.post(
90
+ "https://openrouter.ai/api/v1/chat/completions",
91
+ headers={
92
+ "Authorization": f"Bearer {OPENROUTER_API_KEY}",
93
+ "Content-Type": "application/json",
94
+ },
95
+ json={
96
+ "model": "google/gemma-3-27b-it:free",
97
+ "messages": messages,
98
+ "temperature": 0.1,
99
+ "max_tokens": 800
100
+ },
101
+ timeout=60
102
+ )
103
+
104
+ if r.status_code == 200:
105
+ return r.json()["choices"][0]["message"]["content"]
106
+
107
+ return "LLM analysis failed."
108
+
109
+
110
+ def analyze_coordination_needs(message, department, user_name, image=None):
111
+
112
+ if image:
113
+ buffer = io.BytesIO()
114
+ image.save(buffer, format="PNG")
115
+ img64 = base64.b64encode(buffer.getvalue()).decode()
116
+
117
+ user_prompt = f"""
118
+ Analyze the following request and attached image.
119
+
120
+ Department: {department}
121
+ Requestor: {user_name}
122
+ Message: {message}
123
+
124
+ Return:
125
+
126
+ === SUMMARY ===
127
+ Brief executive summary
128
+
129
+ === IMAGE OBSERVATIONS ===
130
+ Relevant findings
131
+
132
+ === DEPARTMENTS INVOLVED ===
133
+ Bullets
134
+
135
+ === ACTION PLAN ===
136
+ Numbered steps
137
+
138
+ === PRIORITY ===
139
+ Low | Medium | High with reason
140
+
141
+ === FOLLOW-UP ===
142
+ Next checkpoints
143
+ """
144
+
145
+ return call_llm([
146
+ {"role": "system", "content": SYSTEM_PROMPT},
147
+ {
148
+ "role": "user",
149
+ "content": [
150
+ {"type": "text", "text": user_prompt},
151
+ {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img64}"}}
152
+ ]
153
+ }
154
+ ])
155
+
156
+ else:
157
+
158
+ user_prompt = f"""
159
+ Analyze this inter-department request.
160
+
161
+ Department: {department}
162
+ Requestor: {user_name}
163
+ Message: {message}
164
+
165
+ Return:
166
+
167
  === COORDINATION SUMMARY ===
168
+ Short summary
169
 
170
  === DEPARTMENTS INVOLVED ===
171
+ Bullets
 
172
 
173
  === RECOMMENDED ACTION PLAN ===
174
+ Numbered steps
 
 
175
 
176
  === PRIORITY LEVEL ===
177
+ Low | Medium | High with justification
178
 
179
  === FOLLOW-UP ===
180
+ Monitoring or reporting
181
+ """
182
+
183
+ return call_llm([
184
+ {"role": "system", "content": SYSTEM_PROMPT},
185
+ {"role": "user", "content": user_prompt}
186
+ ])
187
+
188
+
189
+ # =========================================================
190
+ # HISTORY
191
+ # =========================================================
192
+
193
+ def add_history(entry):
194
+ conversation_history.append(entry)
195
+ if len(conversation_history) > 50:
196
+ conversation_history.pop(0)
197
+
198
+
199
+ # =========================================================
200
+ # MAIN PROCESS
201
+ # =========================================================
202
+
203
+ def process_request(name, department, message, image, recipient, send_email, urgency):
204
+
205
+ if not name or not message or not department:
206
+ return "Please complete all required fields."
207
+
208
+ analysis = analyze_coordination_needs(message, department, name, image)
209
+
210
+ response = f"""
211
+ Requestor: {name}
212
+ Department: {departments[department]['name']}
213
+
214
+ {analysis}
215
+ """
216
+
217
+ email_status = ""
218
+
219
+ if send_email and recipient:
220
+ recipient_email = departments[recipient]["email"] or current_report_email
221
+
222
+ html = f"""
223
+ <pre style="font-family:Arial">{response}</pre>
224
+ """
225
+
226
+ email_status = send_email_brevo_api(
227
+ recipient_email,
228
+ f"[{urgency}] Coordination Request",
229
+ html
230
+ )
231
+
232
+ response += f"\n\nEmail Status: {email_status}"
233
+
234
+ add_history({
235
+ "time": datetime.datetime.now().isoformat(),
236
+ "user": name,
237
+ "department": department,
238
+ "message": message,
239
+ "analysis": analysis
240
+ })
241
+
242
+ return response
243
+
244
+
245
+ # =========================================================
246
+ # STATS
247
+ # =========================================================
248
+
249
+ def stats():
250
+ return f"Total interactions: {len(conversation_history)}"
251
+
252
+
253
+ def clear():
254
+ conversation_history.clear()
255
+ return "History cleared."
256
+
257
+
258
+ # =========================================================
259
+ # UI
260
+ # =========================================================
261
+
262
+ with gr.Blocks(theme=gr.themes.Soft(), title="AI Coordination System") as ui:
263
+
264
+ gr.Markdown("# 🏢 AI Department Coordination System")
265
+
266
+ with gr.Row():
267
+
268
+ with gr.Column(scale=1):
269
+
270
+ name = gr.Textbox(label="Name")
271
+ dept = gr.Dropdown(list(departments.keys()), label="Department")
272
+ message = gr.Textbox(lines=4, label="Request")
273
+ image = gr.Image(type="pil", label="Optional Image")
274
+
275
+ recipient = gr.Dropdown(list(departments.keys()), label="Notify Department")
276
+ urgency = gr.Dropdown(["Low", "Medium", "High"], value="Medium")
277
+
278
+ send_email = gr.Checkbox(label="Send Email", value=True)
279
+
280
+ submit = gr.Button("Analyze", variant="primary")
281
+ stats_btn = gr.Button("Stats")
282
+ clear_btn = gr.Button("Clear")
283
+
284
+ with gr.Column(scale=2):
285
+ output = gr.Textbox(lines=20, show_copy_button=True)
286
+
287
+ submit.click(
288
+ process_request,
289
+ inputs=[name, dept, message, image, recipient, send_email, urgency],
290
+ outputs=output
291
+ )
292
+
293
+ stats_btn.click(stats, outputs=output)
294
+ clear_btn.click(clear, outputs=output)
295
+
296
+
297
+ # =========================================================
298
+
299
+ if __name__ == "__main__":
300
+ ui.launch()
301
+