import requests import json import logging from datetime import datetime from simple_salesforce import Salesforce from flask import Flask, jsonify, request, render_template, redirect, url_for # Configure logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Hugging Face API configuration HUGGING_FACE_API_URL = "https://api-inference.huggingface.co/models/distilgpt2" HUGGING_FACE_API_TOKEN = "your_hugging_face_api_token_here" # Replace with your actual Hugging Face API token # Salesforce configuration SALESFORCE_USERNAME = "Ai@Coach.com" SALESFORCE_PASSWORD = "Teja90325@" SALESFORCE_SECURITY_TOKEN = "clceSdBgQ30Rx9BSC66gAcRx" SALESFORCE_DOMAIN = "login.salesforce.com" # Validate configuration if not HUGGING_FACE_API_TOKEN: logger.error("HUGGING_FACE_API_TOKEN is not set") raise ValueError("HUGGING_FACE_API_TOKEN must be provided") if not HUGGING_FACE_API_URL.startswith("https://api-inference.huggingface.co/models/"): logger.error("Invalid HUGGING_FACE_API_URL: %s", HUGGING_FACE_API_URL) raise ValueError("HUGGING_FACE_API_URL must point to a valid Hugging Face model") if not all([SALESFORCE_USERNAME, SALESFORCE_PASSWORD, SALESFORCE_SECURITY_TOKEN]): logger.error("Salesforce credentials are incomplete") raise ValueError("Salesforce credentials must be set") # Initialize Flask app app = Flask(__name__) def generate_coaching_output(data): """ Generate daily checklist and tips using Hugging Face LLM. """ logger.info("Generating coaching output for supervisor %s", data['supervisor_id']) milestones_json = json.dumps(data['milestones'], indent=2) prompt = f""" 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. Supervisor Role: {data['role']} Project Milestones: {milestones_json} Reflection Log: {data['reflection_log']} Weather: {data['weather']} Format the response as JSON: {{ "checklist": ["item1", "item2", ...], "tips": ["tip1", "tip2", "tip3"], "quote": "motivational quote" }} """ headers = { "Authorization": f"Bearer {HUGGING_FACE_API_TOKEN}", "Content-Type": "application/json" } payload = { "inputs": prompt, "parameters": { "max_length": 200, "temperature": 0.7, "top_p": 0.9 } } try: response = requests.post(HUGGING_FACE_API_URL, headers=headers, json=payload, timeout=5) response.raise_for_status() result = response.json() generated_text = result[0]["generated_text"] if isinstance(result, list) else result["generated_text"] start_idx = generated_text.find('{') end_idx = generated_text.rfind('}') + 1 if start_idx == -1 or end_idx == 0: logger.error("No valid JSON found in LLM output") raise ValueError("No valid JSON found in LLM output") json_str = generated_text[start_idx:end_idx] output = json.loads(json_str) logger.info("Successfully generated coaching output") return output except requests.exceptions.HTTPError as e: logger.error("Hugging Face API HTTP error: %s", e) return None except (json.JSONDecodeError, ValueError) as e: logger.error("Error parsing LLM output: %s", e) return None except Exception as e: logger.error("Unexpected error in Hugging Face API call: %s", e) return None def save_to_salesforce(output, supervisor_id, project_id): """ Save coaching output to Salesforce Supervisor_AI_Coaching__c object. """ if not output: logger.error("No coaching output to save") return False try: sf = Salesforce( username=SALESFORCE_USERNAME, password=SALESFORCE_PASSWORD, security_token=SALESFORCE_SECURITY_TOKEN, domain=SALESFORCE_DOMAIN ) logger.info("Connected to Salesforce") coaching_record = { "Supervisor_ID__c": supervisor_id, "Project_ID__c": project_id, "Daily_Checklist__c": "\n".join(output["checklist"]), "Suggested_Tips__c": "\n".join(output["tips"]), "Quote__c": output["quote"], "Generated_Date__c": datetime.now().strftime("%Y-%m-%d") } sf.Supervisor_AI_Coaching__c.upsert( f"Supervisor_ID__c/{supervisor_id}_{datetime.now().strftime('%Y-%m-%d')}", coaching_record ) logger.info("Successfully saved coaching record to Salesforce for supervisor %s", supervisor_id) return True except Exception as e: logger.error("Salesforce error: %s", e) return False def fetch_salesforce_data(supervisor_id, project_id): """ Fetch coaching data from Salesforce for a given supervisor and project. """ try: sf = Salesforce( username=SALESFORCE_USERNAME, password=SALESFORCE_PASSWORD, security_token=SALESFORCE_SECURITY_TOKEN, domain=SALESFORCE_DOMAIN ) logger.info("Connected to Salesforce for data fetch") query = f""" SELECT Daily_Checklist__c, Suggested_Tips__c, Quote__c, Generated_Date__c FROM Supervisor_AI_Coaching__c WHERE Supervisor_ID__c = '{supervisor_id}' AND Project_ID__c = '{project_id}' ORDER BY Generated_Date__c DESC LIMIT 1 """ result = sf.query(query) if result['totalSize'] > 0: record = result['records'][0] return { 'checklist': record['Daily_Checklist__c'].split('\n') if record['Daily_Checklist__c'] else [], 'tips': record['Suggested_Tips__c'].split('\n') if record['Suggested_Tips__c'] else [], 'quote': record['Quote__c'] or '' } else: logger.info("No coaching data found for supervisor %s and project %s", supervisor_id, project_id) return None except Exception as e: logger.error("Salesforce fetch error: %s", e) return None @app.route('/', methods=['GET']) def redirect_to_ui(): """ Redirect root URL to the UI. """ return redirect(url_for('ui')) @app.route('/ui', methods=['GET', 'POST']) def ui(): """ Serve the HTML user interface and handle form submissions. """ form_data = {} output = {} error = "" if request.method == 'POST': action = request.form.get('action') form_data = { 'supervisor_id': request.form.get('supervisor_id', ''), 'role': request.form.get('role', ''), 'project_id': request.form.get('project_id', ''), 'weather': request.form.get('weather', ''), 'milestones': request.form.get('milestones', ''), 'reflection': request.form.get('reflection', '') } if action == 'generate': # Validate all fields if not all([form_data['supervisor_id'], form_data['role'], form_data['project_id'], form_data['weather'], form_data['milestones'], form_data['reflection']]): error = "Error: All fields are required." else: # First, try to fetch existing data from Salesforce sf_data = fetch_salesforce_data(form_data['supervisor_id'], form_data['project_id']) if sf_data: output = sf_data else: # If no data exists, generate new output data = { 'supervisor_id': form_data['supervisor_id'], 'role': form_data['role'], 'project_id': form_data['project_id'], 'milestones': [m.strip() for m in form_data['milestones'].split(',') if m.strip()], 'reflection_log': form_data['reflection'], 'weather': form_data['weather'] } coaching_output = generate_coaching_output(data) if coaching_output: success = save_to_salesforce(coaching_output, data['supervisor_id'], data['project_id']) if success: output = coaching_output else: error = "Error: Failed to save to Salesforce." else: error = "Error: Failed to generate coaching output." return render_template('index.html', form_data=form_data, output=output, error=error) @app.route('/health', methods=['GET']) def health_check(): """ Health check endpoint. """ return jsonify({"status": "healthy", "message": "Application is running"}), 200 if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)