geethareddy commited on
Commit
2fe12f1
·
verified ·
1 Parent(s): 749a542

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -78
app.py CHANGED
@@ -3,7 +3,10 @@ import torch
3
  from transformers import AutoModelForCausalLM, AutoTokenizer
4
  from simple_salesforce import Salesforce
5
  import os
 
 
6
  from dotenv import load_dotenv
 
7
 
8
  # Load environment variables
9
  load_dotenv()
@@ -14,12 +17,8 @@ missing_vars = [var for var in required_env_vars if not os.getenv(var)]
14
  if missing_vars:
15
  raise EnvironmentError(f"Missing required environment variables: {missing_vars}")
16
 
17
- # Defaults
18
- KPI_FLAG_DEFAULT = os.getenv('KPI_FLAG', 'True') == 'True'
19
- ENGAGEMENT_SCORE_DEFAULT = float(os.getenv('ENGAGEMENT_SCORE', '85.0'))
20
-
21
- # Load model and tokenizer (Updated to use distilgpt2)
22
- model_name = "distilgpt2" # Using distilgpt2 for faster response
23
  tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=True)
24
  model = AutoModelForCausalLM.from_pretrained(model_name, low_cpu_mem_usage=True)
25
 
@@ -28,7 +27,7 @@ if tokenizer.pad_token is None:
28
  tokenizer.pad_token_id = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)
29
  model.config.pad_token_id = tokenizer.pad_token_id
30
 
31
- # Refined Prompt to generate day-by-day tasks based on milestones
32
  PROMPT_TEMPLATE = """You are an AI assistant for construction supervisors. Given the role, project, milestones, and a reflection log, generate:
33
 
34
  1. A Daily Checklist with clear and concise tasks based on the role and milestones.
@@ -54,7 +53,82 @@ Suggestions:
54
  -
55
  """
56
 
57
- # Salesforce Functions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  def get_roles_from_salesforce():
59
  try:
60
  sf = Salesforce(
@@ -67,7 +141,7 @@ def get_roles_from_salesforce():
67
  return list(set(record['Role__c'] for record in result['records']))
68
  except Exception as e:
69
  print(f"⚠️ Error fetching roles: {e}")
70
- return ["Site Manager", "Safety Officer", "Project Lead"]
71
 
72
  def get_supervisor_name_by_role(role):
73
  try:
@@ -77,11 +151,10 @@ def get_supervisor_name_by_role(role):
77
  security_token=os.getenv('SF_SECURITY_TOKEN'),
78
  domain=os.getenv('SF_DOMAIN', 'login')
79
  )
80
- role = role.replace("'", "\\'")
81
  result = sf.query(f"SELECT Name FROM Supervisor__c WHERE Role__c = '{role}'")
82
  return [record['Name'] for record in result['records']]
83
  except Exception as e:
84
- print(f"⚠️ Error fetching supervisor names: {e}")
85
  return []
86
 
87
  def get_projects_for_supervisor(supervisor_name):
@@ -92,37 +165,16 @@ def get_projects_for_supervisor(supervisor_name):
92
  security_token=os.getenv('SF_SECURITY_TOKEN'),
93
  domain=os.getenv('SF_DOMAIN', 'login')
94
  )
95
- supervisor_name = supervisor_name.replace("'", "\\'")
96
- supervisor_result = sf.query(f"SELECT Id FROM Supervisor__c WHERE Name = '{supervisor_name}' LIMIT 1")
97
- if supervisor_result['totalSize'] == 0:
98
  return ""
99
- supervisor_id = supervisor_result['records'][0]['Id']
100
  project_result = sf.query(f"SELECT Name FROM Project__c WHERE Supervisor_ID__c = '{supervisor_id}' LIMIT 1")
101
  return project_result['records'][0]['Name'] if project_result['totalSize'] > 0 else ""
102
  except Exception as e:
103
  print(f"⚠️ Error fetching project: {e}")
104
  return ""
105
 
106
- def field_exists(sf, object_name, field_name):
107
- try:
108
- obj_desc = getattr(sf, object_name).describe()
109
- return field_name in [field['name'] for field in obj_desc['fields']]
110
- except Exception as e:
111
- print(f"⚠️ Error checking field {field_name}: {e}")
112
- return False
113
-
114
- # New function to generate Salesforce dashboard URL (Visualforce Page)
115
- def generate_salesforce_dashboard_url(supervisor_name, project_id):
116
- # Use the provided Salesforce Visualforce URL with supervisorName and projectId as parameters
117
- return f"https://aicoachforsitesupervisors-dev-ed--c.develop.vf.force.com/apex/DashboardPage?supervisorName={supervisor_name}&projectId={project_id}"
118
-
119
- # Dashboard button function
120
- def open_dashboard(role, supervisor_name, project_id):
121
- # Generate dynamic URL based on supervisor and project
122
- dashboard_url = generate_salesforce_dashboard_url(supervisor_name, project_id)
123
- return f'<a href="{dashboard_url}" target="_blank" rel="noopener noreferrer" style="font-size:16px;">Open Salesforce Dashboard</a>'
124
-
125
- # Generate function
126
  def generate_outputs(role, supervisor_name, project_id, milestones, reflection):
