lokeshloki143 commited on
Commit
eb7f886
·
verified ·
1 Parent(s): 070f012

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +203 -304
app.py CHANGED
@@ -1,334 +1,233 @@
1
- from flask import Flask, request, jsonify, session, redirect, url_for, render_template
2
- from simple_salesforce import Salesforce, SalesforceAuthenticationFailed, SalesforceError
 
3
  import os
 
 
 
4
  from dotenv import load_dotenv
5
- import logging
6
- import requests
7
- import json
8
- from datetime import datetime
9
- from urllib.parse import quote
10
 
11
  # Load environment variables
12
  load_dotenv()
13
 
14
- # Configure logging
15
- logging.basicConfig(
16
- level=logging.DEBUG,
17
- format='%(asctime)s - %(levelname)s - %(message)s',
18
- handlers=[logging.FileHandler('app.log'), logging.StreamHandler()]
19
- )
20
- logger = logging.getLogger(__name__)
21
-
22
- app = Flask(__name__)
23
- app.secret_key = os.getenv('FLASK_SECRET_KEY', 'tTPLQduw8wDpxdKOMJ3d9dM3o')
24
-
25
- # Salesforce credentials from .env
26
- SALESFORCE_USERNAME = os.getenv('SALESFORCE_USERNAME')
27
- SALESFORCE_PASSWORD = os.getenv('SALESFORCE_PASSWORD')
28
- SALESFORCE_SECURITY_TOKEN = os.getenv('SALESFORCE_SECURITY_TOKEN')
29
- SALESFORCE_DOMAIN = os.getenv('SALESFORCE_DOMAIN', 'login')
30
- HUGGING_FACE_API_TOKEN = os.getenv('HUGGING_FACE_API_TOKEN')
31
- HUGGING_FACE_API_URL = os.getenv('HUGGING_FACE_API_URL', 'https://api-inference.huggingface.co/models/facebook/bart-large')
32
-
33
  def get_salesforce_connection():
34
- """Establish a Salesforce connection with detailed error handling."""
35
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  sf = Salesforce(
37
- username=SALESFORCE_USERNAME,
38
- password=SALESFORCE_PASSWORD,
39
- security_token=SALESFORCE_SECURITY_TOKEN,
40
- domain=SALESFORCE_DOMAIN,
41
- version='60.0'
42
  )
43
- logger.info("Successfully connected to Salesforce")
44
- sf.query("SELECT Id FROM Supervisor_AI_Coaching__c LIMIT 1")
45
- logger.debug("Salesforce connection test query successful")
46
- return sf
47
- except SalesforceAuthenticationFailed as e:
48
- logger.error(f"Salesforce authentication failed: {str(e)}")
49
- raise Exception(f"Salesforce authentication failed: {str(e)}")
50
- except SalesforceError as e:
51
- logger.error(f"Salesforce error during connection: {str(e)}")
52
- raise Exception(f"Salesforce error: {str(e)}")
53
- except Exception as e:
54
- logger.error(f"Unexpected error connecting to Salesforce: {str(e)}")
55
- raise Exception(f"Unable to connect to Salesforce: {str(e)}")
56
-
57
- @app.route('/')
58
- def index():
59
- if 'supervisor_id' not in session:
60
- logger.info("User not logged in, redirecting to login page")
61
- return redirect(url_for('login_page'))
62
- return redirect(url_for('dashboard'))
63
-
64
- @app.route('/login', methods=['GET'])
65
- def login_page():
66
- return render_template('login.html')
67
-
68
- @app.route('/signup', methods=['GET'])
69
- def signup_page():
70
- return render_template('signup.html')
71
-
72
- @app.route('/login', methods=['POST'])
73
- def login():
74
- data = request.get_json()
75
- supervisor_id = data.get('supervisor_id')
76
-
77
- if not supervisor_id:
78
- logger.warning("Login failed: Supervisor ID is required")
79
- return jsonify({"status": "error", "message": "Supervisor ID is required"}), 400
80
-
81
- try:
82
- sf = get_salesforce_connection()
83
- logger.debug(f"Querying Salesforce for Supervisor_AI_Coaching_Name__c: {supervisor_id}")
84
- supervisor_id_escaped = quote(supervisor_id, safe='')
85
- query = f"SELECT Id, Supervisor_AI_Coaching_Name__c, Project_ID__c FROM Supervisor_AI_Coaching__c WHERE Supervisor_AI_Coaching_Name__c = '{supervisor_id_escaped}' LIMIT 1"
86
- result = sf.query(query)
87
- logger.debug(f"Salesforce query result: {result}")
88
-
89
- if not result['records']:
90
- logger.warning(f"Invalid Supervisor ID: {supervisor_id}")
91
- return jsonify({"status": "error", "message": "Invalid Supervisor ID"}), 401
92
-
93
- session['supervisor_id'] = supervisor_id
94
- logger.info(f"Login successful for {supervisor_id}")
95
- return jsonify({"status": "success", "message": "Login successful", "redirect": "/dashboard"})
96
 
 
 
 
97
  except Exception as e:
