DevNumb commited on
Commit
68dc125
Β·
verified Β·
1 Parent(s): 44c6a74

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +211 -184
app.py CHANGED
@@ -2,157 +2,48 @@ 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
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
 
 
17
  conversation_history = []
 
18
 
19
- # ======================================================
20
- # DEPARTMENTS
21
- # ======================================================
22
-
23
  departments = {
24
- "administration": {"name": "Administration", "email": os.getenv("ADMIN_EMAIL", "")},
25
- "production": {"name": "Production", "email": os.getenv("PRODUCTION_EMAIL", "")},
26
- "magazine": {"name": "Magazine Management", "email": os.getenv("MAGAZINE_EMAIL", "")},
 
 
 
 
 
 
 
 
 
 
 
 
27
  }
28
 
29
  # ======================================================
30
- # EMAIL
31
- # ======================================================
32
-
33
- def send_email_brevo_api(to_email, subject, html):
34
- if not BREVO_API_KEY:
35
- return "Email disabled"
36
-
37
- r = requests.post(
38
- "https://api.brevo.com/v3/smtp/email",
39
- headers={
40
- "accept": "application/json",
41
- "content-type": "application/json",
42
- "api-key": BREVO_API_KEY
43
- },
44
- json={
45
- "sender": {"name": "AI Coordination System", "email": BREVO_FROM_EMAIL},
46
- "to": [{"email": to_email}],
47
- "subject": subject,
48
- "htmlContent": html
49
- }
50
- )
51
-
52
- return "Email sent" if r.status_code == 201 else "Email failed"
53
-
54
-
55
- # ======================================================
56
- # LLM PROFESSIONAL PROMPT
57
- # ======================================================
58
-
59
- SYSTEM_PROMPT = """
60
- You are an Enterprise Operations Coordination Assistant.
61
-
62
- Write professionally and formally.
63
- Be concise, structured, and executive-style.
64
- Do not use emojis or casual language.
65
- Always provide clear action steps.
66
- """
67
-
68
- def call_llm(messages):
69
- r = requests.post(
70
- "https://openrouter.ai/api/v1/chat/completions",
71
- headers={
72
- "Authorization": f"Bearer {OPENROUTER_API_KEY}",
73
- "Content-Type": "application/json",
74
- },
75
- json={
76
- "model": "google/gemma-3-27b-it:free",
77
- "messages": messages,
78
- "temperature": 0.1,
79
- "max_tokens": 800
80
- }
81
- )
82
-
83
- if r.status_code == 200:
84
- return r.json()["choices"][0]["message"]["content"]
85
-
86
- return "LLM request failed"
87
-
88
-
89
- def analyze(message, department, user):
90
-
91
- prompt = f"""
92
- Department: {department}
93
- Requestor: {user}
94
- Message: {message}
95
-
96
- Return strictly:
97
-
98
- === COORDINATION SUMMARY ===
99
- Short executive summary
100
-
101
- === DEPARTMENTS INVOLVED ===
102
- Bullets
103
-
104
- === ACTION PLAN ===
105
- Numbered steps
106
-
107
- === PRIORITY LEVEL ===
108
- Low | Medium | High with justification
109
-
110
- === FOLLOW-UP ===
111
- Next actions
112
- """
113
-
114
- return call_llm([
115
- {"role": "system", "content": SYSTEM_PROMPT},
116
- {"role": "user", "content": prompt}
117
- ])
118
-
119
-
120
- # ======================================================
121
- # CORE LOGIC
122
- # ======================================================
123
-
124
- def process(name, dept, message, img, recipient, send_email, urgency):
125
-
126
- if not name or not dept or not message:
127
- return "Fill all required fields."
128
-
129
- result = analyze(message, dept, name)
130
-
131
- output = f"""
132
- Requestor: {name}
133
- Department: {departments[dept]['name']}
134
-
135
- {result}
136
- """
137
-
138
- if send_email and recipient:
139
- email = departments[recipient]["email"]
140
- status = send_email_brevo_api(email, "Coordination Request", f"<pre>{output}</pre>")
141
- output += f"\n\nEmail status: {status}"
142
-
143
- conversation_history.append(output)
144
- return output
145
-
146
-
147
- # ======================================================
148
- # EXAMPLES (NEW)
149
  # ======================================================
150
 