127
  if not all([role, supervisor_name, project_id, milestones, reflection]):
128
  return "❗ Please fill all fields.", ""
@@ -139,7 +191,7 @@ def generate_outputs(role, supervisor_name, project_id, milestones, reflection):
139
  with torch.no_grad():
140
  outputs = model.generate(
141
  inputs['input_ids'],
142
- max_new_tokens=150, # Increased max tokens to capture more content
143
  no_repeat_ngram_size=2,
144
  do_sample=True,
145
  top_p=0.9,
@@ -156,48 +208,21 @@ def generate_outputs(role, supervisor_name, project_id, milestones, reflection):
156
  e = text.find(end, s) if end else len(text)
157
  return text[s + len(start):e].strip() if s != -1 else ""
158
 
159
- # Extract the checklist and suggestions
160
  checklist = extract_between(result, "Checklist:\n", "Suggestions:")
161
  suggestions = extract_between(result, "Suggestions:\n", None)
162
 
163
- # If checklist or suggestions are empty, generate fallback content
164
  if not checklist.strip():
165
- checklist = generate_fallback_checklist(role, milestones)
166
  if not suggestions.strip():
167
- suggestions = generate_fallback_suggestions(reflection)
 
 
 
 
 
168
 
169
  return checklist, suggestions
170
 
171
- # Fallback generation for checklist and suggestions
172
- def generate_fallback_checklist(role, milestones):
173
- checklist_items = []
174
-
175
- # If milestones are provided, add them to the checklist directly
176
- if milestones and milestones.strip():
177
- kpis = [kpi.strip() for kpi in milestones.split(",")]
178
- for kpi in kpis:
179
- checklist_items.append(f"- Ensure progress on {kpi}")
180
- else:
181
- checklist_items.append("- Perform daily safety inspection")
182
-
183
- return "\n".join(checklist_items)
184
-
185
- def generate_fallback_suggestions(reflection):
186
- suggestions_items = []
187
- reflection_lower = reflection.lower()
188
- if "student" in reflection_lower or "learning" in reflection_lower:
189
- suggestions_items.append("- Ensure students are logging incidents consistently")
190
- suggestions_items.append("- Provide guidance on timely incident recording")
191
- if "incident" in reflection_lower:
192
- suggestions_items.append("- Follow up on reported incidents with corrective actions")
193
-
194
- if not suggestions_items:
195
- suggestions_items.append("- Monitor team coordination")
196
- suggestions_items.append("- Review safety protocols with the team")
197
-
198
- return "\n".join(suggestions_items)
199
-
200
- # Interface
201
  def create_interface():
202
  roles = get_roles_from_salesforce()
203
  with gr.Blocks(theme="soft") as demo:
@@ -208,18 +233,16 @@ def create_interface():
208
  supervisor_name = gr.Dropdown(choices=[], label="Supervisor Name")
209
  project_id = gr.Textbox(label="Project ID", interactive=False)
210
 
211
- milestones = gr.Textbox(label="Milestones (comma-separated KPIs)", placeholder="E.g. Safety training, daily inspection")
212
- reflection = gr.Textbox(label="Reflection Log", lines=4, placeholder="Any concerns, delays, updates...")
213
 
214
  with gr.Row():
215
  generate = gr.Button("Generate")
216
  clear = gr.Button("Clear")
217
  refresh = gr.Button("🔄 Refresh Roles")
218
- dashboard_btn = gr.Button("Dashboard")
219
 
220
  checklist_output = gr.Textbox(label="✅ Daily Checklist")
221
  suggestions_output = gr.Textbox(label="💡 Focus Suggestions")
222
- dashboard_link = gr.HTML("")
223
 
224
  role.change(fn=lambda r: gr.update(choices=get_supervisor_name_by_role(r)), inputs=role, outputs=supervisor_name)
225
  supervisor_name.change(fn=get_projects_for_supervisor, inputs=supervisor_name, outputs=project_id)
@@ -233,12 +256,8 @@ def create_interface():
233
 
234
  refresh.click(fn=lambda: gr.update(choices=get_roles_from_salesforce()), outputs=role)
235
 
236
- dashboard_btn.click(fn=open_dashboard, inputs=[role, supervisor_name, project_id], outputs=dashboard_link)
237
-
238
  return demo
239
 
240
  if __name__ == "__main__":
241
  app = create_interface()
242
  app.launch()
243
-
244
-
 
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
 
11
  # Load environment variables
12
  load_dotenv()
 
17
  if missing_vars:
18
  raise EnvironmentError(f"Missing required environment variables: {missing_vars}")
19
 
20
+ # Load model and tokenizer
21
+ model_name = "distilgpt2"
 
 
 
 
22
  tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=True)