98
- logger.error(f"Login error: {str(e)}")
99
- return jsonify({"status": "error", "message": str(e)}), 500
100
-
101
- @app.route('/signup', methods=['POST'])
102
- def signup():
103
- data = request.get_json()
104
- supervisor_id = data.get('supervisor_id')
105
-
106
- if not supervisor_id:
107
- logger.warning("Signup failed: Supervisor ID is required")
108
- return jsonify({"status": "error", "message": "Supervisor ID is required"}), 400
109
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  try:
111
- sf = get_salesforce_connection()
112
- logger.debug(f"Checking if Supervisor_AI_Coaching_Name__c {supervisor_id} already exists")
113
- supervisor_id_escaped = quote(supervisor_id, safe='')
114
- query = f"SELECT Id FROM Supervisor_AI_Coaching__c WHERE Supervisor_AI_Coaching_Name__c = '{supervisor_id_escaped}' LIMIT 1"
115
- result = sf.query(query)
116
- if result['records']:
117
- logger.warning(f"Signup failed: Supervisor ID {supervisor_id} already exists")
118
- return jsonify({"status": "error", "message": "Supervisor ID already exists"}), 400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
- logger.debug(f"Creating new Supervisor_AI_Coaching__c record for {supervisor_id}")
121
- new_record = {
122
- 'Supervisor_AI_Coaching_Name__c': supervisor_id
 
123
  }
124
- response = sf.Supervisor_AI_Coaching__c.create(new_record)
125
- logger.debug(f"Salesforce create response: {response}")
126
-
127
- if not response.get('success'):
128
- logger.error(f"Failed to create Supervisor record: {response.get('errors')}")
129
- return jsonify({"status": "error", "message": f"Failed to create record in Salesforce: {response.get('errors')}"}), 500
130
-
131
- session['supervisor_id'] = supervisor_id
132
- logger.info(f"Signup successful for {supervisor_id}")
133
- return jsonify({"status": "success", "message": "Signup successful, you are now logged in", "redirect": "/dashboard"})
134
  except Exception as e:
135
- logger.error(f"Signup error: {str(e)}")
136
- return jsonify({"status": "error", "message": str(e)}), 500
137
-
138
- @app.route('/dashboard', methods=['GET'])
139
- def dashboard():
140
- return render_template('dashboard.html')
141
-
142
- @app.route('/home')
143
- def home():
144
- return render_template('home.html')
145
-
146
- def generate_coaching_output(data):
147
- """Generate daily checklist and tips using Hugging Face LLM."""
148
- logger.info("Generating coaching output for supervisor %s", data['supervisor_id'])
149
- milestones_json = json.dumps(data['milestones'], indent=2)
150
- prompt = f"""
151
- You are an AI Coach for construction site supervisors. Based on the following data, generate a daily checklist, three focus tips, and a motivational quote. Ensure outputs are concise, actionable, and tailored to the supervisor's role, project status, and reflection log.
152
- Supervisor ID: {data['supervisor_id']}
153
- Project Milestones: {milestones_json}
154
- Reflection Log: {data['reflection_log']}
155
- Weather: {data['weather']}
156
- Format the response as JSON:
157
- {{
158
- "checklist": ["item1", "item2", ...],
159
- "tips": ["tip1", "tip2", "tip3"],
160
- "quote": "motivational quote"
161
- }}
162
- """
163
- headers = {
164
- "Authorization": f"Bearer {HUGGING_FACE_API_TOKEN}",
165
- "Content-Type": "application/json"
166
- }
167
- payload = {
168
- "inputs": prompt,
169
- "parameters": {
170
- "max_length": 200,
171
- "temperature": 0.7,
172
- "top_p": 0.9
173
- }
174
- }
175
 
 
 
