File size: 8,796 Bytes
ed02923
7672cab
d1f37f7
 
7672cab
a4c49c1
d1f37f7
 
 
 
 
7672cab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59c7657
c4961bf
7672cab
 
 
 
 
c4961bf
 
67a7a8f
4b6fd28
 
76b9458
 
 
4b6fd28
76b9458
 
a4c49c1
 
76b9458
 
a4c49c1
59c7657
76b9458
c4961bf
76b9458
59c7657
76b9458
67a7a8f
76b9458
 
a4c49c1
 
67a7a8f
4b6fd28
a4c49c1
 
59c7657
76b9458
59c7657
76b9458
 
7672cab
c4961bf
7672cab
 
a4c49c1
 
7672cab
c4961bf
 
 
 
 
 
 
 
 
 
a4c49c1
 
 
7672cab
67a7a8f
 
7672cab
 
c4961bf
 
 
a4c49c1
7672cab
 
4b6fd28
 
 
c4961bf
a4c49c1
 
59c7657
 
7672cab
59c7657
a4c49c1
 
 
59c7657
7672cab
 
 
 
 
736dc08
59c7657
c4961bf
d72f55d
59c7657
d1f37f7
c4961bf
7672cab
59c7657
 
 
 
 
 
39fbd88
 
d72f55d
 
 
 
 
 
 
 
76b9458
7672cab
c4961bf
 
39fbd88
d72f55d
7672cab
59c7657
7672cab
c4961bf
736dc08
 
d1f37f7
736dc08
c4961bf
736dc08
a4c49c1
4b6fd28
d72f55d
c4961bf
d72f55d
c4961bf
 
59c7657
 
c4961bf
59c7657
d72f55d
c7ba52a
c4961bf
 
7672cab
736dc08
 
59c7657
a4c49c1
736dc08
7672cab
736dc08
 
 
a4c49c1
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import gradio as gr
from simple_salesforce import Salesforce
import os
import logging
from datetime import datetime
import pytz

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Salesforce credentials (using environment variables for security, with defaults)
SF_USERNAME = os.getenv('SF_USERNAME', 'Ai@Coach.com')
SF_PASSWORD = os.getenv('SF_PASSWORD', 'Teja90325@')
SF_SECURITY_TOKEN = os.getenv('SF_SECURITY_TOKEN', 'clceSdBgQ30Rx9BSC66gAcRx')
SF_DOMAIN = os.getenv('SF_DOMAIN', 'login')

# Initialize Salesforce connection
try:
    sf = Salesforce(
        username=SF_USERNAME,
        password=SF_PASSWORD,
        security_token=SF_SECURITY_TOKEN,
        domain=SF_DOMAIN
    )
    logger.info("Successfully connected to Salesforce")
except Exception as e:
    logger.error(f"Failed to connect to Salesforce: {e}")
    sf = None

def store_in_salesforce(project_id, role, checklist, suggestions, reflection):
    """Store the generated data in Salesforce."""
    if sf is None:
        logger.error("Salesforce connection not initialized")
        return "Error: Salesforce connection not initialized"

    try:
        # Map Hugging Face role "Supervisor" to Salesforce role "SiteSupervisor"
        salesforce_role = "SiteSupervisor" if role == "Supervisor" else role

        # Step 1: Find the Project__c record by Name (escape special characters in project_id)
        project_id_safe = project_id.replace("'", "''")  # Escape single quotes for SOQL
        project_query = f"""
            SELECT Id
            FROM Project__c
            WHERE Name = '{project_id_safe}'
            LIMIT 1
        """
        project_result = sf.query(project_query)
        if not project_result['records']:
            logger.error(f"No Project__c record found with Name {project_id}")
            return f"Error: No Project__c record found with Name {project_id}"
        project_sf_id = project_result['records'][0]['Id']
        logger.info(f"Found Project__c record with Id {project_sf_id} for Name {project_id}")

        # Step 2: Find the Supervisor__c record by Role__c (mapped to SiteSupervisor)
        supervisor_query = f"""
            SELECT Id, Name
            FROM Supervisor__c
            WHERE Role__c = '{salesforce_role}'
            LIMIT 1
        """
        supervisor_result = sf.query(supervisor_query)
        if not supervisor_result['records']:
            logger.error(f"No Supervisor__c record found with Role__c {salesforce_role}")
            return f"Error: No Supervisor__c record found with Role__c {salesforce_role}"
        supervisor_sf_id = supervisor_result['records'][0]['Id']
        supervisor_name = supervisor_result['records'][0]['Name']
        logger.info(f"Found Supervisor__c record with Id {supervisor_sf_id} and Name {supervisor_name} for Role__c {salesforce_role}")

        # Step 3: Check for existing Supervisor_AI_Coaching__c record
        coaching_query = f"""
            SELECT Id
            FROM Supervisor_AI_Coaching__c
            WHERE Project_ID__c = '{project_sf_id}' AND Supervisor_ID__c = '{supervisor_sf_id}'
            LIMIT 1
        """
        coaching_result = sf.query(coaching_query)
        logger.info(f"Found {len(coaching_result['records'])} existing Supervisor_AI_Coaching__c records")

        # Step 4: Calculate Engagement Score and KPI Flag
        engagement_score = 50
        if checklist and suggestions:
            engagement_score = 75
        elif checklist or suggestions:
            engagement_score = 60

        kpi_flag = 'delay' in suggestions.lower() or 'issue' in suggestions.lower()

        # Step 5: Prepare the data to store
        # Format the DateTime field for Salesforce (ISO 8601 with 'Z' for UTC)
        last_refresh_date = datetime.utcnow().replace(tzinfo=pytz.UTC).isoformat()

        coaching_data = {
            'Project_ID__c': project_sf_id,
            'Supervisor_ID__c': supervisor_sf_id,
            'Daily_Checklist__c': checklist,
            'Suggested_Tips__c': suggestions,
            'Reflection_Log__c': reflection,
            'Engagement_Score__c': engagement_score,
            'KPI_Flag__c': kpi_flag,
            'Last_Refresh_Date__c': last_refresh_date
        }

        # Log the data being stored for verification
        logger.info(f"Data to be stored in Supervisor_AI_Coaching__c: {coaching_data}")

        # Step 6: Update or create the record
        if coaching_result['records']:
            record_id = coaching_result['records'][0]['Id']
            sf.Supervisor_AI_Coaching__c.update(record_id, coaching_data)
            logger.info(f"Updated Supervisor_AI_Coaching__c record with Id {record_id}")
        else:
            result = sf.Supervisor_AI_Coaching__c.create(coaching_data)
            if not result['success']:
                logger.error(f"Failed to create Supervisor_AI_Coaching__c record: {result['errors']}")
                return f"Error creating Supervisor_AI_Coaching__c record: {result['errors']}"
            logger.info(f"Created new Supervisor_AI_Coaching__c record with Id {result['id']}")

        return "Successfully stored in Salesforce"
    except Exception as e:
        logger.error(f"Error storing in Salesforce: {e}")
        return f"Error storing in Salesforce: {e}"