23
  model = AutoModelForCausalLM.from_pretrained(model_name, low_cpu_mem_usage=True)
24
 
 
27
  tokenizer.pad_token_id = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)
28
  model.config.pad_token_id = tokenizer.pad_token_id
29
 
30
+ # Prompt template
31
  PROMPT_TEMPLATE = """You are an AI assistant for construction supervisors. Given the role, project, milestones, and a reflection log, generate:
32
 
33
  1. A Daily Checklist with clear and concise tasks based on the role and milestones.
 
53
  -
54
  """
55
 
56
+ # Save report as PDF
57
+ def save_report_as_pdf(role, supervisor_name, project_id, checklist, suggestions):
58
+ now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
59
+ filename = f"report_{supervisor_name}_{project_id}_{now}.pdf"
60
+ file_path = f"./reports/{filename}"
61
+ os.makedirs("reports", exist_ok=True)
62
+
63
+ pdf = FPDF()
64
+ pdf.add_page()
65
+ pdf.set_font("Arial", size=12)
66
+ pdf.set_font("Arial", 'B', 14)
67
+ pdf.cell(200, 10, txt="Supervisor Daily Report", ln=True, align="C")
68
+ pdf.set_font("Arial", size=12)
69
+ pdf.cell(200, 10, txt=f"Role: {role}", ln=True)
70
+ pdf.cell(200, 10, txt=f"Supervisor: {supervisor_name}", ln=True)
71
+ pdf.cell(200, 10, txt=f"Project ID: {project_id}", ln=True)
72
+ pdf.ln(5)
73
+ pdf.set_font("Arial", 'B', 12)
74
+ pdf.cell(200, 10, txt="Daily Checklist", ln=True)
75
+ pdf.set_font("Arial", size=12)
76
+ for line in checklist.split("\n"):
77
+ pdf.multi_cell(0, 10, line)
78
+ pdf.ln(5)
79
+ pdf.set_font("Arial", 'B', 12)
80
+ pdf.cell(200, 10, txt="Focus Suggestions", ln=True)
81
+ pdf.set_font("Arial", size=12)
82
+ for line in suggestions.split("\n"):
83
+ pdf.multi_cell(0, 10, line)
84
+ pdf.output(file_path)
85
+ return file_path
86
+
87
+ # Upload to Salesforce and update record
88
+
89
+ def upload_pdf_to_salesforce_and_update_link(supervisor_name, project_id, pdf_path):
90
+ try:
91
+ sf = Salesforce(
92
+ username=os.getenv('SF_USERNAME'),
93
+ password=os.getenv('SF_PASSWORD'),
94
+ security_token=os.getenv('SF_SECURITY_TOKEN'),
95
+ domain=os.getenv('SF_DOMAIN', 'login')
96
+ )
97
+
98
+ with open(pdf_path, "rb") as f:
99
+ encoded = base64.b64encode(f.read()).decode()
100
+
101
+ content = sf.ContentVersion.create({
102
+ 'Title': os.path.basename(pdf_path),
103
+ 'PathOnClient': os.path.basename(pdf_path),
104
+ 'VersionData': encoded
105
+ })
106
+
107
+ content_id = content['id']
108
+ download_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{content_id}"
109
+
110
+ query = sf.query(f"""
111
+ SELECT Id FROM Supervisor_AI_Coaching__c
112
+ WHERE Project_ID__c = '{project_id}'
113
+ AND Name = '{supervisor_name}'
114
+ LIMIT 1
115
+ """)
116
+
117
+ if query['totalSize'] > 0:
118
+ coaching_id = query['records'][0]['Id']
119
+ sf.Supervisor_AI_Coaching__c.update(coaching_id, {
120
+ 'Download_Link__c': download_url
121
+ })
122
+ else:
123
+ print("⚠️ No matching Supervisor_AI_Coaching__c record found.")
124
+
125
+ return download_url
126
+
127
+ except Exception as e:
128
+ print(f"⚠️ Upload error: {e}")
129
+ return ""
130
+
131
+ # Salesforce helpers
132
  def get_roles_from_salesforce():
