geethareddy's picture
Update app.py
02615cd verified
import requests
import json
import os
import logging
from datetime import datetime
from dotenv import load_dotenv
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__)
# Load environment variables
load_dotenv()
# Hugging Face API configuration
HUGGING_FACE_API_URL = os.getenv("HUGGING_FACE_API_URL", "https://api-inference.huggingface.co/models/distilgpt2")
HUGGING_FACE_API_TOKEN = os.getenv("HUGGING_FACE_API_TOKEN")
# Salesforce configuration
SALESFORCE_USERNAME = os.getenv("SALESFORCE_USERNAME")
SALESFORCE_PASSWORD = os.getenv("SALESFORCE_PASSWORD")
SALESFORCE_SECURITY_TOKEN = os.getenv("SALESFORCE_SECURITY_TOKEN")
SALESFORCE_DOMAIN = os.getenv("SALESFORCE_DOMAIN", "login")
# Validate environment variables
if not HUGGING_FACE_API_TOKEN:
logger.error("HUGGING_FACE_API_TOKEN is not set")
raise ValueError("HUGGING_FACE_API_TOKEN environment variable is not set")
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
@app.route('/', methods=['GET'])
def redirect_to_ui():
"""
Redirect root URL to the UI.
"""
return redirect(url_for('ui'))
@app.route('/ui', methods=['GET'])
def ui():
"""
Serve the HTML user interface.
"""
return render_template('index.html')
@app.route('/generate', methods=['POST'])
def generate_endpoint():
"""
Endpoint to generate coaching output based on supervisor data.
"""
try:
data = request.get_json()
if not data or not all(key in data for key in ['supervisor_id', 'role', 'project_id', 'milestones', 'reflection_log', 'weather']):
return jsonify({"status": "error", "message": "Invalid or missing supervisor data"}), 400
coaching_output = generate_coaching_output(data)
if coaching_output:
success = save_to_salesforce(coaching_output, data["supervisor_id"], data["project_id"])
if success:
return jsonify({"status": "success", "output": coaching_output}), 200
else:
return jsonify({"status": "error", "message": "Failed to save to Salesforce"}), 500
else:
return jsonify({"status": "error", "message": "Failed to generate coaching output"}), 500
except Exception as e:
logger.error("Error in generate endpoint: %s", e)
return jsonify({"status": "error", "message": str(e)}), 500
@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=int(os.getenv("PORT", 7860)))