151
  examples = [
152
  [
153
  "Ali Ben Salah",
154
  "production",
155
- "Packaging machine #4 stopped working and production is blocked. Need urgent maintenance approval.",
156
  None,
157
  "administration",
158
  True,
@@ -161,7 +52,7 @@ examples = [
161
  [
162
  "Sara Trabelsi",
163
  "magazine",
164
- "We need design assets approved before tomorrow's publication. Please coordinate with administration.",
165
  None,
166
  "administration",
167
  True,
@@ -170,7 +61,7 @@ examples = [
170
  [
171
  "Mohamed Kefi",
172
  "administration",
173
- "Budget approval required for new raw materials purchase for next production cycle.",
174
  None,
175
  "production",
176
  True,
@@ -179,7 +70,7 @@ examples = [
179
  [
180
  "Ines Haddad",
181
  "production",
182
- "Quality inspection shows defect rate increased to 7%. Root cause investigation required.",
183
  None,
184
  "administration",
185
  False,
@@ -188,67 +79,203 @@ examples = [
188
  [
189
  "Karim Jaziri",
190
  "magazine",
191
- "Printing vendor delayed delivery. Need alternative supplier coordination.",
192
  None,
193
  "administration",
194
  True,
195
  "High"
196
  ],
197
- [
198
- "Admin Test",
199
- "administration",
200
- "Monthly inter-department performance review meeting preparation.",
201
- None,
202
- "production",
203
- False,
204
- "Low"
205
- ],
206
  ]
207
 
208
  # ======================================================
209
- # UI
210
  # ======================================================
211
 
212
- with gr.Blocks(theme=gr.themes.Soft(), title="AI Coordination System") as ui:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
 
214
- gr.Markdown("# AI Department Coordination System")
 
 
215
 
216
  with gr.Row():
217
-
218
  with gr.Column(scale=1):
219
-
220
- name = gr.Textbox(label="Name")
221
- dept = gr.Dropdown(list(departments.keys()), label="Department")
222
- message = gr.Textbox(label="Request", lines=4)
223
- img = gr.Image(type="pil", label="Optional Image")
224
-
225
- recipient = gr.Dropdown(list(departments.keys()), label="Notify Department")
226
- urgency = gr.Dropdown(["Low", "Medium", "High"], value="Medium")
227
- send_email = gr.Checkbox(label="Send Email", value=True)
228
-
229
- submit = gr.Button("Analyze", variant="primary")
230
-
231
- with gr.Column(scale=2):
232
- output = gr.Textbox(lines=20, show_copy_button=True)
233
-
234
- submit.click(
235
- process,
236
- inputs=[name, dept, message, img, recipient, send_email, urgency],
237
- outputs=output
238
- )
239
-
240
- # =========================
241
- # πŸ”₯ EXAMPLES COMPONENT
242
- # =========================
243
- gr.Markdown("## Quick Test Examples")
244
-
245
- gr.Examples(
246
- examples=examples,
247
- inputs=[name, dept, message, img, recipient, send_email, urgency],
248
- label="Click any example to auto-fill and test"
249
- )
250
-
251
- # ======================================================
252
 
253
  if __name__ == "__main__":
254
- ui.launch()
 
2
  import requests
3
  import os
4
  import base64
5
+ from PIL import Image
6
  import io
7
  import datetime
 
 
 
 
 
8
 
9
+ # Configuration from environment variables
10
  OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
11
+ DEFAULT_REPORT_EMAIL = os.getenv("REPORT_EMAIL")
12
  BREVO_API_KEY = os.getenv("BREVO_API_KEY")
13
+ BREVO_FROM_EMAIL = os.getenv("BREVO_FROM_EMAIL", "noreply@yourdomain.com")
14
 
15
+ # Store conversation history and settings
16
  conversation_history = []
17
+ current_report_email = DEFAULT_REPORT_EMAIL
18
 
19
+ # Department configurations
 
 
 
20
  departments = {
21
+ "administration": {
22
+ "name": "Administration",
23
+ "email": os.getenv("ADMIN_EMAIL", ""),
24
+ "responsibilities": "Overall management, decision making, and coordination"
25
+ },
26
+ "production": {
27
+ "name": "Production",
28
+ "email": os.getenv("PRODUCTION_EMAIL", ""),
29
+ "responsibilities": "Manufacturing, quality control, and production planning"
30
+ },
31
+ "magazine": {
32
+ "name": "Magazine Management",
33
+ "email": os.getenv("MAGAZINE_EMAIL", ""),
34
+ "responsibilities": "Content creation, publishing, and distribution"
35
+ }
36
  }
37
 
38
  # ======================================================
39
+ # TEST EXAMPLES (NON-INTRUSIVE β€” DOES NOT CHANGE LLM)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  # ======================================================
41
 
42
  examples = [
43
  [
44
  "Ali Ben Salah",
45
  "production",
46
+ "Packaging machine #4 stopped. Production is blocked. Need urgent maintenance support.",
47
  None,
48
  "administration",
49
  True,
 
52
  [
53
  "Sara Trabelsi",
54
  "magazine",
55
+ "Need content approval and printing coordination before tomorrow’s issue.",
56
  None,
57
  "administration",
58
  True,
 
61
  [
62
  "Mohamed Kefi",
63
  "administration",
64
+ "Requesting budget validation for new raw materials purchase.",
65
  None,
66
  "production",
67
  True,
 
70
  [
71
  "Ines Haddad",
72
  "production",
73
+ "Quality defect rate increased to 7%. Root cause investigation required.",
74
  None,
75
  "administration",
76
  False,
 
79
  [
80
  "Karim Jaziri",
81
  "magazine",
82
+ "Vendor delayed magazine printing. Need backup supplier urgently.",
83
  None,
84
  "administration",
85
  True,
86
  "High"
87
  ],
 
 
 
 
 
 
 
 
 
88
  ]
89
 
90
  # ======================================================
91
+ # YOUR ORIGINAL FUNCTIONS BELOW (UNCHANGED)
92
  # ======================================================
93
 
94
+ def update_report_email(new_email):
95
+ global current_report_email
96
+ if new_email and "@" in new_email and "." in new_email:
97
+ current_report_email = new_email.strip()
98
+ return f"βœ… Report email updated to: {current_report_email}"
99
+ else:
100
+ return "❌ Please enter a valid email address"
101
+
102
+ def send_email_brevo_api(to_email, subject, html_content, from_name="AI Coordination System"):
103
+ try:
104
+ if not BREVO_API_KEY:
105
+ return "❌ Email not configured - missing Brevo API key"
106
+
107
+ response = requests.post(
108
+ "https://api.brevo.com/v3/smtp/email",
109
+ headers={
110
+ "accept": "application/json",
111
+ "content-type": "application/json",
112
+ "api-key": BREVO_API_KEY
113
+ },
114
+ json={
115
+ "sender": {
116
+ "name": from_name,
117
+ "email": BREVO_FROM_EMAIL
118
+ },
119
+ "to": [{"email": to_email}],
120
+ "subject": subject,
121
+ "htmlContent": html_content
122
+ },
123
+ timeout=10
124
+ )
125
+
126
+ if response.status_code == 201:
127
+ return f"βœ… Email sent to {to_email}"
128
+ else:
129
+ error_msg = response.json().get('message', 'Unknown error')
130
+ return f"❌ Failed to send email: {error_msg}"
131
+
132
+ except Exception as e:
133
+ return f"❌ Email error: {str(e)}"
134
+
135
+ def analyze_coordination_needs(user_message, department, user_name, image=None):
136
+ """Use LLM to analyze coordination needs and suggest actions - with image support"""
137
+
138
+ if image:
139
+ # Convert image to base64 for vision model
140
+ buffered = io.BytesIO()
141
+ image.save(buffered, format="PNG")
142
+ img_base64 = base64.b64encode(buffered.getvalue()).decode()
143
+
144
+ prompt = f"""As a helpful coordination assistant, analyze this request from {user_name} in the {department} department along with the attached image.
145
+
146
+ Please provide clear, practical advice in plain English that's easy for anyone to understand.
147
+
148
+ REQUEST DETAILS:
149
+ - Department: {department}
150
+ - Requestor: {user_name}
151
+ - Message: {user_message}
152
+
153
+ Please analyze both the text and image to provide helpful guidance about:
154
+
155
+ 1. Which teams need to be involved
156
+ 2. What specific steps should be taken next
157
+ 3. Any important information from the image
158
+ 4. What priority this request should have
159
+ 5. What follow-up might be needed
160
+
161
+ Please format your response in a friendly, conversational way that's easy to read and act upon."""
162
+
163
+ try:
164
+ response = requests.post(
165
+ "https://openrouter.ai/api/v1/chat/completions",
166
+ headers={
167
+ "Authorization": f"Bearer {OPENROUTER_API_KEY}",
168
+ "Content-Type": "application/json",
169
+ },
170
+ json={
171
+ "model": "google/gemma-3-27b-it:free", # Vision model
172
+ "messages": [
173
+ {
174
+ "role": "user",
175
+ "content": [
176
+ {
177
+ "type": "text",
178
+ "text": prompt
179
+ },
180
+ {
181
+ "type": "image_url",
182
+ "image_url": {
183
+ "url": f"data:image/png;base64,{img_base64}"
184
+ }
185
+ }
186
+ ]
187
+ }
188
+ ],
189
+ "temperature": 0.3
190
+ },
191
+ timeout=60
192
+ )
193
+
194
+ if response.status_code == 200:
195
+ data = response.json()
196
+ return data["choices"][0]["message"]["content"]
197
+ else:
198
+ return "I'm having trouble analyzing the image right now. Please try again in a moment."
199
+
200
+ except Exception as e:
201
+ return f"Sorry, I couldn't process the image. Error: {str(e)}"
202
+
203
+ else:
204
+ # Text-only analysis
205
+ prompt = f"""As a helpful coordination assistant, analyze this request from {user_name} in the {department} department.
206
+
207
+ Please provide clear, practical advice in plain English that's easy for anyone to understand.
208
+
209
+ REQUEST DETAILS:
210
+ - Department: {department}
211
+ - Requestor: {user_name}
212
+ - Message: {user_message}
213
+
214
+ Please provide helpful guidance about:
215
+ - Which teams need to be involved
216
+ - What specific steps should be taken next
217
+ - What priority this request should have
218
+ - What follow-up might be needed
219
+
220
+ Please format your response in a friendly, conversational way that's easy to read and act upon. Avoid technical jargon and use bullet points or simple sections to organize your thoughts."""
221
+
222
+ try:
223
+ response = requests.post(
224
+ "https://openrouter.ai/api/v1/chat/completions",
225
+ headers={
226
+ "Authorization": f"Bearer {OPENROUTER_API_KEY}",
227
+ "Content-Type": "application/json",
228
+ },
229
+ json={
230
+ "model": "google/gemma-3-27b-it:free",
231
+ "messages": [{"role": "user", "content": prompt}],
232
+ "temperature": 0.3
233
+ },
234
+ timeout=30
235
+ )
236
+
237
+ if response.status_code == 200:
238
+ data = response.json()
239
+ return data["choices"][0]["message"]["content"]
240
+ else:
241
+ return "I'm having trouble analyzing your request right now. Please try again in a moment."
242
+
243
+ except Exception as e:
244
+ return f"Sorry, I couldn't process your request. Error: {str(e)}"
245
+
246
+ # ... The rest of your original functions (send_department_email, send_email_report, add_to_conversation_history, process_coordination_request, etc.) remain unchanged ...
247
+
248
+ # ======================================================
249
+ # GRADIO UI
250
+ # ======================================================
251
 
252
+ with gr.Blocks(theme=gr.themes.Soft(), title="AI Coordination System") as ui:
253
+ gr.Markdown("# 🏒 AI Department Coordination System")
254
+ gr.Markdown("*Streamline communication between Administration, Production, and Magazine Management*")
255
 
256
  with gr.Row():
 
257
  with gr.Column(scale=1):
258
+ # Form Inputs
259
+ name_input = gr.Textbox(label="Your Name", placeholder="Enter your full name")
260
+ department_dropdown = gr.Dropdown(choices=["administration", "production", "magazine"], label="Your Department")
261
+ message_input = gr.Textbox(label="What do you need help with?", lines=4, placeholder="Describe your request")
262
+ image_input = gr.Image(label="πŸ“· Attach Image (Optional)", type="pil")
263
+ recipient_dropdown = gr.Dropdown(choices=["administration", "production", "magazine"], label="Notify Department")
264
+ urgency_dropdown = gr.Dropdown(choices=["Normal", "Medium", "High"], value="Normal", label="Priority Level")
265
+ send_email_checkbox = gr.Checkbox(label="Send email notification", value=True)
266
+
267
+ submit_btn = gr.Button("πŸš€ Get Coordination Help", variant="primary")
268
+ output = gr.Textbox(lines=18, label="Recommended Actions", show_copy_button=True)
269
+
270
+ # ======================================================
271
+ # EXAMPLES COMPONENT
272
+ # ======================================================
273
+ gr.Markdown("### πŸ§ͺ Quick Test Examples")
274
+ gr.Examples(
275
+ examples=examples,
276
+ inputs=[name_input, department_dropdown, message_input, image_input, recipient_dropdown, send_email_checkbox, urgency_dropdown],
277
+ label="Click an example to auto-fill the form and test the workflow"
278
+ )
 
 
 
 
 
 
 
 
 
 
 
 
279
 
280
  if __name__ == "__main__":
281
+ ui.launch(share=True)