CoolFace
Apppublic

ModelKiln/calendar-workload-demo

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
app.py268 linesDownload Raw Back to root
1import joblib2import numpy as np3import gradio as gr4 5# Lataa malli6model = joblib.load("workload_model.joblib")7 8CLASS_NAMES = {0: "Low", 1: "Medium", 2: "High"}9EMOJI = {"Low": "🟢", "Medium": "🟠", "High": "🔴"}10 11# Esimerkkipäivät dropdownille12EXAMPLE_PRESETS = {13    "Balanced day": [3, 2.5, 4, 2, 45, 9, 16],14    "Overloaded day": [9, 7.5, 15, 0, 10, 9, 18],15    "Focused day": [2, 1.5, 2, 3, 60, 8, 15],16}17 18 19def predict_workload(20    meetings_count,21    total_meeting_hours,22    context_switches,23    deep_work_blocks,24    break_minutes,25    day_start_hour,26    day_end_hour,27):28    X = np.array([[29        meetings_count,30        total_meeting_hours,31        context_switches,32        deep_work_blocks,33        break_minutes,34        day_start_hour,35        day_end_hour,36    ]])37 38    probs = model.predict_proba(X)[0]39    pred_class = int(np.argmax(probs))40    pred_label = CLASS_NAMES[pred_class]41    confidence = float(probs[pred_class])42 43    probs_dict = {name: float(probs[i]) for i, name in CLASS_NAMES.items()}44 45    headline = (46        f"<div style='text-align:center; font-size:1.8rem; margin:1rem 0;'>"47        f"{EMOJI[pred_label]} <strong>{pred_label} Workload</strong>"48        f"</div>"49        f"<div style='text-align:center; color:#555; font-size:1.1rem;'>"50        f"Confidence: <strong>{confidence * 100:.1f}%</strong>"51        f"</div>"52    )53 54    # --- practical tips ---55    tips = []56    day_length = day_end_hour - day_start_hour57 58    if meetings_count >= 8 or total_meeting_hours >= 6:59        tips.append(60            "Consider blocking <strong>meeting-free focus time</strong> (e.g. 2–3h) and moving "61            "non-essential meetings to another day."62        )63    if context_switches >= 12:64        tips.append(65            "Try to <strong>batch similar tasks or meetings</strong> together to reduce context switching."66        )67    if deep_work_blocks == 0:68        tips.append(69            "Add at least <strong>one deep work block (60–90 minutes)</strong> for focused work without notifications."70        )71    if break_minutes < 30 and day_length >= 8:72        tips.append(73            "Increase <strong>break time</strong> slightly – even short 5–10 minute breaks every few hours reduce fatigue."74        )75    if day_length > 9:76        tips.append(77            "Your workday is long – consider <strong>moving low-priority tasks</strong> to another day or finishing earlier."78        )79 80    if not tips:81        tips.append(82            "Your setup looks balanced! To stay sustainable, consider scheduling regular deep work and micro-breaks."83        )84 85    tips_html = "<ul style='padding-left:1.2rem; line-height:1.6;'>"86    for tip in tips:87        tips_html += f"<li>{tip}</li>"88    tips_html += "</ul>"89 90    explanation = (91        "<h3 style='margin-top:1.5rem;'>💡 Personalized Suggestions</h3>"92        + tips_html +93        "<h3 style='margin-top:1.5rem;'>🧠 How the Model Works</h3>"94        "<p style='color:#555;'>This AI estimates your perceived workload using:</p>"95        "<ul style='padding-left:1.2rem; color:#555;'>"96        "<li>Number and duration of meetings</li>"97        "<li>Frequency of task/meeting switches (context switches)</li>"98        "<li>Presence of uninterrupted deep work blocks</li>"99        "<li>Total break time during the day</li>"100        "<li>Overall workday length</li>"101        "</ul>"102    )103 104    return headline, probs_dict, explanation105 106 107def load_example(example_name):108    """Täyttää sliderit valitun esimerkin arvoilla."""109    if example_name in EXAMPLE_PRESETS:110        return EXAMPLE_PRESETS[example_name]111    return [4, 3, 6, 1, 30, 9, 17]112 113 114# Teema115theme = gr.themes.Soft(116    primary_hue=gr.themes.colors.orange,117    secondary_hue=gr.themes.colors.rose,118    neutral_hue=gr.themes.colors.slate,119    radius_size=gr.themes.sizes.radius_md,120).set(121    button_primary_background_fill="*primary_500",122    button_primary_background_fill_hover="*primary_600",123    block_title_text_weight="600",124)125 126# CSS127css = """128#app-container {129    max-width: 1200px;130    margin: 0 auto;131    padding: 0 1.5rem;132}133#app-header {134    text-align: center;135    margin-bottom: 2rem;136}137#app-header h1 {138    font-weight: 700;139    font-size: 2.2rem;140    color: #222;141    margin-bottom: 0.4rem;142}143#app-header p {144    font-size: 1.1rem;145    color: #666;146    max-width: 650px;147    margin: 0 auto;148    line-height: 1.5;149}150.gr-button-primary {151    font-weight: 600;152    padding: 0.6rem 1.4rem;153    font-size: 1.05rem;154}155@media (max-width: 768px) {156    #app-header h1 {157        font-size: 1.8rem;158    }159    #app-header p {160        font-size: 1rem;161    }162    .gr-button-primary {163        width: 100%;164        padding: 0.7rem;165    }166}167"""168 169with gr.Blocks(theme=theme, css=css, title="🗓️ Workload Estimator") as demo:170    with gr.Column(elem_id="app-container"):171        gr.Markdown(172            """173            <div id="app-header">174                <h1>🗓️ Calendar Workload Estimator</h1>175                <p>Estimate your daily cognitive load based on meetings, focus time, and recovery.</p>176            </div>177            """,178            elem_id="header"179        )180 181        with gr.Tab("📊 Estimate Your Day"):182            with gr.Row(equal_height=False):183 184                # VASEN SARake: dropdown + sliderit + nappi185                with gr.Column(scale=2):186                    example_dropdown = gr.Dropdown(187                        label="💡 Load example schedule",188                        choices=list(EXAMPLE_PRESETS.keys()),189                        value=None,190                        interactive=True,191                    )192 193                    gr.Markdown("### 🗓️ Workday Structure")194                    meetings_count = gr.Slider(0, 12, value=4, step=1, label="Meetings (count)")195                    total_meeting_hours = gr.Slider(0, 9, value=3, step=0.5, label="Total meeting hours")196                    context_switches = gr.Slider(0, 20, value=6, step=1, label="Context switches")197 198                    gr.Markdown("### 🧘 Focus & Recovery")199                    deep_work_blocks = gr.Slider(0, 4, value=1, step=1, label="Deep work blocks (≥60 min)")200                    break_minutes = gr.Slider(0, 120, value=30, step=5, label="Total break minutes")201 202                    gr.Markdown("### ⏰ Workday Timing")203                    day_start_hour = gr.Slider(6, 11, value=9, step=1, label="Start hour (24h)")204                    day_end_hour = gr.Slider(14, 21, value=17, step=1, label="End hour (24h)")205 206                    btn = gr.Button("🔍 Analyze Workload", variant="primary")207 208                # OIKEA sarake: tulos209                with gr.Column(scale=1):210                    gr.Markdown("### 📈 Result")211                    headline_out = gr.HTML()212                    probs_out = gr.Label(label="Workload Probabilities")213                    explanation_out = gr.HTML()214 215            # Kun valitaan esimerkki → täytetään sliderit216            example_dropdown.change(217                load_example,218                inputs=example_dropdown,219                outputs=[220                    meetings_count,221                    total_meeting_hours,222                    context_switches,223                    deep_work_blocks,224                    break_minutes,225                    day_start_hour,226                    day_end_hour,227                ],228            )229 230            # Varsinainen ennustekutsu231            btn.click(232                predict_workload,233                inputs=[234                    meetings_count,235                    total_meeting_hours,236                    context_switches,237                    deep_work_blocks,238                    break_minutes,239                    day_start_hour,240                    day_end_hour,241                ],242                outputs=[headline_out, probs_out, explanation_out],243            )244 245        with gr.Tab("ℹ️ About"):246            gr.Markdown("""247            ### About This Tool248 249            This demo shows how **calendar metadata** can be used to estimate cognitive workload — helping you reflect on sustainability, focus, and recovery.250 251            - **Synthetic data only**: No real user data was used.252            - **Model**: Trained `RandomForestClassifier` (scikit-learn).253            - **Output**: 3-class workload (`Low`, `Medium`, `High`).254            - **Goal**: Spark reflection, not replace judgment.255 256            Use this to **simulate "what-if" scenarios**:  257            _"What if I cancel two meetings?"_ or _"What if I add a 90-min focus block?"_258 259            Built with **Python**, **scikit-learn** and **Gradio**, deployed on **Hugging Face Spaces**.260            """)261 262if __name__ == "__main__":263    demo.launch()264 265 266 267 268