176
  try:
177
- response = requests.post(HUGGING_FACE_API_URL, headers=headers, json=payload, timeout=5)
178
- response.raise_for_status()
179
- result = response.json()
180
- generated_text = result[0]["generated_text"] if isinstance(result, list) else result["generated_text"]
181
-
182
- start_idx = generated_text.find('{')
183
- end_idx = generated_text.rfind('}') + 1
184
- if start_idx == -1 or end_idx == 0:
185
- logger.error("No valid JSON found in LLM output")
186
- raise ValueError("No valid JSON found in LLM output")
187
-
188
- json_str = generated_text[start_idx:end_idx]
189
- output = json.loads(json_str)
190
- logger.info("Successfully generated coaching output")
191
- return output
192
-
193
- except requests.exceptions.HTTPError as e:
194
- logger.error("Hugging Face API HTTP error: %s", e)
195
- return None
196
- except (json.JSONDecodeError, ValueError) as e:
197
- logger.error("Error parsing LLM output: %s", e)
198
- return None
199
  except Exception as e:
200
- logger.error("Unexpected error in Hugging Face API call: %s", e)
201
- return None
202
-
203
- def save_to_salesforce(output, supervisor_id, project_id):
204
- """Save coaching output to Salesforce Supervisor_AI_Coaching__c object."""
205
- if not output:
206
- logger.error("No coaching output to save")
207
- return False
208
 
 
 
209
  try:
210
  sf = get_salesforce_connection()
211
- logger.info("Connected to Salesforce")
212
-
213
- coaching_record = {
214
- "Supervisor_AI_Coaching_Name__c": supervisor_id,
215
- "Project_ID__c": project_id,
216
- "Daily_Checklist__c": "\n".join(output["checklist"]),
217
- "Suggested_Tips__c": "\n".join(output["tips"]),
218
- "Quote__c": output["quote"],
219
- "Generated_Date__c": datetime.now().strftime("%Y-%m-%d")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  }
 
 
221
 
222
- external_id = f"{supervisor_id}_{datetime.now().strftime('%Y-%m-%d')}"
223
- sf.Supervisor_AI_Coaching__c.upsert(f"Supervisor_AI_Coaching_Name__c/{external_id}", coaching_record)
224
- logger.info("Successfully saved coaching record to Salesforce for supervisor %s", supervisor_id)
225
- return True
226
-
227
  except Exception as e:
228
- logger.error("Salesforce error: %s", e)
229
- return False
230
-
231
- @app.route('/generate', methods=['POST'])
232
- def generate_endpoint():
233
- """Endpoint to generate coaching output based on supervisor data."""
234
- try:
235
- data = request.get_json()
236
- required_keys = ['supervisor_id', 'project_id', 'milestones', 'reflection_log', 'weather']
237
- if not data or not all(key in data for key in required_keys):
238
- return jsonify({"status": "error", "message": "Invalid or missing supervisor data"}), 400
239
-
240
- coaching_output = generate_coaching_output(data)
241
- if coaching_output:
242
- success = save_to_salesforce(coaching_output, data["supervisor_id"], data["project_id"])
243
- if success:
244
- return jsonify({"status": "success", "output": coaching_output}), 200
245
- else:
246
- return jsonify({"status": "error", "message": "Failed to save to Salesforce"}), 500
247
- else:
248
- return jsonify({"status": "error", "message": "Failed to generate coaching output"}), 500
249
- except Exception as e:
250
- logger.error("Error in generate endpoint: %s", e)
251
- return jsonify({"status": "error", "message": str(e)}), 500
252
-
253
- @app.route('/submit_reflection', methods=['POST'])
254
- def submit_reflection():
255
- """Endpoint to submit a reflection and update Salesforce."""
256
- try:
257
- data = request.get_json()
258
- reflection = data.get('reflection')
259
- supervisor_id = session.get('supervisor_id')
260
-
261
- if not reflection or not supervisor_id:
262
- return jsonify({"status": "error", "message": "Reflection and supervisor ID are required"}), 400
263
-
264
- sf = get_salesforce_connection()
265
- query = f"SELECT Id FROM Supervisor_AI_Coaching__c WHERE Supervisor_AI_Coaching_Name__c = '{quote(supervisor_id, safe='')}' LIMIT 1"
266
- result = sf.query(query)
267
-
268
- if not result['records']:
269
- return jsonify({"status": "error", "message": "Supervisor not found"}), 404
270
-
271
- record_id = result['records'][0]['Id']
272
- sf.Supervisor_AI_Coaching__c.update(record_id, {"Reflection_Log__c": reflection})
273
- logger.info(f"Reflection saved for supervisor {supervisor_id}")
274
- return jsonify({"status": "success", "message": "Reflection submitted successfully"})
275
 
