geethareddy commited on
Commit
2e49337
Β·
verified Β·
1 Parent(s): 4a4b709

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +301 -0
app.py ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer
4
+ from simple_salesforce import Salesforce
5
+ import os
6
+ import base64
7
+ import datetime
8
+ from dotenv import load_dotenv
9
+ from fpdf import FPDF
10
+ import shutil
11
+ import html
12
+ import io
13
+ import matplotlib.pyplot as plt
14
+ import numpy as np
15
+
16
+ # Load environment variables
17
+ load_dotenv()
18
+
19
+ # Required env vars check
20
+ required_env_vars = ['SF_USERNAME', 'SF_PASSWORD', 'SF_SECURITY_TOKEN']
21
+ missing_vars = [var for var in required_env_vars if not os.getenv(var)]
22
+ if missing_vars:
23
+ raise EnvironmentError(f"Missing required environment variables: {missing_vars}")
24
+
25
+ # Load model and tokenizer
26
+ model_name = "distilgpt2"
27
+ tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=True)
28
+ model = AutoModelForCausalLM.from_pretrained(model_name, low_cpu_mem_usage=True)
29
+
30
+ if tokenizer.pad_token is None:
31
+ tokenizer.pad_token = tokenizer.eos_token
32
+ tokenizer.pad_token_id = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)
33
+ model.config.pad_token_id = tokenizer.pad_token_id
34
+
35
+ # Function to generate progress chart
36
+ def show_dashboard_chart(start_date, end_date, tasks_completed):
37
+ completed_tasks = list(tasks_completed.values())
38
+ labels = list(tasks_completed.keys())
39
+ remaining_tasks = [5 - task for task in completed_tasks] # Assuming 5 tasks per date
40
+
41
+ # Create the bar chart with completed and remaining tasks
42
+ fig, ax = plt.subplots(figsize=(10, 6))
43
+ ax.bar(labels, completed_tasks, color='green', label="Completed")
44
+ ax.bar(labels, remaining_tasks, bottom=completed_tasks, color='gray', label="Remaining")
45
+
46
+ ax.set_xlabel("Dates")
47
+ ax.set_ylabel("Task Progress")
48
+ ax.set_title(f"Task Completion Progress from {start_date} to {end_date}")
49
+ ax.legend()
50
+ plt.xticks(rotation=45)
51
+ chart_image = io.BytesIO()
52
+ plt.savefig(chart_image, format='png')
53
+ chart_image.seek(0)
54
+ return chart_image
55
+
56
+ # Function to get the data from Salesforce
57
+ def get_dashboard_data_from_salesforce(supervisor_name, project_id):
58
+ try:
59
+ sf = Salesforce(
60
+ username=os.getenv('SF_USERNAME'),
61
+ password=os.getenv('SF_PASSWORD'),
62
+ security_token=os.getenv('SF_SECURITY_TOKEN'),
63
+ domain=os.getenv('SF_DOMAIN', 'login')
64
+ )
65
+
66
+ # Get the start and end date from Salesforce
67
+ query = sf.query(f"SELECT Start_Date__c, End_Date__c FROM Project__c WHERE Name = '{project_id}' LIMIT 1")
68
+ if query['totalSize'] == 0:
69
+ return "", "", None, "Project not found"
70
+
71
+ start_date_str = query['records'][0]['Start_Date__c']
72
+ end_date_str = query['records'][0]['End_Date__c']
73
+
74
+ # Convert the string dates to datetime objects
75
+ start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d")
76
+ end_date = datetime.datetime.strptime(end_date_str, "%Y-%m-%d")
77
+
78
+ # Generate task dates and simulated completion data
79
+ task_dates = [start_date + datetime.timedelta(days=i) for i in range((end_date - start_date).days + 1)]
80
+ tasks_completed = {str(task_dates[i].date()): np.random.randint(1, 6) for i in range(len(task_dates))}
81
+
82
+ chart_image = show_dashboard_chart(start_date, end_date, tasks_completed)
83
+ return start_date, end_date, chart_image, f"Project {project_id} Task Progress"
84
+ except Exception as e:
85
+ return "", "", None, f"Error: {str(e)}"
86
+
87
+ # Clean text for PDF generation
88
+ def clean_text_for_pdf(text):
89
+ return html.unescape(text).encode('latin-1', 'replace').decode('latin-1')
90
+
91
+ # Function to save report as PDF
92
+ def save_report_as_pdf(role, supervisor_name, project_id, checklist, suggestions):
93
+ now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
94
+ filename = f"report_{supervisor_name}_{project_id}_{now}.pdf"
95
+ file_path = f"./reports/{filename}"
96
+ os.makedirs("reports", exist_ok=True)
97
+
98
+ pdf = FPDF()
99
+ pdf.add_page()
100
+ pdf.set_font("Arial", 'B', 14)
101
+ pdf.cell(200, 10, txt="Supervisor Daily Report", ln=True, align="C")
102
+ pdf.set_font("Arial", size=12)
103
+ pdf.cell(200, 10, txt=clean_text_for_pdf(f"Role: {role}"), ln=True)
104
+ pdf.cell(200, 10, txt=clean_text_for_pdf(f"Supervisor: {supervisor_name}"), ln=True)
105
+ pdf.cell(200, 10, txt=clean_text_for_pdf(f"Project ID: {project_id}"), ln=True)
106
+ pdf.ln(5)
107
+ pdf.set_font("Arial", 'B', 12)
108
+ pdf.cell(200, 10, txt="Daily Checklist", ln=True)
109
+ pdf.set_font("Arial", size=12)
110
+ for line in checklist.split("\n"):
111
+ pdf.multi_cell(0, 10, clean_text_for_pdf(line))
112
+ pdf.ln(5)
113
+ pdf.set_font("Arial", 'B', 12)
114
+ pdf.cell(200, 10, txt="Focus Suggestions", ln=True)
115
+ pdf.set_font("Arial", size=12)
116
+ for line in suggestions.split("\n"):
117
+ pdf.multi_cell(0, 10, clean_text_for_pdf(line))
118
+ pdf.output(file_path)
119
+
120
+ temp_pdf_path = "/tmp/" + os.path.basename(file_path)
121
+ shutil.copy(file_path, temp_pdf_path)
122
+ return temp_pdf_path, filename
123
+
124
+ # Function to get roles from Salesforce
125
+ def get_roles_from_salesforce():
126
+ try:
127
+ sf = Salesforce(
128
+ username=os.getenv('SF_USERNAME'),
129
+ password=os.getenv('SF_PASSWORD'),
130
+ security_token=os.getenv('SF_SECURITY_TOKEN'),
131
+ domain=os.getenv('SF_DOMAIN', 'login')
132
+ )
133
+ result = sf.query("SELECT Role__c FROM Supervisor__c WHERE Role__c != NULL")
134
+ return list(set(record['Role__c'] for record in result['records']))
135
+ except Exception as e:
136
+ return []
137
+
138
+ # Function to get supervisor names based on role
139
+ def get_supervisor_name_by_role(role):
140
+ try:
141
+ sf = Salesforce(
142
+ username=os.getenv('SF_USERNAME'),
143
+ password=os.getenv('SF_PASSWORD'),
144
+ security_token=os.getenv('SF_SECURITY_TOKEN'),
145
+ domain=os.getenv('SF_DOMAIN', 'login')
146
+ )
147
+ result = sf.query(f"SELECT Name FROM Supervisor__c WHERE Role__c = '{role}'")
148
+ return [record['Name'] for record in result['records']]
149
+ except Exception as e:
150
+ return []
151
+
152
+ # Function to get the project name for a supervisor
153
+ def get_projects_for_supervisor(supervisor_name):
154
+ try:
155
+ sf = Salesforce(
156
+ username=os.getenv('SF_USERNAME'),
157
+ password=os.getenv('SF_PASSWORD'),
158
+ security_token=os.getenv('SF_SECURITY_TOKEN'),
159
+ domain=os.getenv('SF_DOMAIN', 'login')
160
+ )
161
+ result = sf.query(f"SELECT Id FROM Supervisor__c WHERE Name = '{supervisor_name}' LIMIT 1")
162
+ if result['totalSize'] == 0:
163
+ return ""
164
+ supervisor_id = result['records'][0]['Id']
165
+ project_result = sf.query(f"SELECT Name FROM Project__c WHERE Supervisor_ID__c = '{supervisor_id}' LIMIT 1")
166
+ return project_result['records'][0]['Name'] if project_result['totalSize'] > 0 else ""
167
+ except Exception as e:
168
+ return ""
169
+
170
+ # Function to generate daily checklist and focus suggestions
171
+ def generate_checklist_and_suggestions(role, project_id, milestones, reflection):
172
+ prompt = f"""
173
+ You are a supervisor assistant. Given the role {role}, project {project_id}, milestones {milestones}, and reflection log {reflection}, generate:
174
+
175
+ 1. A Daily Checklist with clear and concise tasks.
176
+ 2. Focus Suggestions based on concerns or keywords from the reflection log.
177
+ """
178
+ inputs = tokenizer(prompt, return_tensors="pt")
179
+ outputs = model.generate(inputs['input_ids'], max_length=200, num_return_sequences=1)
180
+ generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
181
+
182
+ # Split generated text into checklist and suggestions
183
+ parts = generated_text.split("\n")
184
+ checklist = "\n".join(parts[:len(parts)//2])
185
+ suggestions = "\n".join(parts[len(parts)//2:])
186
+
187
+ return checklist, suggestions
188
+
189
+ # Function to upload the report and create the Supervisor AI Coaching record in Salesforce
190
+ def upload_report_and_create_supervisor_ai_coaching(supervisor_name, project_id, checklist, suggestions, pdf_path, pdf_name):
191
+ try:
192
+ sf = Salesforce(
193
+ username=os.getenv('SF_USERNAME'),
194
+ password=os.getenv('SF_PASSWORD'),
195
+ security_token=os.getenv('SF_SECURITY_TOKEN'),
196
+ domain=os.getenv('SF_DOMAIN', 'login')
197
+ )
198
+
199
+ # Upload the PDF file to Salesforce as Content Version
200
+ with open(pdf_path, "rb") as f:
201
+ encoded = base64.b64encode(f.read()).decode()
202
+
203
+ content = sf.ContentVersion.create({
204
+ 'Title': pdf_name,
205
+ 'PathOnClient': pdf_name,
206
+ 'VersionData': encoded
207
+ })
208
+
209
+ content_id = content['id']
210
+ download_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{content_id}"
211
+
212
+ # Create a Supervisor AI Coaching record
213
+ query = sf.query(f"SELECT Id FROM Supervisor__c WHERE Name = '{supervisor_name}' LIMIT 1")
214
+ supervisor_id = query['records'][0]['Id'] if query['totalSize'] > 0 else None
215
+ if not supervisor_id:
216
+ return "Supervisor not found."
217
+
218
+ project_query = sf.query(f"SELECT Id FROM Project__c WHERE Name = '{project_id}' LIMIT 1")
219
+ project_id_sf = project_query['records'][0]['Id'] if project_query['totalSize'] > 0 else None
220
+ if not project_id_sf:
221
+ return "Project not found."
222
+
223
+ # Create Supervisor AI Coaching record with all necessary fields
224
+ sf.Supervisor_AI_Coaching__c.create({
225
+ 'Project_ID__c': project_id_sf,
226
+ 'Supervisor_ID__c': supervisor_id,
227
+ 'Daily_Checklist__c': checklist,
228
+ 'Suggested_Tips__c': suggestions,
229
+ 'Download_Link__c': download_url
230
+ })
231
+
232
+ return "Supervisor AI Coaching record created and report uploaded successfully."
233
+
234
+ except Exception as e:
235
+ return f"Error: {str(e)}"
236
+
237
+ # Gradio interface
238
+ def create_interface():
239
+ roles = get_roles_from_salesforce() # Get roles from Salesforce dynamically
240
+ with gr.Blocks(theme="soft", css=".footer { display: none; }") as demo:
241
+ gr.Markdown("## 🧠 AI-Powered Supervisor Assistant")
242
+
243
+ with gr.Row():
244
+ role = gr.Dropdown(choices=roles, label="Role")
245
+ supervisor_name = gr.Dropdown(choices=[], label="Supervisor Name")
246
+ project_id = gr.Textbox(label="Project ID", interactive=False)
247
+
248
+ milestones = gr.Textbox(label="Milestones (comma-separated KPIs)")
249
+ reflection = gr.Textbox(label="Reflection Log", lines=4)
250
+
251
+ with gr.Row():
252
+ generate = gr.Button("Generate")
253
+ clear = gr.Button("Clear")
254
+ refresh = gr.Button("πŸ”„ Refresh Roles")
255
+
256
+ checklist_output = gr.Textbox(label="βœ… Daily Checklist")
257
+ suggestions_output = gr.Textbox(label="πŸ’‘ Focus Suggestions")
258
+ download_button = gr.File(label="⬇ Download Report")
259
+ pdf_link = gr.HTML()
260
+
261
+ role.change(fn=lambda r: gr.update(choices=get_supervisor_name_by_role(r)), inputs=role, outputs=supervisor_name)
262
+ supervisor_name.change(fn=get_projects_for_supervisor, inputs=supervisor_name, outputs=project_id)
263
+
264
+ def handle_generate(role, supervisor_name, project_id, milestones, reflection):
265
+ checklist, suggestions = generate_checklist_and_suggestions(role, project_id, milestones, reflection)
266
+ pdf_path, pdf_name = save_report_as_pdf(role, supervisor_name, project_id, checklist, suggestions)
267
+ supervisor_ai_coaching_response = upload_report_and_create_supervisor_ai_coaching(supervisor_name, project_id, checklist, suggestions, pdf_path, pdf_name)
268
+ return checklist, suggestions, pdf_path, pdf_name, supervisor_ai_coaching_response
269
+
270
+ generate.click(fn=handle_generate,
271
+ inputs=[role, supervisor_name, project_id, milestones, reflection],
272
+ outputs=[checklist_output, suggestions_output, download_button, pdf_link, gr.HTML()])
273
+
274
+ clear.click(fn=lambda: ("", "", "", "", ""),
275
+ inputs=None,
276
+ outputs=[role, supervisor_name, project_id, milestones, reflection])
277
+
278
+ refresh.click(fn=lambda: gr.update(choices=get_roles_from_salesforce()), outputs=role)
279
+
280
+ # Supervisor Dashboard Tab
281
+ with gr.Tab("πŸ“Š Supervisor Dashboard"):
282
+ dash_supervisor = gr.Textbox(label="Supervisor Name", placeholder="e.g., SUP-056")
283
+ dash_project = gr.Textbox(label="Project ID", placeholder="e.g., PROJ-078")
284
+ load_dash = gr.Button("πŸ“₯ Load Dashboard")
285
+ dash_output = gr.HTML()
286
+
287
+ def show_dashboard_html(sup_name, proj_id):
288
+ start_date, end_date, chart_image, chart_title = get_dashboard_data_from_salesforce(sup_name, proj_id)
289
+ if chart_image:
290
+ chart_html = f"<img src='data:image/png;base64,{base64.b64encode(chart_image.read()).decode()}' />"
291
+ return f"<h3>{chart_title}</h3><p>From {start_date} to {end_date}</p>{chart_html}"
292
+ else:
293
+ return f"Error: {chart_title}"
294
+
295
+ load_dash.click(fn=show_dashboard_html, inputs=[dash_supervisor, dash_project], outputs=dash_output)
296
+
297
+ return demo
298
+
299
+ if __name__ == "__main__":
300
+ app = create_interface()
301
+ app.launch()