|
import gradio as gr |
|
import logging |
|
import os |
|
import numpy as np |
|
from simple_salesforce import Salesforce |
|
from dotenv import load_dotenv |
|
|
|
|
|
logging.basicConfig(level=logging.INFO) |
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
sf_username = os.getenv("SF_USERNAME") |
|
sf_password = os.getenv("SF_PASSWORD") |
|
sf_security_token = os.getenv("SF_SECURITY_TOKEN") |
|
sf_instance_url = os.getenv("SF_INSTANCE_URL") |
|
|
|
|
|
if not sf_username or not sf_password or not sf_security_token or not sf_instance_url: |
|
logger.error("β Salesforce credentials are missing from environment variables!") |
|
raise ValueError("Salesforce credentials are not properly set.") |
|
|
|
|
|
try: |
|
sf = Salesforce( |
|
username=sf_username, |
|
password=sf_password, |
|
security_token=sf_security_token, |
|
instance_url=sf_instance_url |
|
) |
|
logger.info("β
Connected to Salesforce") |
|
except Exception as e: |
|
logger.error(f"β Salesforce connection failed: {str(e)}") |
|
raise |
|
|
|
|
|
def get_lead_score(stage, emails, meetings, close_gap, amount): |
|
|
|
return 0.8 * amount + 0.1 * emails + 0.1 * meetings |
|
|
|
def calculate_score(lead_score, emails, meetings, close_gap, amount): |
|
|
|
return lead_score * 0.5 + 0.3 * emails + 0.2 * meetings |
|
|
|
def calculate_confidence(ai_score): |
|
|
|
confidence = ai_score * 100 |
|
return min(max(confidence, 0), 100) |
|
|
|
def calculate_risk(ai_score, confidence, emails, meetings): |
|
|
|
if ai_score > 0.75 and confidence > 75: |
|
return "Low" |
|
elif ai_score > 0.5: |
|
return "Medium" |
|
else: |
|
return "High" |
|
|
|
def generate_recommendation(stage, emails, meetings, risk): |
|
|
|
return "Proceed with caution" if risk == "High" else "Proceed" |
|
|
|
def explain_score(lead_score, ai_score, confidence, risk, stage, close_gap, emails, meetings): |
|
|
|
return f"Lead score based on {emails} emails and {meetings} meetings is {lead_score}. AI score is {ai_score}, confidence is {confidence}%. Risk: {risk}." |
|
|
|
|
|
|
|
def push_to_salesforce(data: dict) -> str: |
|
try: |
|
response = sf.qualification_engine__c.create({ |
|
"Deal_Amount__c": data.get("amount"), |
|
"Stage__c": data.get("stage"), |
|
"Industry__c": data.get("industry"), |
|
"Emails_7_Days__c": data.get("emails"), |
|
"Meetings_30_Days__c": data.get("meetings"), |
|
"Days_Until_Close__c": data.get("gap"), |
|
"Rep_Feedback__c": data.get("feedback"), |
|
"Lead_Score__c": data.get("lead_score"), |
|
"AI_Score__c": data.get("score"), |
|
"Confidence__c": data.get("confidence"), |
|
"Risk_Level__c": data.get("risk"), |
|
"AI_Recommendation__c": data.get("recommendation"), |
|
"Explanation__c": data.get("explanation") |
|
}) |
|
return f"β
Pushed to Salesforce with ID: {response['id']}" |
|
except Exception as e: |
|
return f"β Salesforce Error: {str(e)}" |
|
|
|
|
|
|
|
def run_engine(amount, stage, industry, emails, meetings, close_gap, feedback=""): |
|
try: |
|
lead_score = get_lead_score(stage, emails, meetings, close_gap, amount) |
|
ai_score = calculate_score(lead_score, emails, meetings, close_gap, amount) |
|
confidence = calculate_confidence(ai_score) |
|
risk = calculate_risk(ai_score, confidence, emails, meetings) |
|
recommendation = generate_recommendation(stage, emails, meetings, risk) |
|
explanation = explain_score(lead_score, ai_score, confidence, risk, stage, close_gap, emails, meetings) |
|
|
|
sf_status = push_to_salesforce({ |
|
"amount": amount, "stage": stage, "industry": industry, |
|
"emails": emails, "meetings": meetings, "gap": close_gap, |
|
"feedback": feedback, "lead_score": lead_score, "score": ai_score, |
|
"confidence": confidence, "risk": risk, |
|
"recommendation": recommendation, "explanation": explanation |
|
}) |
|
|
|
return lead_score, ai_score, confidence, risk, recommendation, explanation, sf_status |
|
|
|
except Exception as e: |
|
return 0, 0, 0.0, "Error", "N/A", f"Error occurred: {str(e)}", f"β Error: {str(e)}" |
|
|
|
|
|
|
|
with gr.Blocks(title="AI Deal Qualification Engine") as app: |
|
|
|
gr.HTML(""" |
|
<div style="display: flex; justify-content: space-between; align-items: center; |
|
background-color: #1a1a1a; color: white; padding: 12px 20px; border-radius: 8px;"> |
|
<div> |
|
<h1 style="margin: 0; font-size: 22px;">π€ AI-Powered Deal Qualification Engine</h1> |
|
</div> |
|
<div> |
|
<button style="background-color: black; color: white; border: none; |
|
padding: 8px 16px; border-radius: 6px; cursor: pointer;"> |
|
Logout |
|
</button> |
|
</div> |
|
</div> |
|
<p style="text-align:center;">Intelligently qualify sales deals using engagement and pipeline signals.</p> |
|
""", elem_id="header") |
|
|
|
with gr.Tab("π₯ Input", elem_id="input-tab"): |
|
with gr.Row(): |
|
amount = gr.Number(label="π° Deal Amount (USD)", value=50000, elem_id="deal-amount") |
|
stage = gr.Dropdown( |
|
["Prospecting", "Proposal/Price Quote", "Negotiation", "Closed Won", "Closed Lost"], |
|
label="π Stage", |
|
elem_id="deal-stage" |
|
) |
|
industry = gr.Textbox(label="π Industry", value="Software", elem_id="industry") |
|
|
|
with gr.Row(): |
|
emails = gr.Number(label="βοΈ Emails (Last 7 Days)", value=3, elem_id="emails") |
|
meetings = gr.Number(label="π
Meetings (Last 30 Days)", value=2, elem_id="meetings") |
|
close_gap = gr.Number(label="π Days Until Close", value=14, elem_id="days-until-close") |
|
|
|
feedback = gr.Textbox(label="π¬ Optional: Rep Feedback", placeholder="Add any qualitative insights...", elem_id="feedback") |
|
submit = gr.Button("π Run AI Scoring", elem_id="submit-btn") |
|
|
|
with gr.Tab("π Results", elem_id="result-tab"): |
|
with gr.Accordion("AI Scoring Output", open=True): |
|
lead_score_out = gr.Number(label="π’ Lead Score", interactive=False, elem_id="lead-score") |
|
ai_score_out = gr.Number(label="π AI Score (0β100)", interactive=False, elem_id="ai-score") |
|
confidence_out = gr.Number(label="π Confidence", interactive=False, elem_id="confidence") |
|
|
|
risk_out = gr.Textbox(label="β οΈ Risk Level", lines=1, interactive=False, elem_id="risk-level") |
|
reco_out = gr.Textbox(label="π‘ AI Recommendation", lines=2, interactive=False, elem_id="ai-recommendation") |
|
explain_out = gr.Textbox(label="π§ Explanation", lines=5, interactive=False, elem_id="explanation") |
|
|
|
status = gr.Markdown("", elem_id="status") |
|
|
|
submit.click( |
|
fn=run_engine, |
|
inputs=[amount, stage, industry, emails, meetings, close_gap, feedback], |
|
outputs=[lead_score_out, ai_score_out, confidence_out, risk_out, reco_out, explain_out, status] |
|
) |
|
|
|
app.launch(share=True) |
|
|