133
  try:
134
  sf = Salesforce(
 
141
  return list(set(record['Role__c'] for record in result['records']))
142
  except Exception as e:
143
  print(f"⚠️ Error fetching roles: {e}")
144
+ return []
145
 
146
  def get_supervisor_name_by_role(role):
147
  try:
 
151
  security_token=os.getenv('SF_SECURITY_TOKEN'),
152
  domain=os.getenv('SF_DOMAIN', 'login')
153
  )
 
154
  result = sf.query(f"SELECT Name FROM Supervisor__c WHERE Role__c = '{role}'")
155
  return [record['Name'] for record in result['records']]
156
  except Exception as e:
157
+ print(f"⚠️ Error fetching names: {e}")
158
  return []
159
 
160
  def get_projects_for_supervisor(supervisor_name):
 
165
  security_token=os.getenv('SF_SECURITY_TOKEN'),
166
  domain=os.getenv('SF_DOMAIN', 'login')
167
  )
168
+ result = sf.query(f"SELECT Id FROM Supervisor__c WHERE Name = '{supervisor_name}' LIMIT 1")
169
+ if result['totalSize'] == 0:
 
170
  return ""
171
+ supervisor_id = result['records'][0]['Id']
172
  project_result = sf.query(f"SELECT Name FROM Project__c WHERE Supervisor_ID__c = '{supervisor_id}' LIMIT 1")
173
  return project_result['records'][0]['Name'] if project_result['totalSize'] > 0 else ""
174
  except Exception as e:
175
  print(f"⚠️ Error fetching project: {e}")
176
  return ""
177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  def generate_outputs(role, supervisor_name, project_id, milestones, reflection):
179
  if not all([role, supervisor_name, project_id, milestones, reflection]):
180
  return "❗ Please fill all fields.", ""
 
191
  with torch.no_grad():
192
  outputs = model.generate(
193
  inputs['input_ids'],
194
+ max_new_tokens=150,
195
  no_repeat_ngram_size=2,
196
  do_sample=True,
197
  top_p=0.9,
 
208
  e = text.find(end, s) if end else len(text)
209
  return text[s + len(start):e].strip() if s != -1 else ""
210
 
 
211
  checklist = extract_between(result, "Checklist:\n", "Suggestions:")
212
  suggestions = extract_between(result, "Suggestions:\n", None)
213
 
 
214
  if not checklist.strip():
215
+ checklist = "- Perform daily safety inspection"
216
  if not suggestions.strip():
217
+ suggestions = "- Monitor team coordination\n- Review safety protocols with the team"
218
+
219
+ pdf_path = save_report_as_pdf(role, supervisor_name, project_id, checklist, suggestions)
220
+ pdf_url = upload_pdf_to_salesforce_and_update_link(supervisor_name, project_id, pdf_path)
221
+ if pdf_url:
222
+ suggestions += f"\n\n🔗 [Download PDF Report]({pdf_url})"
223
 
224
  return checklist, suggestions
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  def create_interface():
227
  roles = get_roles_from_salesforce()
228
  with gr.Blocks(theme="soft") as demo:
 
233
  supervisor_name = gr.Dropdown(choices=[], label="Supervisor Name")
234
  project_id = gr.Textbox(label="Project ID", interactive=False)
235
 
236
+ milestones = gr.Textbox(label="Milestones (comma-separated KPIs)")
237
+ reflection = gr.Textbox(label="Reflection Log", lines=4)
238
 
239
  with gr.Row():
240
  generate = gr.Button("Generate")
241
  clear = gr.Button("Clear")
242
  refresh = gr.Button("🔄 Refresh Roles")
 
243
 
244
  checklist_output = gr.Textbox(label="✅ Daily Checklist")
245
  suggestions_output = gr.Textbox(label="💡 Focus Suggestions")
 
246
 
247
  role.change(fn=lambda r: gr.update(choices=get_supervisor_name_by_role(r)), inputs=role, outputs=supervisor_name)
248
  supervisor_name.change(fn=get_projects_for_supervisor, inputs=supervisor_name, outputs=project_id)
 
256
 
257
  refresh.click(fn=lambda: gr.update(choices=get_roles_from_salesforce()), outputs=role)
258
 
 
 
259
  return demo
260
 
261
  if __name__ == "__main__":
262
  app = create_interface()
263
  app.launch()