276
- except Exception as e:
277
- logger.error(f"Error submitting reflection: {str(e)}")
278
- return jsonify({"status": "error", "message": str(e)}), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
 
280
- @app.route('/get_supervisor_data', methods=['GET'])
281
- def get_supervisor_data():
282
- supervisor_id = session.get('supervisor_id')
283
- if not supervisor_id:
284
- logger.warning("No supervisor ID in session")
285
- return jsonify({"status": "error", "message": "User not logged in"}), 401
286
 
 
287
  try:
288
- sf = get_salesforce_connection()
289
- supervisor_id_escaped = quote(supervisor_id, safe='')
290
- query = f"""
291
- SELECT Supervisor_AI_Coaching_Name__c, Project_ID__c, Daily_Checklist__c, Suggested_Tips__c,
292
- Reflection_Log__c, Engagement_Score__c, KPI_Flag__c, Quote__c
293
- FROM Supervisor_AI_Coaching__c
294
- WHERE Supervisor_AI_Coaching_Name__c = '{supervisor_id_escaped}'
295
- LIMIT 1
296
- """
297
- result = sf.query(query)
298
-
299
- if result['records']:
300
- record = result['records'][0]
301
- data = {
302
- "supervisor_id": record['Supervisor_AI_Coaching_Name__c'],
303
- "project_id": record['Project_ID__c'],
304
- "daily_checklist": record['Daily_Checklist__c'],
305
- "suggested_tips": record['Suggested_Tips__c'],
306
- "reflection_log": record['Reflection_Log__c'],
307
- "engagement_score": record['Engagement_Score__c'] or 0,
308
- "kpi_flag": record['KPI_Flag__c'] or False,
309
- "quote": record['Quote__c'],
310
- "last_login": str(datetime.now())
311
- }
312
- logger.info(f"Fetched data for supervisor {supervisor_id}")
313
- return jsonify({"status": "success", "data": data})
314
- else:
315
- logger.warning(f"No data found for supervisor {supervisor_id}")
316
- return jsonify({"status": "error", "message": "No data found for this supervisor"}), 404
317
  except Exception as e:
318
- logger.error(f"Error fetching supervisor data: {str(e)}")
319
- return jsonify({"status": "error", "message": str(e)}), 500
320
-
321
- @app.route('/logout', methods=['POST'])
322
- def logout():
323
- supervisor_id = session.get('supervisor_id', 'Unknown')
324
- session.pop('supervisor_id', None)
325
- logger.info(f"User {supervisor_id} logged out")
326
- return jsonify({"status": "success", "message": "Logged out successfully"})
327
-
328
- @app.route('/health', methods=['GET'])
329
- def health_check():
330
- return jsonify({"status": "healthy", "message": "Application is running"}), 200
331
-
332
- if __name__ == '__main__':
333
- port = int(os.getenv('PORT', 5000))
334
- app.run(host='0.0.0.0', port=port, debug=True)
 
1
+
2
+ import gradio as gr
3
+ from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
4
  import os
