How_Ready_R_U / app.py
MaryahGreene's picture
Update app.py
b9c27f4 verified
# app.py — Entrepreneurial Readiness Trainer Bot (future-proof Gradio version)
import gradio as gr
import random
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import skops.io as sio
import json
import os
import io
import base64
from datetime import datetime
from huggingface_hub import hf_hub_download
# ---- CONFIG ----
MODEL_REPO = "MaryahGreene/entrepreneur_readiness_modelt"
MODEL_FILE = "xgboost_readiness.skops"
COLS_FILE = "feature_columns.json"
LEADERBOARD_FILE = "leaderboard.csv"
# ---- LOAD MODEL ----
model = None
feature_columns = []
try:
model_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILE)
cols_path = hf_hub_download(repo_id=MODEL_REPO, filename=COLS_FILE)
trusted_types = ["xgboost.core.Booster", "xgboost.sklearn.XGBRegressor"]
with open(model_path, "rb") as f:
model = sio.load(f, trusted=trusted_types)
with open(cols_path, "r") as f:
feature_columns = json.load(f)
except Exception as e:
print("⚠️ Model failed to load:", str(e))
model = None
feature_columns = []
# ---- HELPERS ----
def make_scenario():
assets_choices = [
"N/A",
f"car({random.randint(200,5000)})",
f"house({random.randint(20000,200000)})",
f"trust({random.randint(50000,1000000)})"
]
return {
"savings_account": round(random.uniform(0, 15000), 2),
"monthly_income": round(random.uniform(0, 12000), 2),
"monthly_bills": round(random.uniform(0, 12000), 2),
"monthly_entertainment": round(random.uniform(0, 2000), 2),
"sales_skills": random.randint(1, 10),
"age": random.randint(16, 65),
"dependents": random.randint(0, 5),
"assets": random.choice(assets_choices),
"risk_level": random.randint(1, 10),
"confidence_level": random.randint(1, 10),
"idea_difficulty": random.randint(1, 10),
}
def model_predict_percent(scenario):
if model is None or not feature_columns:
return None
df = pd.DataFrame([scenario])
df = pd.get_dummies(df, columns=["assets"], dummy_na=False)
df = df.reindex(columns=feature_columns, fill_value=0)
pred = model.predict(df)[0]
return float(np.clip(pred * 10.0, 0, 100))
def tips_for_scenario(scenario, percent):
tips = []
if percent <= 50:
if scenario["sales_skills"] < 5: tips.append("📈 Boost sales skills")
if scenario["risk_level"] < 5: tips.append("⚖️ Be more comfortable with risk")
if scenario["confidence_level"] < 5: tips.append("💪 Build your confidence")
if scenario["idea_difficulty"] > 6: tips.append("🎯 Simplify your business idea")
if scenario["monthly_income"] < scenario["monthly_bills"]: tips.append("💵 Balance income vs. expenses")
advice = "⚡ Areas to improve:\n" + "\n".join([f"- {t}" for t in tips]) if tips else "⚡ Keep building your foundation!"
vibe = "💡 Needs work, but you can level up!"
elif percent >= 60:
advice = "✅ You're on track! Keep pushing forward 🚀"
vibe = "🚀🔥 You're launch-ready!"
else:
advice = "🌱 You're close — polish up a few areas."
vibe = "🌕 Solid potential, keep growing!"
return vibe, advice
def gauge_to_base64(percent):
fig = go.Figure(go.Indicator(
mode="gauge+number",
value=percent,
number={'suffix': "%"},
title={'text': "Model Readiness"},
gauge={
'axis': {'range': [0, 100]},
'bar': {'color': "purple"},
'steps': [
{'range': [0, 50], 'color': "lightpink"},
{'range': [50, 60], 'color': "plum"},
{'range': [60, 100], 'color': "mediumorchid"}
],
}
))
fig.update_layout(height=260)
buf = io.BytesIO()
fig.write_image(buf, format="png")
buf.seek(0)
img_b64 = base64.b64encode(buf.read()).decode("utf-8")
return f"![gauge](data:image/png;base64,{img_b64})"
# ---- LEADERBOARD ----
def log_result(user, guess, percent, diff, correct, mode):
record = {
"timestamp": datetime.utcnow().isoformat(),
"user": user if user else "anonymous",
"guess": guess,
"model_score": percent,
"diff": diff,
"correct": correct,
"mode": mode,
}
df = pd.DataFrame([record])
if os.path.exists(LEADERBOARD_FILE):
df.to_csv(LEADERBOARD_FILE, mode="a", header=False, index=False)
else:
df.to_csv(LEADERBOARD_FILE, index=False)
def show_leaderboard():
if os.path.exists(LEADERBOARD_FILE):
return pd.read_csv(LEADERBOARD_FILE).tail(10)
return pd.DataFrame(columns=["timestamp","user","guess","model_score","diff","correct","mode"])
def show_top_players():
if os.path.exists(LEADERBOARD_FILE):
df = pd.read_csv(LEADERBOARD_FILE)
top = df.groupby("user")["diff"].mean().reset_index()
top = top.sort_values("diff", ascending=True).head(5)
top = top.rename(columns={"diff":"avg_diff"})
# Medal emojis
medals = ["🥇","🥈","🥉","🎖️","🏅"]
top["rank"] = [medals[i] for i in range(len(top))]
return top[["rank","user","avg_diff"]]
return pd.DataFrame(columns=["rank","user","avg_diff"])
# ---- CHAT LOGIC ----
def start_game(mode="Easy"):
scenario = make_scenario()
percent = model_predict_percent(scenario)
text = "**Scenario (decide readiness 0-100%)**\n" + "\n".join([f"- {k}: {v}" for k,v in scenario.items()])
prompt = f"\nGuess the entrepreneurial readiness (0-100%). Mode: {mode}."
chat = [{"role":"assistant","content":f"{text}\n{prompt}"}]
state = {"scenario": scenario, "mode": mode, "awaiting_guess": True, "answer": percent}
return chat, state
def user_guess(history, user_message, state, username="player"):
try:
guess = float(user_message.strip().rstrip("%"))
except:
history.append({"role":"assistant","content":"⚠️ Please reply with a number 0–100."})
return history, state
percent = state["answer"]
mode = state.get("mode","Easy")
tol = 10 if mode=="Easy" else 7 if mode=="Medium" else 5
diff = abs(guess - percent)
correct = diff <= tol
if mode=="Free":
verdict = f"Model score: {percent:.1f}% (Free mode)."
else:
if correct:
verdict = f"✅ Correct! Your guess {guess:.1f}% vs model {percent:.1f}% (within ±{tol})."
else:
verdict = f"❌ Off. You guessed {guess:.1f}%, model is {percent:.1f}% (diff {diff:.1f}%)."
vibe, advice = tips_for_scenario(state["scenario"], percent)
gauge_img = gauge_to_base64(percent)
history.extend([
{"role":"user","content":user_message},
{"role":"assistant","content":verdict},
{"role":"assistant","content":gauge_img},
{"role":"assistant","content":f"{vibe}\n\n{advice}"}
])
log_result(username, guess, percent, diff, bool(correct), mode)
state["awaiting_guess"] = False
return history, state
def handle_user(history, message, state, username):
msg = message.strip().lower()
if msg in ["start","new","begin"]:
return start_game(state.get("mode","Easy"))
if msg.startswith("mode:"):
m = msg.split("mode:")[1].strip().capitalize()
if m not in ["Easy","Medium","Hard","Free"]:
history.append({"role":"assistant","content":"Unknown mode. Try Easy, Medium, Hard, Free."})
return history, state
return start_game(m)
if msg=="next":
if state.get("awaiting_guess",False):
history.append({"role":"assistant","content":"⚠️ Guess first before 'next'."})
return history, state
return start_game(state.get("mode","Easy"))
if state.get("awaiting_guess",False):
return user_guess(history, message, state, username)
return user_guess(history, message, state, username)
# ---- GRADIO UI ----
with gr.Blocks(theme=gr.themes.Soft(primary_hue="pink",secondary_hue="purple")) as demo:
gr.Markdown("## 🎮 Entrepreneurial Readiness Trainer Bot")
gr.Markdown("Type `start` to begin, or `mode:easy|medium|hard|free` to change difficulty.")
nickname = gr.Textbox(label="Nickname", value="player")
chatbot = gr.Chatbot(label="Trainer Bot", height=520, type="messages")
user_input = gr.Textbox(placeholder="Type 'start' to begin, or enter your guess…", show_label=False)
state = gr.State({"scenario":None,"mode":"Easy","awaiting_guess":False,"answer":None})
mode_selector = gr.Radio(["Easy","Medium","Hard","Free"], value="Easy", label="Mode")
new_btn = gr.Button("Start / New Scenario")
with gr.Accordion("📊 Leaderboard", open=False):
with gr.Row():
leaderboard_btn = gr.Button("Refresh Recent")
top_btn = gr.Button("Show Top Players")
leaderboard_display = gr.Dataframe(interactive=False)
def submit_message(msg, hist, st, mode, user):
st["mode"] = mode
if hist is None: hist = []
hist.append({"role":"user","content":msg})
updated, st_new = handle_user(hist, msg, st, user)
return updated, "", st_new
def new_game(mode):
chat, st = start_game(mode)
return chat, st
user_input.submit(submit_message,
inputs=[user_input, chatbot, state, mode_selector, nickname],
outputs=[chatbot, user_input, state])
new_btn.click(new_game, inputs=[mode_selector], outputs=[chatbot, state])
leaderboard_btn.click(show_leaderboard, outputs=[leaderboard_display])
top_btn.click(show_top_players, outputs=[leaderboard_display])
demo.launch()