def generate_outputs(role, project_id, reflection, milestone):
    """Generate checklist and suggestions using rule-based logic for speed."""
    # Input validation
    if not all([role, project_id, reflection, milestone]):
        logger.error("All fields are required")
        return "", "", "Error: All fields are required."

    # Checklist: Generate from milestone input
    milestones_list = "\n- ".join([m.strip() for m in milestone.split(",") if m.strip()])
    if not milestones_list:
        logger.error("At least one valid milestone is required")
        return "", "", "Error: At least one valid milestone is required."
    checklist = f"- {milestones_list}"

    # Generate suggestions based on reflection (rule-based)
    suggestions_list = []
    reflection_lower = reflection.lower()
    if "delays" in reflection_lower:
        suggestions_list.extend(["Adjust timelines for delays.", "Communicate with stakeholders."])
    if "weather" in reflection_lower:
        suggestions_list.extend(["Ensure rain gear availability.", "Monitor weather updates."])
    if "equipment" in reflection_lower:
        suggestions_list.extend(["Inspect equipment.", "Schedule maintenance."])
    if any(keyword in reflection_lower for keyword in ["information", "plan", "specification", "management"]):
        suggestions_list.extend(["Review the project information plan.", "Ensure all team members are updated."])
    if any(keyword in reflection_lower for keyword in ["personal", "experience", "learning", "feeling", "thinking"]):
        suggestions_list.extend(["Schedule a one-on-one meeting to discuss concerns.", "Provide additional training if needed."])
    suggestions = "\n- ".join(suggestions_list) if suggestions_list else "No specific suggestions."

    # Store the generated outputs in Salesforce
    storage_result = store_in_salesforce(project_id, role, checklist, suggestions, reflection)

    return checklist, suggestions, storage_result

def create_interface():
    """Create Gradio interface for manual testing."""
    with gr.Blocks() as demo:
        gr.Markdown("### AI Coach for Site Supervisors")
        with gr.Row():
            role = gr.Dropdown(choices=["Site Supervisor", "Foreman", "Project Manager"], label="Role", value="Supervisor")
            project_id = gr.Textbox(label="Project ID", placeholder="e.g., PROJ-003")
        reflection = gr.Textbox(
            label="Reflection Log",
            lines=3,
            placeholder="Reflect on your personal response to what you have been experiencing, learning, doing, feeling, and thinking..."
        )
        milestone = gr.Textbox(
            label="Milestone",
            lines=2,
            placeholder="Enter milestones (comma-separated), e.g., Foundation complete, Framing started..."
        )
        submit = gr.Button("Generate")
        checklist_output = gr.Textbox(label="Daily Checklist", lines=4)
        suggestions_output = gr.Textbox(label="Suggested Tips", lines=4)

        submit.click(
            fn=generate_outputs,
            inputs=[role, project_id, reflection, milestone],
            outputs=[checklist_output, suggestions_output]
        )

    return demo

if __name__ == "__main__":
    try:
        demo = create_interface()
        demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
    except Exception as e:
        logger.error(f"Error launching Gradio interface: {e}")