5
+ from fastapi import FastAPI
6
+ from pydantic import BaseModel
7
+ from simple_salesforce import Salesforce
8
  from dotenv import load_dotenv
 
 
 
 
 
9
 
10
  # Load environment variables
11
  load_dotenv()
12
 
13
+ # Salesforce connection
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  def get_salesforce_connection():
 
15
  try:
16
+ # Load credentials from environment variables
17
+ username = os.getenv("SF_USERNAME")
18
+ password = os.getenv("SF_PASSWORD")
19
+ security_token = os.getenv("SF_SECURITY_TOKEN")
20
+ domain = os.getenv("SF_DOMAIN", "login") # Default to production (login.salesforce.com)
21
+
22
+ # Validate credentials
23
+ if not all([username, password, security_token, domain]):
24
+ missing = []
25
+ if not username:
26
+ missing.append("SF_USERNAME")
27
+ if not password:
28
+ missing.append("SF_PASSWORD")
29
+ if not security_token:
30
+ missing.append("SF_SECURITY_TOKEN")
31
+ if not domain:
32
+ missing.append("SF_DOMAIN")
33
+ raise ValueError(f"Missing environment variables: {', '.join(missing)}. Set them in .env or Space environment variables.")
34
+
35
+ # Ensure all are strings
36
+ if not all(isinstance(x, str) for x in [username, password, security_token, domain]):
37
+ raise ValueError("All Salesforce credentials (SF_USERNAME, SF_PASSWORD, SF_SECURITY_TOKEN, SF_DOMAIN) must be strings.")
38
+
39
  sf = Salesforce(
40
+ username=username,
41
+ password=password,
42
+ security_token=security_token,
43
+ domain=domain
 
44
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ # Test connection by fetching user info
47
+ sf.User.get(sf.user_id)
48
+ return sf
49
  except Exception as e:
50
+ raise Exception(f"Failed to connect to Salesforce: {str(e)}")
51
+
52
+ # Load Hugging Face token
53
+ HF_TOKEN = os.getenv("HF_TOKEN")
54
+
55
+ # Model configuration
56
+ MODEL_PATH = "facebook/bart-large" # Public model
57
+ # MODEL_PATH = "your_actual_username/fine_tuned_bart_construction" # Uncomment after uploading
58
+
59
+ try:
60
+ model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_PATH, use_auth_token=HF_TOKEN if HF_TOKEN else None)
61
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, use_auth_token=HF_TOKEN if HF_TOKEN else None)
62
+ except Exception as e:
63
+ raise Exception(f"Failed to load model: {str(e)}")
64
+
65
+ # Define input model for FastAPI
66
+ class ChecklistInput(BaseModel):
67
+ role: str = "Supervisor"
68
+ project_id: str = "Unknown"
69
+ project_name: str = "Unknown Project"
70
+ milestones: str = "No milestones provided"
71
+ record_id: str = None
72
+ supervisor_id: str = None
73
+ project_id_sf: str = None
74
+ reflection_log: str = None
75
+ download_link: str = None
76
+
77
+ # Initialize FastAPI
78
+ app = FastAPI()
79
+
80
+ @app.post("/generate")
81
+ async def generate_checklist(data: ChecklistInput):
82
  try:
83
+ inputs = f"Role: {data.role} Project: {data.project_id} ({data.project_name}) Milestones: {data.milestones}"
84
+ input_ids = tokenizer(inputs, return_tensors="pt", max_length=128, truncation=True).input_ids
85
+ outputs = model.generate(input_ids, max_length=128, num_beams=4, early_stopping=True)
86
+ checklist = tokenizer.decode(outputs[0], skip_special_tokens=True)
87
+ tips = "1. Prioritize safety checks\n2. Review milestones\n3. Log progress"
88
+ kpi_flag = "delay" in data.milestones.lower() or "behind" in data.milestones.lower()
89
+
90
+ if data.record_id:
91
+ sf = get_salesforce_connection()
92
+ existing_record = sf.Supervisor_AI_Coaching__c.get(data.record_id, default={
93
+ 'Name': '',
94
+ 'Supervisor_ID__c': None,
95
+ 'Project_ID__c': None,
96
+ 'Reflection_Log__c': '',
97
+ 'Download_Link__c': '',
98
+ 'Engagement_Score__c': 0,
99
+ 'KPI_Flag__c': False,
100
+ 'Daily_Checklist__c': '',
101
+ 'Suggested_Tips__c': ''
102
+ })
103
+ update_data = {
104
+ 'Daily_Checklist__c': checklist,
105
+ 'Suggested_Tips__c': tips,
106
+ 'Engagement_Score__c': existing_record.get('Engagement_Score__c', 0) + 10,
107
+ 'KPI_Flag__c': kpi_flag,
108
+ 'Supervisor_ID__c': data.supervisor_id if data.supervisor_id else existing_record.get('Supervisor_ID__c'),
109
+ 'Project_ID__c': data.project_id_sf if data.project_id_sf else existing_record.get('Project_ID__c'),
110
+ 'Reflection_Log__c': data.reflection_log if data.reflection_log else existing_record.get('Reflection_Log__c', ''),
111
+ 'Download_Link__c': data.download_link if data.download_link else existing_record.get('Download_Link__c', '')
112
+ }
113
+ sf.Supervisor_AI_Coaching__c.update(data.record_id, update_data)
114
 
115
+ return {
116
+ "checklist": checklist,
117
+ "tips": tips,
118
+ "kpi_flag": kpi_flag
119
  }
 
 
 
 
 
 
 
 
 
 
120
  except Exception as e:
121
+ return {"error": str(e)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
+ # Login and display records
124
+ def login_and_display(project_id_sf):
125
  try:
126
+ sf = get_salesforce_connection()
127
+ query = f"SELECT Id, Name, Supervisor_ID__c, Project_ID__c, Daily_Checklist__c, Suggested_Tips__c, Reflection_Log__c, Engagement_Score__c, KPI_Flag__c, Download_Link__c FROM Supervisor_AI_Coaching__c WHERE Project_ID__c = '{project_id_sf}'"
128
+ records = sf.query(query)["records"]
129
+ if not records:
130
+ return "No records found for Project ID.", "", False
131
+
132
+ output = "Supervisor_AI_Coaching__c Records:\n"
133
+ for record in records:
134
+ output += (
135
+ f"Record ID: {record['Id']}\n"
136
+ f"Name: {record['Name']}\n"
137
+ f"Supervisor ID: {record['Supervisor_ID__c']}\n"
138
+ f"Project ID: {record['Project_ID__c']}\n"
139
+ f"Daily Checklist: {record['Daily_Checklist__c'] or 'N/A'}\n"
140
+ f"Suggested Tips: {record['Suggested_Tips__c'] or 'N/A'}\n"
141
+ f"Reflection Log: {record['Reflection_Log__c'] or 'N/A'}\n"
142
+ f"Engagement Score: {record['Engagement_Score__c'] or 0}%\n"
143
+ f"KPI Flag: {record['KPI_Flag__c']}\n"
144
+ f"Download Link: {record['Download_Link__c'] or 'N/A'}\n"
145
+ f"{'-'*50}\n"
146
+ )
147
+ return output, "", False
148
  except Exception as e:
149
+ return f"Error querying Salesforce: {str(e)}", "", False
 
 
 
 
 
 
 
150
 
151
+ # Generate checklist from record
152
+ def gradio_generate_checklist(record_id, role="Supervisor", project_id="Unknown", project_name="Unknown Project", milestones="No milestones provided", supervisor_id="", project_id_sf="", reflection_log="", download_link=""):
153
  try:
154
  sf = get_salesforce_connection()
155
+ existing_record = sf.Supervisor_AI_Coaching__c.get(record_id, default={
156
+ 'Name': '',
157
+ 'Supervisor_ID__c': None,
158
+ 'Project_ID__c': None,
159
+ 'Reflection_Log__c': '',
160
+ 'Download_Link__c': '',
161
+ 'Engagement_Score__c': 0,
162
+ 'KPI_Flag__c': False,
163
+ 'Daily_Checklist__c': '',
164
+ 'Suggested_Tips__c': ''
165
+ })
166
+ inputs = f"Role: {role} Project: {project_id} ({project_name}) Milestones: {milestones}"
167
+ input_ids = tokenizer(inputs, return_tensors="pt", max_length=128, truncation=True).input_ids
168
+ outputs = model.generate(input_ids, max_length=128, num_beams=4, early_stopping=True)
169
+ checklist = tokenizer.decode(outputs[0], skip_special_tokens=True)
170
+ tips = "1. Prioritize safety checks\n2. Review milestones\n3. Log progress"
171
+ kpi_flag = "delay" in milestones.lower() or "behind" in milestones.lower()
172
+
173
+ update_data = {
174
+ 'Daily_Checklist__c': checklist,
175
+ 'Suggested_Tips__c': tips,
176
+ 'Engagement_Score__c': existing_record.get('Engagement_Score__c', 0) + 10,
177
+ 'KPI_Flag__c': kpi_flag,
178
+ 'Supervisor_ID__c': supervisor_id if supervisor_id else existing_record.get('Supervisor_ID__c'),
179
+ 'Project_ID__c': project_id_sf if project_id_sf else existing_record.get('Project_ID__c'),
180
+ 'Reflection_Log__c': reflection_log if reflection_log else existing_record.get('Reflection_Log__c', ''),
181
+ 'Download_Link__c': download_link if download_link else existing_record.get('Download_Link__c', '')
182
  }
183
+ sf.Supervisor_AI_Coaching__c.update(record_id, update_data)
184
+ status = f"Updated Salesforce record {record_id}"
185
 
186
+ return checklist, tips, kpi_flag, status
 
 
 
 
187
  except Exception as e:
188
+ return f"Error: {str(e)}", "", False, ""
189
+
190
+ # Define Gradio interface
191
+ with gr.Blocks() as iface:
192
+ gr.Markdown("# AI Coach for Site Supervisors")
193
+ gr.Markdown("Enter a Project ID to view Supervisor_AI_Coaching__c records and generate checklists.")
194
+
195
+ with gr.Tab("Login"):
196
+ project_id_input = gr.Textbox(label="Project ID (Salesforce Project__c ID)", placeholder="Enter Project ID")
197
+ login_button = gr.Button("Submit")
198
+ records_output = gr.Textbox(label="Records", lines=10)
199
+ login_button.click(
200
+ fn=login_and_display,
201
+ inputs=project_id_input,
202
+ outputs=[records_output, gr.Textbox(visible=False), gr.Checkbox(visible=False)]
203
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
+ with gr.Tab("Generate Checklist"):
206
+ record_id = gr.Textbox(label="Record ID", placeholder="Enter Record ID from above")
207
+ role = gr.Textbox(label="Role", value="Supervisor")
208
+ project_id = gr.Textbox(label="Project ID", value="P001")
209
+ project_name = gr.Textbox(label="Project Name", value="Building A")
210
+ milestones = gr.Textbox(label="Milestones", value="Complete foundation by 5/15")
211
+ supervisor_id = gr.Textbox(label="Supervisor ID (Salesforce User ID, optional)", value="")
212
+ project_id_sf = gr.Textbox(label="Project ID (Salesforce Project__c ID, optional)", value="")
213
+ reflection_log = gr.Textbox(label="Reflection Log (optional)", value="")
214
+ download_link = gr.Textbox(label="Download Link (optional)", value="")
215
+ generate_button = gr.Button("Generate and Update")
216
+ checklist_output = gr.Textbox(label="Checklist")
217
+ tips_output = gr.Textbox(label="Tips")
218
+ kpi_flag_output = gr.Checkbox(label="KPI Flag")
219
+ status_output = gr.Textbox(label="Salesforce Status")
220
+ generate_button.click(
221
+ fn=gradio_generate_checklist,
222
+ inputs=[record_id, role, project_id, project_name, milestones, supervisor_id, project_id_sf, reflection_log, download_link],
223
+ outputs=[checklist_output, tips_output, kpi_flag_output, status_output]
224
+ )
225
 
226
+ # Mount FastAPI
227
+ iface.app = app
 
 
 
 
228
 
229
+ if __name__ == "__main__":
230
  try:
231
+ iface.launch(server_name="0.0.0.0", server_port=7860, share=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  except Exception as e:
233
+ print(f"Failed to launch Gradio: {str(e)}")