{ "cells": [ { "cell_type": "markdown", "id": "758e4c36", "metadata": {}, "source": [ "# CTM Token Calculator — Genesys AI Cost & Business Case\n", "\n", "**Version 0.1.0** · interactive working analysis for Robert / CTM stakeholders / NTT delivery.\n", "\n", "Models Genesys Cloud **CX 3** platform + AI feature costs (published token meters,\n", "confidence-flagged) against pressure-tested benefit scenarios — replacing single-point\n", "vendor ROI outputs with **Floor / Realistic / Stretch** sensitivity-aware analysis.\n", "\n", "> ⚠️ **Planning tool.** List rates unless overridden; not contractual pricing.\n", "> Site data outside NAM is **estimated — confirm with CTM**.\n", "\n", "Same `tokencalc` library that powers the corrected business case notebook — serve either interactively with `mercury --working-dir notebooks/` —\n", "Run-All here produces identical headline numbers on default inputs." ] }, { "cell_type": "code", "execution_count": 1, "id": "57efb206", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:57.711516Z", "iopub.status.busy": "2026-07-13T19:32:57.711205Z", "iopub.status.idle": "2026-07-13T19:32:58.206644Z", "shell.execute_reply": "2026-07-13T19:32:58.205709Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tokencalc loaded — 9 sites, 2,088 named users (contracted: 2,088)\n" ] } ], "source": [ "# ── Setup ──────────────────────────3rd with just the────────────────────────────────\n", "import sys, pathlib\n", "_ROOT = pathlib.Path.cwd()\n", "if not (_ROOT / \"tokencalc\").exists(): # notebook lives in notebooks/\n", " _ROOT = _ROOT.parent\n", "sys.path.insert(0, str(_ROOT))\n", "\n", "import dataclasses\n", "import pandas as pd\n", "import plotly.express as px\n", "import plotly.graph_objects as go\n", "\n", "from tokencalc import *\n", "from tokencalc.scenarios import BENEFIT_PARAMS\n", "\n", "pd.options.display.float_format = \"{:,.0f}\".format\n", "print(f\"tokencalc loaded — {len(CTM_DEFAULT_SITES)} sites, \"\n", " f\"{sum(s.named_users for s in CTM_DEFAULT_SITES):,} named users \"\n", " f\"(contracted: {CONTRACTED_NAMED_USERS:,})\")" ] }, { "cell_type": "markdown", "id": "cbf6851d", "metadata": {}, "source": [ "## Inputs\n", "\n", "Sites, cost takeouts, and feature scoping as Python objects (CTM defaults).\n", "To resume a saved scenario instead:\n", "`sites, takeouts, scopes = scenario_state_from_json(\"my_scenario.json\")`" ] }, { "cell_type": "code", "execution_count": 2, "id": "361bde24", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:58.210328Z", "iopub.status.busy": "2026-07-13T19:32:58.209921Z", "iopub.status.idle": "2026-07-13T19:32:58.234502Z", "shell.execute_reply": "2026-07-13T19:32:58.233799Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
site_nameregion_pricingagentssupervisorsvoice_volume_monthlyemail_volume_monthlychat_volume_monthlysms_volume_monthlyvoice_aht_secondsemail_aht_secondschat_aht_secondsvoice_acw_secondsfully_loaded_agent_cost_annualfully_loaded_supervisor_cost_annuallicence_typelanguages
0NAMUS8906012143582758001101040300600480606500095000namedEnglish, French, Spanish
1EMEAEU320254200009500040400300600480606000088000namedEnglish, French, German, Italian, Spanish
2AUZAU1801525000056000252503006004806070000100000namedEnglish
3APAC HKAPAC120101600003800015150300600480605500080000namedEnglish, Cantonese, Mandarin
4APAC SGAPAC110101500003400015120300600480605500080000namedEnglish, Mandarin, Malay
5APAC SHAPAC130101750004000015130300600480603500055000namedMandarin
6APAC GZAPAC9081200002800010100300600480603500055000namedMandarin, Cantonese
7APAC JPAPAC6068000019000880300600480606000085000namedJapanese
8APAC TWAPAC4045400012000550300600480604000060000namedMandarin
\n", "
" ], "text/plain": [ " site_name region_pricing agents supervisors voice_volume_monthly \\\n", "0 NAM US 890 60 1214358 \n", "1 EMEA EU 320 25 420000 \n", "2 AUZ AU 180 15 250000 \n", "3 APAC HK APAC 120 10 160000 \n", "4 APAC SG APAC 110 10 150000 \n", "5 APAC SH APAC 130 10 175000 \n", "6 APAC GZ APAC 90 8 120000 \n", "7 APAC JP APAC 60 6 80000 \n", "8 APAC TW APAC 40 4 54000 \n", "\n", " email_volume_monthly chat_volume_monthly sms_volume_monthly \\\n", "0 275800 110 1040 \n", "1 95000 40 400 \n", "2 56000 25 250 \n", "3 38000 15 150 \n", "4 34000 15 120 \n", "5 40000 15 130 \n", "6 28000 10 100 \n", "7 19000 8 80 \n", "8 12000 5 50 \n", "\n", " voice_aht_seconds email_aht_seconds chat_aht_seconds voice_acw_seconds \\\n", "0 300 600 480 60 \n", "1 300 600 480 60 \n", "2 300 600 480 60 \n", "3 300 600 480 60 \n", "4 300 600 480 60 \n", "5 300 600 480 60 \n", "6 300 600 480 60 \n", "7 300 600 480 60 \n", "8 300 600 480 60 \n", "\n", " fully_loaded_agent_cost_annual fully_loaded_supervisor_cost_annual \\\n", "0 65000 95000 \n", "1 60000 88000 \n", "2 70000 100000 \n", "3 55000 80000 \n", "4 55000 80000 \n", "5 35000 55000 \n", "6 35000 55000 \n", "7 60000 85000 \n", "8 40000 60000 \n", "\n", " licence_type languages \n", "0 named English, French, Spanish \n", "1 named English, French, German, Italian, Spanish \n", "2 named English \n", "3 named English, Cantonese, Mandarin \n", "4 named English, Mandarin, Malay \n", "5 named Mandarin \n", "6 named Mandarin, Cantonese \n", "7 named Japanese \n", "8 named Mandarin " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
takeoutannual_coststart_yearconfidencenotes
0NICE IEX (NAM)13000001🟡 estimatedMid-band estimate; needs CTM contract confirma...
1Legacy CC platform02🔴 unknownPlaceholder — populate once retirement scope i...
\n", "
" ], "text/plain": [ " takeout annual_cost start_year confidence \\\n", "0 NICE IEX (NAM) 1300000 1 🟡 estimated \n", "1 Legacy CC platform 0 2 🔴 unknown \n", "\n", " notes \n", "0 Mid-band estimate; needs CTM contract confirma... \n", "1 Placeholder — populate once retirement scope i... " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sites = list(CTM_DEFAULT_SITES)\n", "takeouts = list(CTM_DEFAULT_TAKEOUTS)\n", "scopes = list(CTM_DEFAULT_FEATURE_SCOPES)\n", "meters = dict(DEFAULT_METERS)\n", "pricing = dict(DEFAULT_PRICING)\n", "\n", "total_users = sum(s.named_users for s in sites)\n", "if total_users != CONTRACTED_NAMED_USERS:\n", " print(f\"⚠️ Named users ({total_users:,}) ≠ contracted licences \"\n", " f\"({CONTRACTED_NAMED_USERS:,})\")\n", "\n", "display(sites_dataframe(sites))\n", "display(pd.DataFrame([{\"takeout\": t.name, \"annual_cost\": t.annual_cost,\n", " \"start_year\": t.start_year,\n", " \"confidence\": t.confidence.icon + \" \" + t.confidence.value,\n", " \"notes\": t.notes} for t in takeouts]))" ] }, { "cell_type": "markdown", "id": "51e84f75", "metadata": {}, "source": [ "## Token meters\n", "\n", "Source: [Genesys Cloud AI Experience metering details](https://help.genesys.cloud/articles/genesys-cloud-tokens-model/) (2026-06-07)\n", "\n", "🟢 confirmed (published Genesys rate) · 🟡 estimated · 🔴 unknown (working default, rate not yet published).\n", "\n", "**Licence variants** — Agent Copilot and Speech & Text Analytics each have two published rates:\n", "- **[named]** — 40 tok/user/month (Copilot) · 30 tok/user/month (STA)\n", "- **[concurrent]** — 60 tok/user/month (Copilot) · 45 tok/user/month (STA)\n", "\n", "CTM has **named** licences; the `[named]` variants are used in `CTM_DEFAULT_FEATURE_SCOPES`.\n", "Override by swapping the feature name in `scopes` for sites with concurrent licences.\n", "\n", "**Copilot rule:** Agent Copilot includes interaction summarization, so\n", "AI Summary & Insights is never billed at Copilot-enabled sites.\n", "\n", "**New in 2026-06-07 catalogue:** Digital Bot (51 sessions/token), AI Scoring\n", "(20 evaluations/token), Predictive Routing (17 routes/token), Genesys Cloud Copilot\n", "(20 AI actions/token), and AI Translate is now a confirmed consumption meter\n", "(2 translations/token, previously UNKNOWN)." ] }, { "cell_type": "code", "execution_count": 3, "id": "72311955", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:58.236321Z", "iopub.status.busy": "2026-07-13T19:32:58.236148Z", "iopub.status.idle": "2026-07-13T19:32:58.246527Z", "shell.execute_reply": "2026-07-13T19:32:58.245798Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
featuremeter_typeunits_per_tokentokens_per_unitconfidencenotessource
0Voice Botper_minute170🟢 confirmedIVR self-service voice bot minutes; 17 min per...https://help.genesys.cloud/articles/genesys-cl...
1Digital Botper_interaction510🟢 confirmedDigital (non-voice) bot sessions; 51 sessions ...https://help.genesys.cloud/articles/genesys-cl...
2Virtual Agent (legacy)per_interaction20🟢 confirmedLegacy (non-agentic) virtual agent; 0.5 tokens...https://help.genesys.cloud/articles/genesys-cl...
3Agentic Virtual Agentper_interaction11🟢 confirmedAgentic VA; 1.2 tokens per interaction.https://help.genesys.cloud/articles/genesys-cl...
4Agent Copilot [named]per_user_per_monthNaN40🟢 confirmed40 tokens per named user per month. Includes i...https://help.genesys.cloud/articles/genesys-cl...
5Agent Copilot [concurrent]per_user_per_monthNaN60🟢 confirmed60 tokens per concurrent user per month. Inclu...https://help.genesys.cloud/articles/genesys-cl...
6AI Scoringper_interaction200🟢 confirmedAI-scored quality evaluations; 20 evaluations ...https://help.genesys.cloud/articles/genesys-cl...
7AI Summary & Insightsper_summary500🟢 confirmedSupervisor standalone summarization; 50 summar...https://help.genesys.cloud/articles/genesys-cl...
8Speech & Text Analytics [named]per_user_per_monthNaN30🟢 confirmedSTA named licence; 30 tokens per named user pe...https://help.genesys.cloud/articles/genesys-cl...
9Speech & Text Analytics [concurrent]per_user_per_monthNaN45🟢 confirmedSTA concurrent licence; 45 tokens per concurre...https://help.genesys.cloud/articles/genesys-cl...
10Predictive Routingper_interaction170🟢 confirmedPredictive routing; 17 routes per token.https://help.genesys.cloud/articles/genesys-cl...
11Direct Messagingper_message4000🟢 confirmedApple Messages for Business, Facebook Messenge...https://help.genesys.cloud/articles/genesys-cl...
12Social Listeningper_message4000🟢 confirmedGenesys Cloud Social; 400 social post ingestio...https://help.genesys.cloud/articles/genesys-cl...
13Social Responsesper_message4000🟢 confirmedSocial Post Responses; 400 outbound messages p...https://help.genesys.cloud/articles/genesys-cl...
14AI Translateper_interaction20🟢 confirmedAI translation; 2 translations per token.https://help.genesys.cloud/articles/genesys-cl...
15Genesys Cloud Copilotper_interaction200🟢 confirmed20 AI actions per token; Genesys Cloud knowled...https://help.genesys.cloud/articles/genesys-cl...
16Email AI (Auto-Respond)per_messageNaN0🔴 unknownFeature not yet available; rate TBD.
\n", "
" ], "text/plain": [ " feature meter_type units_per_token \\\n", "0 Voice Bot per_minute 17 \n", "1 Digital Bot per_interaction 51 \n", "2 Virtual Agent (legacy) per_interaction 2 \n", "3 Agentic Virtual Agent per_interaction 1 \n", "4 Agent Copilot [named] per_user_per_month NaN \n", "5 Agent Copilot [concurrent] per_user_per_month NaN \n", "6 AI Scoring per_interaction 20 \n", "7 AI Summary & Insights per_summary 50 \n", "8 Speech & Text Analytics [named] per_user_per_month NaN \n", "9 Speech & Text Analytics [concurrent] per_user_per_month NaN \n", "10 Predictive Routing per_interaction 17 \n", "11 Direct Messaging per_message 400 \n", "12 Social Listening per_message 400 \n", "13 Social Responses per_message 400 \n", "14 AI Translate per_interaction 2 \n", "15 Genesys Cloud Copilot per_interaction 20 \n", "16 Email AI (Auto-Respond) per_message NaN \n", "\n", " tokens_per_unit confidence \\\n", "0 0 🟢 confirmed \n", "1 0 🟢 confirmed \n", "2 0 🟢 confirmed \n", "3 1 🟢 confirmed \n", "4 40 🟢 confirmed \n", "5 60 🟢 confirmed \n", "6 0 🟢 confirmed \n", "7 0 🟢 confirmed \n", "8 30 🟢 confirmed \n", "9 45 🟢 confirmed \n", "10 0 🟢 confirmed \n", "11 0 🟢 confirmed \n", "12 0 🟢 confirmed \n", "13 0 🟢 confirmed \n", "14 0 🟢 confirmed \n", "15 0 🟢 confirmed \n", "16 0 🔴 unknown \n", "\n", " notes \\\n", "0 IVR self-service voice bot minutes; 17 min per... \n", "1 Digital (non-voice) bot sessions; 51 sessions ... \n", "2 Legacy (non-agentic) virtual agent; 0.5 tokens... \n", "3 Agentic VA; 1.2 tokens per interaction. \n", "4 40 tokens per named user per month. Includes i... \n", "5 60 tokens per concurrent user per month. Inclu... \n", "6 AI-scored quality evaluations; 20 evaluations ... \n", "7 Supervisor standalone summarization; 50 summar... \n", "8 STA named licence; 30 tokens per named user pe... \n", "9 STA concurrent licence; 45 tokens per concurre... \n", "10 Predictive routing; 17 routes per token. \n", "11 Apple Messages for Business, Facebook Messenge... \n", "12 Genesys Cloud Social; 400 social post ingestio... \n", "13 Social Post Responses; 400 outbound messages p... \n", "14 AI translation; 2 translations per token. \n", "15 20 AI actions per token; Genesys Cloud knowled... \n", "16 Feature not yet available; rate TBD. \n", "\n", " source \n", "0 https://help.genesys.cloud/articles/genesys-cl... \n", "1 https://help.genesys.cloud/articles/genesys-cl... \n", "2 https://help.genesys.cloud/articles/genesys-cl... \n", "3 https://help.genesys.cloud/articles/genesys-cl... \n", "4 https://help.genesys.cloud/articles/genesys-cl... \n", "5 https://help.genesys.cloud/articles/genesys-cl... \n", "6 https://help.genesys.cloud/articles/genesys-cl... \n", "7 https://help.genesys.cloud/articles/genesys-cl... \n", "8 https://help.genesys.cloud/articles/genesys-cl... \n", "9 https://help.genesys.cloud/articles/genesys-cl... \n", "10 https://help.genesys.cloud/articles/genesys-cl... \n", "11 https://help.genesys.cloud/articles/genesys-cl... \n", "12 https://help.genesys.cloud/articles/genesys-cl... \n", "13 https://help.genesys.cloud/articles/genesys-cl... \n", "14 https://help.genesys.cloud/articles/genesys-cl... \n", "15 https://help.genesys.cloud/articles/genesys-cl... \n", "16 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display(meters_dataframe(meters))" ] }, { "cell_type": "markdown", "id": "6c308d2f", "metadata": {}, "source": [ "## Controls\n", "\n", "Plain variables (always work). Run the optional widget cell below for sliders —\n", "either way, re-run the calculation cells after changing anything." ] }, { "cell_type": "code", "execution_count": 4, "id": "8b24676f", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:58.248518Z", "iopub.status.busy": "2026-07-13T19:32:58.248332Z", "iopub.status.idle": "2026-07-13T19:32:58.252173Z", "shell.execute_reply": "2026-07-13T19:32:58.251375Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scenario: realistic · Year 1 · benefit params: realistic\n" ] } ], "source": [ "SCENARIO = \"realistic\" # \"floor\" | \"realistic\" | \"stretch\"\n", "YEAR = 1 # 1 | 2 | 3\n", "BENEFIT_PARAMS_MODE = \"realistic\" # \"realistic\" (pressure-tested) | \"claim\" (Genesys)\n", "USE_CONTRACTED_RATES = False\n", "IMPLEMENTATION_COST = 0.0 # one-off, amortized over 3 years\n", "\n", "scenario = get_scenario(SCENARIO)\n", "print(f\"Scenario: {SCENARIO} · Year {YEAR} · benefit params: {BENEFIT_PARAMS_MODE}\")" ] }, { "cell_type": "code", "execution_count": 5, "id": "810e9dae", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:58.253831Z", "iopub.status.busy": "2026-07-13T19:32:58.253676Z", "iopub.status.idle": "2026-07-13T19:32:58.302237Z", "shell.execute_reply": "2026-07-13T19:32:58.301248Z" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "69f65b8fab04496fa3f3b45116f421e5", "version_major": 2, "version_minor": 0 }, "text/plain": [ "ToggleButtons(description='Scenario', index=1, options=('floor', 'realistic', 'stretch'), value='realistic')" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "2b35efbfa83f4dfb994080acef7b28cc", "version_major": 2, "version_minor": 0 }, "text/plain": [ "ToggleButtons(description='Year', options=(1, 2, 3), value=1)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Optional: ipywidgets controls (skip if ipywidgets unavailable)\n", "try:\n", " import ipywidgets as W\n", " from IPython.display import display as _disp\n", "\n", " _scen = W.ToggleButtons(options=[\"floor\", \"realistic\", \"stretch\"],\n", " value=SCENARIO, description=\"Scenario\")\n", " _year = W.ToggleButtons(options=[1, 2, 3], value=YEAR, description=\"Year\")\n", "\n", " def _on_change(change):\n", " global SCENARIO, YEAR, scenario\n", " SCENARIO, YEAR = _scen.value, _year.value\n", " scenario = get_scenario(SCENARIO)\n", " print(f\"→ {SCENARIO}, year {YEAR} — re-run the cells below.\")\n", "\n", " _scen.observe(_on_change, \"value\"); _year.observe(_on_change, \"value\")\n", " _disp(_scen, _year)\n", "except ImportError:\n", " print(\"ipywidgets not installed — use the plain variables above.\")" ] }, { "cell_type": "markdown", "id": "5a590988", "metadata": {}, "source": [ "## Virtual Agents — deflection, costs & benefits\n", "\n", "**Both** voice volume cost drivers (token consumption) **and** benefit drivers\n", "(agent labour avoided). Two mechanisms operate on the same call pool:\n", "\n", "| Layer | What it does | Cost meter | Benefit |\n", "|---|---|---|---|\n", "| **Voice Bot** | IVR self-service on the full call pool | per-minute (17 min/token) | labour avoided × completion |\n", "| **Agentic Virtual Agent** | Handles a share of the **residual** (calls the bot did not deflect) | per-interaction (1.2 tok/interaction) | labour avoided × completion |\n", "\n", "### Layered (sequential) deflection model\n", "\n", "The two mechanisms are **substitutes**, not independent additive benefits:\n", "\n", "$$\n", "\\text{effective deflection} = r_{bot} + (1 - r_{bot}) \\cdot r_{va}\n", "$$\n", "\n", "Realistic scenario: 35% + 65% × 15% = **44.75%** (not the naive 50%).\n", "\n", "### Three realization haircuts on labour avoided\n", "\n", "Deflected volume does NOT translate 1:1 into labour savings:\n", "\n", "1. **Completion rate** — share of \"deflected\" calls the bot/VA fully handles\n", " without escalating mid-session (60-75% voice bot, 50-70% agentic VA Y1).\n", "2. **Labour realization** — staffing flexibility ceiling (minimums, shrinkage,\n", " occupancy); 70-85% of deflected volume actually reduces FTE need.\n", "3. **Callback discount** — poorly-handled deflections drive 5-10% repeat contacts.\n", "\n", "Combined realistic factor: 0.70 × 0.80 × (1 − 0.05) ≈ **0.53**\n", "\n", "So a naive \"$25M of labour avoided\" is realistically ~$13M. The variables below\n", "override the scenario defaults — adjust them to test sensitivity, then re-run\n", "the Cost & Benefit cells.\n" ] }, { "cell_type": "code", "execution_count": 6, "id": "65773422", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:58.304432Z", "iopub.status.busy": "2026-07-13T19:32:58.304177Z", "iopub.status.idle": "2026-07-13T19:32:58.312707Z", "shell.execute_reply": "2026-07-13T19:32:58.311008Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Voice Bot: 35% of full pool · Agentic VA: 15% of residual\n", "Effective deflection: 44.75% · Realization factor: 53.2% · Net labour avoidance: 23.8%\n" ] } ], "source": [ "# ── Virtual Agent inputs (override scenario defaults below) ──────────\n", "# Cost & benefit drivers — applied as deflection_target overrides on the\n", "# Voice Bot and Agentic VA feature scopes; realization haircuts mutate\n", "# the scenario object so calculate_va_deflection_benefit picks them up.\n", "\n", "# Voice Bot — % of FULL voice volume deflected to the bot\n", "VA_BOT_DEFLECTION = scenario.voice_bot_deflection # cost & benefit\n", "VA_BOT_AVG_MINUTES = scenario.voice_bot_avg_minutes # cost only\n", "\n", "# Agentic VA — % of RESIDUAL (1 − bot) deflected to the agentic VA\n", "VA_AGENTIC_DEFLECTION = scenario.agentic_va_deflection # cost & benefit\n", "\n", "# Realization haircuts (benefit-side only — never reduce token consumption)\n", "VA_COMPLETION_RATE = scenario.va_completion_rate # bot/VA fully handles call\n", "VA_LABOUR_REALIZATION = scenario.va_labour_realization # staffing flexibility\n", "VA_CALLBACK_DISCOUNT = scenario.va_callback_discount # 5-10% repeat contacts\n", "\n", "\n", "def _apply_va_inputs():\n", " \"\"\"Push notebook variables into the scenario + scopes used downstream.\"\"\"\n", " global scopes\n", " # Mutate scenario (regular dataclass, not frozen) — picked up by\n", " # calculate_va_deflection_benefit via _param() and direct attribute reads.\n", " scenario.voice_bot_deflection = VA_BOT_DEFLECTION\n", " scenario.voice_bot_avg_minutes = VA_BOT_AVG_MINUTES\n", " scenario.agentic_va_deflection = VA_AGENTIC_DEFLECTION\n", " scenario.va_completion_rate = VA_COMPLETION_RATE\n", " scenario.va_labour_realization = VA_LABOUR_REALIZATION\n", " scenario.va_callback_discount = VA_CALLBACK_DISCOUNT\n", " # ALSO patch BENEFIT_PARAMS so the realistic path uses our overrides\n", " # (calculate_va_deflection_benefit reads via _param()).\n", " BENEFIT_PARAMS[\"va_completion_rate\"][\"realistic\"] = VA_COMPLETION_RATE\n", " BENEFIT_PARAMS[\"va_labour_realization\"][\"realistic\"] = VA_LABOUR_REALIZATION\n", " BENEFIT_PARAMS[\"va_callback_discount\"][\"realistic\"] = VA_CALLBACK_DISCOUNT\n", " # Override deflection_target on the Voice Bot / Agentic VA scopes\n", " scopes = [\n", " dataclasses.replace(\n", " s,\n", " deflection_target=(\n", " VA_BOT_DEFLECTION if s.feature == \"Voice Bot\"\n", " else VA_AGENTIC_DEFLECTION if s.feature == \"Agentic Virtual Agent\"\n", " else s.deflection_target\n", " ),\n", " )\n", " for s in scopes\n", " ]\n", "\n", "\n", "_apply_va_inputs()\n", "\n", "bot_pct = VA_BOT_DEFLECTION * 100\n", "va_pct = VA_AGENTIC_DEFLECTION * 100\n", "combined = VA_BOT_DEFLECTION + (1 - VA_BOT_DEFLECTION) * VA_AGENTIC_DEFLECTION\n", "real_factor = (\n", " VA_COMPLETION_RATE * VA_LABOUR_REALIZATION * (1 - VA_CALLBACK_DISCOUNT)\n", ")\n", "print(\n", " f\"Voice Bot: {bot_pct:.0f}% of full pool · \"\n", " f\"Agentic VA: {va_pct:.0f}% of residual\\n\"\n", " f\"Effective deflection: {combined*100:.2f}% · \"\n", " f\"Realization factor: {real_factor*100:.1f}% · \"\n", " f\"Net labour avoidance: {combined*real_factor*100:.1f}%\"\n", ")\n" ] }, { "cell_type": "code", "execution_count": 7, "id": "872af216", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:58.315429Z", "iopub.status.busy": "2026-07-13T19:32:58.315136Z", "iopub.status.idle": "2026-07-13T19:32:58.329667Z", "shell.execute_reply": "2026-07-13T19:32:58.328977Z" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "cf854dec89944ceca7119f9f177abfd5", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(HBox(children=(FloatSlider(value=0.35, description='Bot %', max=0.7, readout_format='.0%', step…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Optional: ipywidgets sliders for VA inputs (skip if ipywidgets unavailable)\n", "try:\n", " import ipywidgets as W\n", " from IPython.display import display as _disp\n", "\n", " _w_bot = W.FloatSlider(value=VA_BOT_DEFLECTION, min=0, max=0.7,\n", " step=0.01, description=\"Bot %\",\n", " readout_format=\".0%\")\n", " _w_botm = W.FloatSlider(value=VA_BOT_AVG_MINUTES, min=0.5, max=5.0,\n", " step=0.1, description=\"Bot min\")\n", " _w_va = W.FloatSlider(value=VA_AGENTIC_DEFLECTION, min=0, max=0.5,\n", " step=0.01, description=\"VA %\",\n", " readout_format=\".0%\")\n", " _w_cmp = W.FloatSlider(value=VA_COMPLETION_RATE, min=0.3, max=1.0,\n", " step=0.01, description=\"Completion\",\n", " readout_format=\".0%\")\n", " _w_lab = W.FloatSlider(value=VA_LABOUR_REALIZATION, min=0.3, max=1.0,\n", " step=0.01, description=\"Labour real.\",\n", " readout_format=\".0%\")\n", " _w_cb = W.FloatSlider(value=VA_CALLBACK_DISCOUNT, min=0.0, max=0.30,\n", " step=0.01, description=\"Callback\",\n", " readout_format=\".0%\")\n", "\n", " def _on_va_change(change):\n", " global VA_BOT_DEFLECTION, VA_BOT_AVG_MINUTES, VA_AGENTIC_DEFLECTION\n", " global VA_COMPLETION_RATE, VA_LABOUR_REALIZATION, VA_CALLBACK_DISCOUNT\n", " VA_BOT_DEFLECTION = _w_bot.value\n", " VA_BOT_AVG_MINUTES = _w_botm.value\n", " VA_AGENTIC_DEFLECTION = _w_va.value\n", " VA_COMPLETION_RATE = _w_cmp.value\n", " VA_LABOUR_REALIZATION = _w_lab.value\n", " VA_CALLBACK_DISCOUNT = _w_cb.value\n", " _apply_va_inputs()\n", " eff = VA_BOT_DEFLECTION + (1-VA_BOT_DEFLECTION)*VA_AGENTIC_DEFLECTION\n", " rf = VA_COMPLETION_RATE * VA_LABOUR_REALIZATION * (1-VA_CALLBACK_DISCOUNT)\n", " print(f\"→ effective {eff*100:.2f}% · realization {rf*100:.1f}% \"\n", " f\"· net {eff*rf*100:.1f}% — re-run cells below.\")\n", "\n", " for w in (_w_bot, _w_botm, _w_va, _w_cmp, _w_lab, _w_cb):\n", " w.observe(_on_va_change, \"value\")\n", " _disp(W.VBox([\n", " W.HBox([_w_bot, _w_botm, _w_va]),\n", " W.HBox([_w_cmp, _w_lab, _w_cb]),\n", " ]))\n", "except ImportError:\n", " print(\"ipywidgets not installed — adjust the variables above.\")\n" ] }, { "cell_type": "code", "execution_count": 8, "id": "07ed3a9e", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:58.334260Z", "iopub.status.busy": "2026-07-13T19:32:58.334037Z", "iopub.status.idle": "2026-07-13T19:32:59.377489Z", "shell.execute_reply": "2026-07-13T19:32:59.376614Z" } }, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "decreasing": { "marker": { "color": "#C62828" } }, "increasing": { "marker": { "color": "#2E7D32" } }, "measure": [ "absolute", "relative", "relative", "relative", "total" ], "name": "Call flow", "orientation": "v", "text": [ "100%", "−35%", "−15% of residual", "", "55.2%" ], "textposition": "outside", "totals": { "marker": { "color": "#1565C0" } }, "type": "waterfall", "x": [ "Total calls
(14,572,296)", "Voice Bot
(−5,100,304)", "Agentic VA
(−1,420,799)", "To agent
(8,051,194)", "Net to agent" ], "y": [ 14572296, -5100303.6, -1420798.86, 0, 0 ] } ], "layout": { "height": 420, "margin": { "b": 40, "l": 20, "r": 20, "t": 60 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermap": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermap" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "NAM deflection cascade · realistic scenario · 44.8% effective deflection" }, "yaxis": { "title": { "text": "Annual calls" } } } } }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
layer% of totalannual callslabour avoided (raw)labour avoided (realized)
0Voice Bot deflection35.0%5,100,30413,282,0417,066,046
1Agentic VA deflection (residual)9.8%1,420,7993,699,9971,968,398
2Combined (effective)44.75%6,521,10216,982,0389,034,444
\n", "
" ], "text/plain": [ " layer % of total annual calls \\\n", "0 Voice Bot deflection 35.0% 5,100,304 \n", "1 Agentic VA deflection (residual) 9.8% 1,420,799 \n", "2 Combined (effective) 44.75% 6,521,102 \n", "\n", " labour avoided (raw) labour avoided (realized) \n", "0 13,282,041 7,066,046 \n", "1 3,699,997 1,968,398 \n", "2 16,982,038 9,034,444 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "NAM realization haircut: $16,982,038 raw → $9,034,444 realized (×0.532 = 70% completion × 80% labour × 95% retained)\n" ] } ], "source": [ "# Visualize the deflection cascade for the largest site (NAM) at the\n", "# current scenario × year. Shows where calls go and how realization\n", "# haircuts shrink raw deflection into actual labour savings.\n", "\n", "_site = next(s for s in sites if s.site_name == \"NAM\")\n", "_annual_calls = _site.voice_volume_monthly * 12\n", "_aht_seconds = _site.voice_aht_seconds\n", "_labour_rate = _site.agent_cost_per_second\n", "\n", "bot_calls = _annual_calls * VA_BOT_DEFLECTION\n", "residual_calls = _annual_calls * (1 - VA_BOT_DEFLECTION)\n", "va_calls = residual_calls * VA_AGENTIC_DEFLECTION\n", "to_agent_calls = residual_calls - va_calls\n", "deflected_total = bot_calls + va_calls\n", "\n", "# Raw labour avoided (no haircuts)\n", "raw_labour_avoided = deflected_total * _aht_seconds * _labour_rate\n", "# After realization haircuts\n", "real_labour_avoided = raw_labour_avoided * real_factor\n", "\n", "# Waterfall: starting at 100% of calls, show where they go\n", "fig = go.Figure(go.Waterfall(\n", " name=\"Call flow\",\n", " orientation=\"v\",\n", " measure=[\"absolute\", \"relative\", \"relative\", \"relative\", \"total\"],\n", " x=[\n", " f\"Total calls
({_annual_calls:,.0f})\",\n", " f\"Voice Bot
(−{bot_calls:,.0f})\",\n", " f\"Agentic VA
(−{va_calls:,.0f})\",\n", " f\"To agent
({to_agent_calls:,.0f})\",\n", " \"Net to agent\",\n", " ],\n", " y=[_annual_calls, -bot_calls, -va_calls, 0, 0],\n", " text=[\n", " f\"100%\",\n", " f\"−{VA_BOT_DEFLECTION*100:.0f}%\",\n", " f\"−{VA_AGENTIC_DEFLECTION*100:.0f}% of residual\",\n", " \"\",\n", " f\"{(to_agent_calls/_annual_calls)*100:.1f}%\",\n", " ],\n", " textposition=\"outside\",\n", " increasing={\"marker\": {\"color\": \"#2E7D32\"}},\n", " decreasing={\"marker\": {\"color\": \"#C62828\"}},\n", " totals={\"marker\": {\"color\": \"#1565C0\"}},\n", "))\n", "fig.update_layout(\n", " title=f\"NAM deflection cascade · {SCENARIO} scenario · \"\n", " f\"{deflected_total/_annual_calls*100:.1f}% effective deflection\",\n", " yaxis_title=\"Annual calls\",\n", " height=420,\n", " margin=dict(l=20, r=20, t=60, b=40),\n", ")\n", "fig.show()\n", "\n", "# Summary table\n", "summary = pd.DataFrame([\n", " {\"layer\": \"Voice Bot deflection\",\n", " \"% of total\": f\"{VA_BOT_DEFLECTION*100:.1f}%\",\n", " \"annual calls\": bot_calls,\n", " \"labour avoided (raw)\": bot_calls * _aht_seconds * _labour_rate,\n", " \"labour avoided (realized)\": bot_calls * _aht_seconds * _labour_rate * real_factor},\n", " {\"layer\": \"Agentic VA deflection (residual)\",\n", " \"% of total\": f\"{(va_calls/_annual_calls)*100:.1f}%\",\n", " \"annual calls\": va_calls,\n", " \"labour avoided (raw)\": va_calls * _aht_seconds * _labour_rate,\n", " \"labour avoided (realized)\": va_calls * _aht_seconds * _labour_rate * real_factor},\n", " {\"layer\": \"Combined (effective)\",\n", " \"% of total\": f\"{(deflected_total/_annual_calls)*100:.2f}%\",\n", " \"annual calls\": deflected_total,\n", " \"labour avoided (raw)\": raw_labour_avoided,\n", " \"labour avoided (realized)\": real_labour_avoided},\n", "])\n", "display(summary)\n", "print(f\"NAM realization haircut: ${raw_labour_avoided:,.0f} raw → \"\n", " f\"${real_labour_avoided:,.0f} realized \"\n", " f\"(×{real_factor:.3f} = {VA_COMPLETION_RATE:.0%} completion × \"\n", " f\"{VA_LABOUR_REALIZATION:.0%} labour × {1-VA_CALLBACK_DISCOUNT:.0%} retained)\")\n" ] }, { "cell_type": "code", "execution_count": 9, "id": "e7fc3a73", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:59.380017Z", "iopub.status.busy": "2026-07-13T19:32:59.379684Z", "iopub.status.idle": "2026-07-13T19:32:59.407404Z", "shell.execute_reply": "2026-07-13T19:32:59.406552Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
inputvaluedrives
0Voice Bot deflection (full pool)35%Voice Bot tokens (cost) + bot deflection benefit
1Voice Bot avg minutes1.5 minVoice Bot tokens (cost only)
2Agentic VA deflection (residual)15%Agentic VA tokens (cost) + VA deflection benefit
3Effective combined deflection44.75%Total share of voice calls deflected
4Realization factor53.2%Haircut on labour avoided (70% × 80% × 95%)
\n", "
" ], "text/plain": [ " input value \\\n", "0 Voice Bot deflection (full pool) 35% \n", "1 Voice Bot avg minutes 1.5 min \n", "2 Agentic VA deflection (residual) 15% \n", "3 Effective combined deflection 44.75% \n", "4 Realization factor 53.2% \n", "\n", " drives \n", "0 Voice Bot tokens (cost) + bot deflection benefit \n", "1 Voice Bot tokens (cost only) \n", "2 Agentic VA tokens (cost) + VA deflection benefit \n", "3 Total share of voice calls deflected \n", "4 Haircut on labour avoided (70% × 80% × 95%) " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
modelY2 benefitvs correctednote
0Original (broken) — additive on full base, no ...29,993,898Counts bot + VA on the same call pool, 100% la...
1Corrected — layered + 'claim' params (no hairc...24,900,726-17.0%Layered model alone removes double-count
2Corrected — layered + realistic haircuts (curr...13,247,186-55.8%Production-calibrated; this is what flows into...
\n", "
" ], "text/plain": [ " model Y2 benefit vs corrected \\\n", "0 Original (broken) — additive on full base, no ... 29,993,898 \n", "1 Corrected — layered + 'claim' params (no hairc... 24,900,726 -17.0% \n", "2 Corrected — layered + realistic haircuts (curr... 13,247,186 -55.8% \n", "\n", " note \n", "0 Counts bot + VA on the same call pool, 100% la... \n", "1 Layered model alone removes double-count \n", "2 Production-calibrated; this is what flows into... " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Reconciliation: how the inputs above flow into both the Cost Model and\n", "# Benefit Model. Compare the corrected (layered + haircut) figures\n", "# against the original Genesys ROI-doc 'claim' assumption to make the\n", "# correction visible.\n", "\n", "from tokencalc.benefit_model import calculate_va_deflection_benefit\n", "\n", "# Use a year where both Voice Bot AND Agentic VA are active. In the\n", "# default rollout that's year 2 onward (Agentic VA phase=2).\n", "_RECON_YEAR = max(YEAR, 2)\n", "\n", "_bot_scope = next(s for s in scopes if s.feature == \"Voice Bot\")\n", "_va_scope = next((s for s in scopes if s.feature == \"Agentic Virtual Agent\"), None)\n", "\n", "_bot_realistic = calculate_va_deflection_benefit(\n", " sites, _bot_scope, scenario, _RECON_YEAR, params=\"realistic\"\n", ")[\"annual_value\"].sum()\n", "_bot_claim = calculate_va_deflection_benefit(\n", " sites, _bot_scope, scenario, _RECON_YEAR, params=\"claim\"\n", ")[\"annual_value\"].sum()\n", "\n", "if _va_scope is not None:\n", " _va_realistic = calculate_va_deflection_benefit(\n", " sites, _va_scope, scenario, _RECON_YEAR, params=\"realistic\"\n", " )[\"annual_value\"].sum()\n", " _va_claim = calculate_va_deflection_benefit(\n", " sites, _va_scope, scenario, _RECON_YEAR, params=\"claim\"\n", " )[\"annual_value\"].sum()\n", "else:\n", " _va_realistic = _va_claim = 0.0\n", "\n", "# What the (broken) additive model would have produced — naive sum on full base\n", "_total_calls_yr = sum(s.voice_volume_monthly * 12 for s in sites)\n", "_avg_labour = sum(\n", " (s.voice_volume_monthly * 12) * s.voice_aht_seconds * s.agent_cost_per_second\n", " for s in sites\n", ") / max(_total_calls_yr, 1)\n", "_naive_additive_claim = (\n", " _total_calls_yr * (VA_BOT_DEFLECTION + VA_AGENTIC_DEFLECTION) * _avg_labour\n", " * scenario.realization(_RECON_YEAR)\n", ") # original error: rates added on full base, no haircuts\n", "\n", "_recon = pd.DataFrame([\n", " {\"input\": \"Voice Bot deflection (full pool)\",\n", " \"value\": f\"{VA_BOT_DEFLECTION:.0%}\",\n", " \"drives\": \"Voice Bot tokens (cost) + bot deflection benefit\"},\n", " {\"input\": \"Voice Bot avg minutes\",\n", " \"value\": f\"{VA_BOT_AVG_MINUTES:.1f} min\",\n", " \"drives\": \"Voice Bot tokens (cost only)\"},\n", " {\"input\": \"Agentic VA deflection (residual)\",\n", " \"value\": f\"{VA_AGENTIC_DEFLECTION:.0%}\",\n", " \"drives\": \"Agentic VA tokens (cost) + VA deflection benefit\"},\n", " {\"input\": \"Effective combined deflection\",\n", " \"value\": f\"{(VA_BOT_DEFLECTION + (1-VA_BOT_DEFLECTION)*VA_AGENTIC_DEFLECTION):.2%}\",\n", " \"drives\": \"Total share of voice calls deflected\"},\n", " {\"input\": \"Realization factor\",\n", " \"value\": f\"{real_factor:.1%}\",\n", " \"drives\": \"Haircut on labour avoided \"\n", " f\"({VA_COMPLETION_RATE:.0%} × {VA_LABOUR_REALIZATION:.0%} × \"\n", " f\"{1-VA_CALLBACK_DISCOUNT:.0%})\"},\n", "])\n", "display(_recon)\n", "\n", "_compare = pd.DataFrame([\n", " {\"model\": \"Original (broken) — additive on full base, no haircuts\",\n", " f\"Y{_RECON_YEAR} benefit\": _naive_additive_claim,\n", " \"vs corrected\": \"\",\n", " \"note\": \"Counts bot + VA on the same call pool, 100% labour avoidance\"},\n", " {\"model\": \"Corrected — layered + 'claim' params (no haircuts)\",\n", " f\"Y{_RECON_YEAR} benefit\": _bot_claim + _va_claim,\n", " \"vs corrected\": f\"{((_bot_claim+_va_claim)/_naive_additive_claim - 1)*100:+.1f}%\",\n", " \"note\": \"Layered model alone removes double-count\"},\n", " {\"model\": \"Corrected — layered + realistic haircuts (current)\",\n", " f\"Y{_RECON_YEAR} benefit\": _bot_realistic + _va_realistic,\n", " \"vs corrected\": f\"{((_bot_realistic+_va_realistic)/_naive_additive_claim - 1)*100:+.1f}%\",\n", " \"note\": \"Production-calibrated; this is what flows into the business case\"},\n", "])\n", "display(_compare)\n" ] }, { "cell_type": "markdown", "id": "3079316e", "metadata": {}, "source": [ "## Cost model" ] }, { "cell_type": "code", "execution_count": 10, "id": "3ac4fee1", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:59.410682Z", "iopub.status.busy": "2026-07-13T19:32:59.410375Z", "iopub.status.idle": "2026-07-13T19:32:59.435201Z", "shell.execute_reply": "2026-07-13T19:32:59.432035Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
cost_linescopeannual_costconfidence
0Genesys CX 3 platform licencesall sites2,788,232confirmed
4Agent Copilot [named]NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...1,002,240confirmed
3Speech & Text Analytics [named]NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...751,680confirmed
1Voice BotNAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...680,592confirmed
6Direct MessagingNAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...132confirmed
2Agentic Virtual Agent0confirmed
5AI Summary & Insights0confirmed
7AI Translate0confirmed
\n", "
" ], "text/plain": [ " cost_line \\\n", "0 Genesys CX 3 platform licences \n", "4 Agent Copilot [named] \n", "3 Speech & Text Analytics [named] \n", "1 Voice Bot \n", "6 Direct Messaging \n", "2 Agentic Virtual Agent \n", "5 AI Summary & Insights \n", "7 AI Translate \n", "\n", " scope annual_cost confidence \n", "0 all sites 2,788,232 confirmed \n", "4 NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA... 1,002,240 confirmed \n", "3 NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA... 751,680 confirmed \n", "1 NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA... 680,592 confirmed \n", "6 NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA... 132 confirmed \n", "2 — 0 confirmed \n", "5 — 0 confirmed \n", "7 — 0 confirmed " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Year 1 total: $5,222,876 (of which 🔴 unknown-rate features: $0)\n" ] } ], "source": [ "cost_df = calculate_total_cost(sites, scopes, meters, pricing, scenario, YEAR,\n", " use_contracted=USE_CONTRACTED_RATES)\n", "display(cost_df.sort_values(\"annual_cost\", ascending=False))\n", "unknown_cost = cost_df[cost_df.confidence == \"unknown\"][\"annual_cost\"].sum()\n", "print(f\"Year {YEAR} total: ${cost_df['annual_cost'].sum():,.0f}\"\n", " f\" (of which 🔴 unknown-rate features: ${unknown_cost:,.0f})\")" ] }, { "cell_type": "code", "execution_count": 11, "id": "fa4c9cdc", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:59.440342Z", "iopub.status.busy": "2026-07-13T19:32:59.440009Z", "iopub.status.idle": "2026-07-13T19:32:59.903308Z", "shell.execute_reply": "2026-07-13T19:32:59.902627Z" } }, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "hovertemplate": "cost_line=Genesys CX 3 platform licences
year=%{x}
$/yr=%{y}", "legendgroup": "Genesys CX 3 platform licences", "marker": { "color": "#636efa", "pattern": { "shape": "" } }, "name": "Genesys CX 3 platform licences", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "cT0K18NFRUFxPQrXw0VFQXE9CtfDRUVB", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "cost_line=Voice Bot
year=%{x}
$/yr=%{y}", "legendgroup": "Voice Bot", "marker": { "color": "#EF553B", "pattern": { "shape": "" } }, "name": "Voice Bot", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "AAAAACDFJEEAAAAAoKstQQAAAACgqy1B", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "cost_line=Agentic Virtual Agent
year=%{x}
$/yr=%{y}", "legendgroup": "Agentic Virtual Agent", "marker": { "color": "#00cc96", "pattern": { "shape": "" } }, "name": "Agentic Virtual Agent", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "AAAAAAAAAAAAAAAAaII4QQAAAAC4gUFB", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "cost_line=Speech & Text Analytics [named]
year=%{x}
$/yr=%{y}", "legendgroup": "Speech & Text Analytics [named]", "marker": { "color": "#ab63fa", "pattern": { "shape": "" } }, "name": "Speech & Text Analytics [named]", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "AAAAAIDwJkEAAAAAgPAmQQAAAACA8CZB", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "cost_line=Agent Copilot [named]
year=%{x}
$/yr=%{y}", "legendgroup": "Agent Copilot [named]", "marker": { "color": "#FFA15A", "pattern": { "shape": "" } }, "name": "Agent Copilot [named]", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "AAAAAACWLkEAAAAAAJYuQQAAAAAAli5B", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "cost_line=AI Summary & Insights
year=%{x}
$/yr=%{y}", "legendgroup": "AI Summary & Insights", "marker": { "color": "#19d3f3", "pattern": { "shape": "" } }, "name": "AI Summary & Insights", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "cost_line=Direct Messaging
year=%{x}
$/yr=%{y}", "legendgroup": "Direct Messaging", "marker": { "color": "#FF6692", "pattern": { "shape": "" } }, "name": "Direct Messaging", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "AAAAAACAYEAAAAAAAABiQAAAAAAAAGJA", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "cost_line=AI Translate
year=%{x}
$/yr=%{y}", "legendgroup": "AI Translate", "marker": { "color": "#B6E880", "pattern": { "shape": "" } }, "name": "AI Translate", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "AAAAAAAAAAAAAAAAAAAAAAAAAAAU6lBB", "dtype": "f8" }, "yaxis": "y" } ], "layout": { "barmode": "relative", "legend": { "title": { "text": "cost_line" }, "tracegroupgap": 0 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermap": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermap" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "Cost breakdown by feature — realistic" }, "xaxis": { "anchor": "y", "domain": [ 0.0, 1.0 ], "title": { "text": "year" } }, "yaxis": { "anchor": "x", "domain": [ 0.0, 1.0 ], "title": { "text": "$/yr" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Stacked bar — cost by feature, one bar per year\n", "frames = []\n", "for y in (1, 2, 3):\n", " d = calculate_total_cost(sites, scopes, meters, pricing, scenario, y,\n", " use_contracted=USE_CONTRACTED_RATES)\n", " d[\"year\"] = f\"Y{y}\"\n", " frames.append(d)\n", "cost_3y = pd.concat(frames, ignore_index=True)\n", "px.bar(cost_3y, x=\"year\", y=\"annual_cost\", color=\"cost_line\",\n", " title=f\"Cost breakdown by feature — {SCENARIO}\",\n", " labels={\"annual_cost\": \"$/yr\"})" ] }, { "cell_type": "markdown", "id": "326602c1", "metadata": {}, "source": [ "## Benefit model" ] }, { "cell_type": "code", "execution_count": 12, "id": "380914e0", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:59.906155Z", "iopub.status.busy": "2026-07-13T19:32:59.905981Z", "iopub.status.idle": "2026-07-13T19:32:59.928045Z", "shell.execute_reply": "2026-07-13T19:32:59.926937Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
benefit_linescopeannual_valueconfidence
0Voice Bot deflection (labour avoided)APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...6,981,080estimated
3Voice ACW (summarization)APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...2,099,573estimated
2Voice AHT (knowledge surfacing)APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...1,237,248estimated
1STA coaching (AHT)APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...562,386estimated
4Supervisor time (AI summaries/insights)APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...318,500estimated
\n", "
" ], "text/plain": [ " benefit_line \\\n", "0 Voice Bot deflection (labour avoided) \n", "3 Voice ACW (summarization) \n", "2 Voice AHT (knowledge surfacing) \n", "1 STA coaching (AHT) \n", "4 Supervisor time (AI summaries/insights) \n", "\n", " scope annual_value confidence \n", "0 APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A... 6,981,080 estimated \n", "3 APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A... 2,099,573 estimated \n", "2 APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A... 1,237,248 estimated \n", "1 APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A... 562,386 estimated \n", "4 APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A... 318,500 estimated " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Year 1 total benefit: $11,198,787\n" ] } ], "source": [ "benefit_df = calculate_total_benefit(sites, scopes, scenario, YEAR,\n", " params=BENEFIT_PARAMS_MODE)\n", "display(benefit_df.sort_values(\"annual_value\", ascending=False))\n", "print(f\"Year {YEAR} total benefit: ${benefit_df['annual_value'].sum():,.0f}\")" ] }, { "cell_type": "code", "execution_count": 13, "id": "ae5fb48b", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:32:59.930242Z", "iopub.status.busy": "2026-07-13T19:32:59.930066Z", "iopub.status.idle": "2026-07-13T19:33:00.022614Z", "shell.execute_reply": "2026-07-13T19:33:00.022032Z" } }, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "hovertemplate": "benefit_line=Voice Bot deflection (labour avoided)
year=%{x}
$/yr=%{y}", "legendgroup": "Voice Bot deflection (labour avoided)", "marker": { "color": "#636efa", "pattern": { "shape": "" } }, "name": "Voice Bot deflection (labour avoided)", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "DvzA8XWhWkE/Y5r0901lQdtVd3KWTGlB", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "benefit_line=STA coaching (AHT)
year=%{x}
$/yr=%{y}", "legendgroup": "STA coaching (AHT)", "marker": { "color": "#EF553B", "pattern": { "shape": "" } }, "name": "STA coaching (AHT)", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "ndiJLaMpIUFjJ3bi0XUrQWIndp70TTBB", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "benefit_line=Voice AHT (knowledge surfacing)
year=%{x}
$/yr=%{y}", "legendgroup": "Voice AHT (knowledge surfacing)", "marker": { "color": "#00cc96", "pattern": { "shape": "" } }, "name": "Voice AHT (knowledge surfacing)", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "FDuxSwDhMkGGXuhFzTQ+QR/4geFZ70FB", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "benefit_line=Voice ACW (summarization)
year=%{x}
$/yr=%{y}", "legendgroup": "Voice ACW (summarization)", "marker": { "color": "#ab63fa", "pattern": { "shape": "" } }, "name": "Voice ACW (summarization)", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "T+zEbroEQEFLrdRKKqFJQcmN3Dhib05B", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "benefit_line=Supervisor time (AI summaries/insights)
year=%{x}
$/yr=%{y}", "legendgroup": "Supervisor time (AI summaries/insights)", "marker": { "color": "#FFA15A", "pattern": { "shape": "" } }, "name": "Supervisor time (AI summaries/insights)", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y1", "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "AAAAAJBwE0EAAAAAgBofQQAAAAC8dyJB", "dtype": "f8" }, "yaxis": "y" }, { "hovertemplate": "benefit_line=Agentic Virtual Agent deflection (labour avoided)
year=%{x}
$/yr=%{y}", "legendgroup": "Agentic Virtual Agent deflection (labour avoided)", "marker": { "color": "#19d3f3", "pattern": { "shape": "" } }, "name": "Agentic Virtual Agent deflection (labour avoided)", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "Y2", "Y3" ], "xaxis": "x", "y": { "bdata": "lkOLvBKzP0EgsPIfU9JCQQ==", "dtype": "f8" }, "yaxis": "y" } ], "layout": { "barmode": "relative", "legend": { "title": { "text": "benefit_line" }, "tracegroupgap": 0 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermap": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermap" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "Benefit breakdown by source — realistic" }, "xaxis": { "anchor": "y", "domain": [ 0.0, 1.0 ], "title": { "text": "year" } }, "yaxis": { "anchor": "x", "domain": [ 0.0, 1.0 ], "title": { "text": "$/yr" } } } } }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "name": "Genesys claim", "type": "bar", "x": [ "STA coaching (AHT)", "Supervisor time (AI summaries/insights)", "Voice ACW (summarization)", "Voice AHT (knowledge surfacing)", "Voice Bot deflection (labour avoided)" ], "y": { "bdata": "J3Zi5y7iNkEAAAAAkHAjQWIndgrpBVRB8AM/6AQiQEE7sRNNYwdpQQ==", "dtype": "f8" } }, { "name": "Pressure-tested realistic", "type": "bar", "x": [ "STA coaching (AHT)", "Supervisor time (AI summaries/insights)", "Voice ACW (summarization)", "Voice AHT (knowledge surfacing)", "Voice Bot deflection (labour avoided)" ], "y": { "bdata": "ndiJLaMpIUEAAAAAkHATQU/sxG66BEBBFDuxSwDhMkEO/MDxdaFaQQ==", "dtype": "f8" } } ], "layout": { "barmode": "group", "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermap": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermap" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "Claim vs pressure-tested — Year 1" }, "yaxis": { "tickformat": "$,.0f" } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Stacked bar by source per year + Genesys claim vs pressure-tested comparison\n", "frames = []\n", "for y in (1, 2, 3):\n", " d = calculate_total_benefit(sites, scopes, scenario, y, params=BENEFIT_PARAMS_MODE)\n", " d[\"year\"] = f\"Y{y}\"\n", " frames.append(d)\n", "ben_3y = pd.concat(frames, ignore_index=True)\n", "fig = px.bar(ben_3y, x=\"year\", y=\"annual_value\", color=\"benefit_line\",\n", " title=f\"Benefit breakdown by source — {SCENARIO}\",\n", " labels={\"annual_value\": \"$/yr\"})\n", "fig.show()\n", "\n", "claim = calculate_total_benefit(sites, scopes, scenario, YEAR, params=\"claim\")\n", "comp = pd.merge(\n", " claim[[\"benefit_line\", \"annual_value\"]].rename(columns={\"annual_value\": \"Genesys claim\"}),\n", " benefit_df[[\"benefit_line\", \"annual_value\"]].rename(columns={\"annual_value\": \"Pressure-tested\"}),\n", " on=\"benefit_line\", how=\"outer\",\n", ").fillna(0)\n", "go.Figure([\n", " go.Bar(name=\"Genesys claim\", x=comp.benefit_line, y=comp[\"Genesys claim\"]),\n", " go.Bar(name=\"Pressure-tested realistic\", x=comp.benefit_line, y=comp[\"Pressure-tested\"]),\n", "]).update_layout(barmode=\"group\", title=f\"Claim vs pressure-tested — Year {YEAR}\",\n", " yaxis_tickformat=\"$,.0f\")" ] }, { "cell_type": "markdown", "id": "33e2dc31", "metadata": {}, "source": [ "## Business case — 3-year P&L, NPV @ 8%, payback, ROI" ] }, { "cell_type": "code", "execution_count": 14, "id": "7bd6456e", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:33:00.025440Z", "iopub.status.busy": "2026-07-13T19:33:00.025068Z", "iopub.status.idle": "2026-07-13T19:33:00.089596Z", "shell.execute_reply": "2026-07-13T19:33:00.088897Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lineY1Y2Y33-yr Total
0Genesys CX 3 platform licences2,788,2322,788,2322,788,2328,364,695
1Voice Bot680,592972,240972,2402,625,072
2Agentic Virtual Agent01,606,2482,294,6403,900,888
3Speech & Text Analytics [named]751,680751,680751,6802,255,040
4Agent Copilot [named]1,002,2401,002,2401,002,2403,006,720
5AI Summary & Insights0000
6Direct Messaging132144144420
7AI Translate004,434,0004,434,000
8NICE IEX (NAM)650,0001,300,0001,300,0003,250,000
9Legacy CC platform0000
10Voice Bot deflection (labour avoided)6,981,08011,169,72813,264,05231,414,859
11STA coaching (AHT)562,386899,8171,068,5332,530,735
12Voice AHT (knowledge surfacing)1,237,2481,979,5972,350,7725,567,617
13Voice ACW (summarization)2,099,5733,359,3173,989,1889,448,078
14Supervisor time (AI summaries/insights)318,500509,600605,1501,433,250
15Agentic Virtual Agent deflection (labour avoided)02,077,4592,466,9824,544,441
16TOTAL COSTS5,222,8767,120,78412,243,17624,586,835
17TOTAL TAKEOUTS650,0001,300,0001,300,0003,250,000
18TOTAL BENEFITS11,198,78719,995,51723,744,67754,938,980
19NET6,625,91114,174,73412,801,50133,602,145
20Cumulative net6,625,91120,800,64433,602,14561,028,701
\n", "
" ], "text/plain": [ " line Y1 Y2 \\\n", "0 Genesys CX 3 platform licences 2,788,232 2,788,232 \n", "1 Voice Bot 680,592 972,240 \n", "2 Agentic Virtual Agent 0 1,606,248 \n", "3 Speech & Text Analytics [named] 751,680 751,680 \n", "4 Agent Copilot [named] 1,002,240 1,002,240 \n", "5 AI Summary & Insights 0 0 \n", "6 Direct Messaging 132 144 \n", "7 AI Translate 0 0 \n", "8 NICE IEX (NAM) 650,000 1,300,000 \n", "9 Legacy CC platform 0 0 \n", "10 Voice Bot deflection (labour avoided) 6,981,080 11,169,728 \n", "11 STA coaching (AHT) 562,386 899,817 \n", "12 Voice AHT (knowledge surfacing) 1,237,248 1,979,597 \n", "13 Voice ACW (summarization) 2,099,573 3,359,317 \n", "14 Supervisor time (AI summaries/insights) 318,500 509,600 \n", "15 Agentic Virtual Agent deflection (labour avoided) 0 2,077,459 \n", "16 TOTAL COSTS 5,222,876 7,120,784 \n", "17 TOTAL TAKEOUTS 650,000 1,300,000 \n", "18 TOTAL BENEFITS 11,198,787 19,995,517 \n", "19 NET 6,625,911 14,174,734 \n", "20 Cumulative net 6,625,911 20,800,644 \n", "\n", " Y3 3-yr Total \n", "0 2,788,232 8,364,695 \n", "1 972,240 2,625,072 \n", "2 2,294,640 3,900,888 \n", "3 751,680 2,255,040 \n", "4 1,002,240 3,006,720 \n", "5 0 0 \n", "6 144 420 \n", "7 4,434,000 4,434,000 \n", "8 1,300,000 3,250,000 \n", "9 0 0 \n", "10 13,264,052 31,414,859 \n", "11 1,068,533 2,530,735 \n", "12 2,350,772 5,567,617 \n", "13 3,989,188 9,448,078 \n", "14 605,150 1,433,250 \n", "15 2,466,982 4,544,441 \n", "16 12,243,176 24,586,835 \n", "17 1,300,000 3,250,000 \n", "18 23,744,677 54,938,980 \n", "19 12,801,501 33,602,145 \n", "20 33,602,145 61,028,701 " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "NPV @ 8%: $28,449,896 Payback: 0.00 years 3-yr ROI: 137%\n" ] } ], "source": [ "case = build_business_case(sites, scopes, meters, pricing, takeouts, scenario,\n", " implementation_cost=IMPLEMENTATION_COST,\n", " use_contracted=USE_CONTRACTED_RATES,\n", " benefit_params=BENEFIT_PARAMS_MODE)\n", "\n", "pnl = pd.concat([\n", " case[\"cost_by_year\"].drop(columns=\"confidence\"),\n", " case[\"takeouts_by_year\"].drop(columns=\"confidence\"),\n", " case[\"benefit_by_year\"].drop(columns=\"confidence\"),\n", " case[\"net_by_year\"],\n", "], ignore_index=True)\n", "pnl[\"3-yr Total\"] = pnl[[\"Y1\", \"Y2\", \"Y3\"]].sum(axis=1)\n", "display(pnl)\n", "\n", "pb = case[\"payback_period_years\"]\n", "pb_text = f\"{pb:.2f} years\" if pb is not None else \"never\"\n", "print(f\"NPV @ 8%: ${case['npv']:,.0f} Payback: {pb_text} \"\n", " f\"3-yr ROI: {case['roi_3yr']:.0%}\")" ] }, { "cell_type": "code", "execution_count": 15, "id": "c869422e", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:33:00.092683Z", "iopub.status.busy": "2026-07-13T19:33:00.092484Z", "iopub.status.idle": "2026-07-13T19:33:00.264469Z", "shell.execute_reply": "2026-07-13T19:33:00.263571Z" } }, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "mode": "lines+markers", "name": "Floor", "type": "scatter", "x": { "bdata": "AQID", "dtype": "i1" }, "y": { "bdata": "kAHmzPfxOkFcMJWpTCZjQS9Qu52k7HBB", "dtype": "f8" } }, { "mode": "lines+markers", "name": "Realistic", "type": "scatter", "x": { "bdata": "AQID", "dtype": "i1" }, "y": { "bdata": "WN07tp1GWUFNYpBFSNZzQWInjgrTBYBB", "dtype": "f8" } }, { "mode": "lines+markers", "name": "Stretch", "type": "scatter", "x": { "bdata": "AQID", "dtype": "i1" }, "y": { "bdata": "1qNwJg/IaUHmEqiU71F/QR6FGxpGI4dB", "dtype": "f8" } } ], "layout": { "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermap": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermap" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "Cumulative net cash flow by scenario" }, "xaxis": { "title": { "text": "Year" } }, "yaxis": { "tickformat": "$,.0f" } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Cumulative net cash flow — all three scenarios\n", "fig = go.Figure()\n", "for name in (\"floor\", \"realistic\", \"stretch\"):\n", " c = build_business_case(sites, scopes, meters, pricing, takeouts, name,\n", " implementation_cost=IMPLEMENTATION_COST,\n", " benefit_params=BENEFIT_PARAMS_MODE)\n", " fig.add_scatter(x=c[\"cumulative_net\"].year, y=c[\"cumulative_net\"].cumulative_net,\n", " mode=\"lines+markers\", name=name.capitalize())\n", "fig.update_layout(title=\"Cumulative net cash flow by scenario\",\n", " xaxis_title=\"Year\", yaxis_tickformat=\"$,.0f\")" ] }, { "cell_type": "markdown", "id": "855966ce", "metadata": {}, "source": [ "## Sensitivity — tornado & break-even" ] }, { "cell_type": "code", "execution_count": 16, "id": "bab4c657", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:33:00.266887Z", "iopub.status.busy": "2026-07-13T19:33:00.266647Z", "iopub.status.idle": "2026-07-13T19:33:00.944991Z", "shell.execute_reply": "2026-07-13T19:33:00.943841Z" } }, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "name": "-25%", "orientation": "h", "type": "bar", "x": { "bdata": "AAAAAAAAAAAAAAAAAAAAAACbJKi2xPFAwDdo8SUOIUFw0vARivYxwcAuqPeUez7B", "dtype": "f8" }, "y": [ "agentic_va_deflection", "email_auto_respond_rate", "voice_bot_deflection", "voice_bot_avg_minutes", "voice_knowledge_eligibility", "voice_summarization_eligibility" ] }, { "name": "+25%", "orientation": "h", "type": "bar", "x": { "bdata": "AAAAAAAAAAAAAAAAAAAAAACya0qYxvHAoCS5F+gNIcFA0vARivYxQaAuqPeUez5B", "dtype": "f8" }, "y": [ "agentic_va_deflection", "email_auto_respond_rate", "voice_bot_deflection", "voice_bot_avg_minutes", "voice_knowledge_eligibility", "voice_summarization_eligibility" ] } ], "layout": { "barmode": "overlay", "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermap": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermap" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "Tornado — NPV swing vs input ±25%" }, "xaxis": { "tickformat": "$,.0f", "title": { "text": "Δ 3-yr NPV ($)" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Tornado: vary each scenario driver ±25% (clamped to 0–1), hold others\n", "DRIVERS = [\"voice_bot_deflection\", \"voice_bot_avg_minutes\", \"agentic_va_deflection\",\n", " \"voice_summarization_eligibility\", \"voice_knowledge_eligibility\",\n", " \"email_auto_respond_rate\"]\n", "\n", "def npv_with(field, factor):\n", " v = getattr(scenario, field) * factor\n", " if field != \"voice_bot_avg_minutes\":\n", " v = min(max(v, 0.0), 1.0)\n", " sc = dataclasses.replace(scenario, **{field: v})\n", " return build_business_case(sites, scopes, meters, pricing, takeouts, sc,\n", " benefit_params=BENEFIT_PARAMS_MODE)[\"npv\"]\n", "\n", "base_npv = case[\"npv\"]\n", "rows = [{\"driver\": d, \"low\": npv_with(d, 0.75) - base_npv,\n", " \"high\": npv_with(d, 1.25) - base_npv} for d in DRIVERS]\n", "torn = pd.DataFrame(rows)\n", "torn[\"swing\"] = (torn.high - torn.low).abs()\n", "torn = torn.sort_values(\"swing\")\n", "go.Figure([\n", " go.Bar(y=torn.driver, x=torn.low, orientation=\"h\", name=\"-25%\"),\n", " go.Bar(y=torn.driver, x=torn.high, orientation=\"h\", name=\"+25%\"),\n", "]).update_layout(barmode=\"overlay\", title=\"Tornado — NPV swing vs input ±25%\",\n", " xaxis_title=\"Δ 3-yr NPV ($)\", xaxis_tickformat=\"$,.0f\")" ] }, { "cell_type": "code", "execution_count": 17, "id": "2b3dee90", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:33:00.947480Z", "iopub.status.busy": "2026-07-13T19:33:00.947233Z", "iopub.status.idle": "2026-07-13T19:33:02.288725Z", "shell.execute_reply": "2026-07-13T19:33:02.288084Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Break-even auto-respond rate: 0% (NPV already $28,449,896 at 0%)\n" ] }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "hovertemplate": "Email Auto-Respond rate=%{x}
3-yr NPV ($)=%{y}", "legendgroup": "", "line": { "color": "#636efa", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "", "orientation": "v", "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAAAAAAB7FK5H4XqUP3sUrkfheqQ/uB6F61G4rj97FK5H4Xq0P5qZmZmZmbk/uB6F61G4vj/sUbgehevBP3sUrkfhesQ/CtejcD0Kxz+amZmZmZnJPylcj8L1KMw/uB6F61G4zj+kcD0K16PQP+xRuB6F69E/MzMzMzMz0z97FK5H4XrUP8P1KFyPwtU/CtejcD0K1z9SuB6F61HYP5qZmZmZmdk/4XoUrkfh2j8pXI/C9SjcP3E9CtejcN0/uB6F61G43j8AAAAAAADgPw==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "SGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QQ==", "dtype": "f8" }, "yaxis": "y" } ], "layout": { "legend": { "tracegroupgap": 0 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermap": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermap" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "NPV vs email Auto-Respond rate" }, "xaxis": { "anchor": "y", "domain": [ 0.0, 1.0 ], "title": { "text": "Email Auto-Respond rate" } }, "yaxis": { "anchor": "x", "domain": [ 0.0, 1.0 ], "title": { "text": "3-yr NPV ($)" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Break-even: at what email Auto-Respond rate does the case break even?\n", "import numpy as np\n", "\n", "rates = np.linspace(0.0, 0.5, 26)\n", "npvs = [build_business_case(\n", " sites, scopes, meters, pricing, takeouts,\n", " dataclasses.replace(scenario, email_auto_respond_rate=float(r)),\n", " benefit_params=BENEFIT_PARAMS_MODE)[\"npv\"]\n", " for r in rates]\n", "breakeven = next((r for r, v in zip(rates, npvs) if v >= 0), None)\n", "print(\"Break-even auto-respond rate:\",\n", " f\"{breakeven:.0%}\" if breakeven is not None else \"not reached ≤50%\",\n", " f\"(NPV already ${npvs[0]:,.0f} at 0%)\" if npvs[0] >= 0 else \"\")\n", "px.line(x=rates, y=npvs, labels={\"x\": \"Email Auto-Respond rate\", \"y\": \"3-yr NPV ($)\"},\n", " title=\"NPV vs email Auto-Respond rate\")" ] }, { "cell_type": "markdown", "id": "2c4d5a54", "metadata": {}, "source": [ "## Export" ] }, { "cell_type": "code", "execution_count": 18, "id": "57611721", "metadata": { "execution": { "iopub.execute_input": "2026-07-13T19:33:02.293716Z", "iopub.status.busy": "2026-07-13T19:33:02.293526Z", "iopub.status.idle": "2026-07-13T19:33:02.541639Z", "shell.execute_reply": "2026-07-13T19:33:02.541002Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Excel → /home/robert/git/palladium/studies/202607_CTM_GenesysCX/exports/ctm_token_calculator_realistic.xlsx\n", "JSON → /home/robert/git/palladium/studies/202607_CTM_GenesysCX/exports/ctm_scenario_realistic.json\n" ] } ], "source": [ "scenario_comparison = pd.DataFrame([\n", " {\"scenario\": n,\n", " **{f\"NPV\": c[\"npv\"], \"payback_years\": c[\"payback_period_years\"],\n", " \"roi_3yr\": c[\"roi_3yr\"]}}\n", " for n, c in ((n, build_business_case(sites, scopes, meters, pricing,\n", " takeouts, n,\n", " benefit_params=BENEFIT_PARAMS_MODE))\n", " for n in (\"floor\", \"realistic\", \"stretch\"))\n", "])\n", "\n", "xlsx = export_excel({\n", " \"Inputs\": sites_dataframe(sites),\n", " \"Meters\": meters_dataframe(meters),\n", " \"Cost detail\": cost_3y,\n", " \"Benefit detail\": ben_3y,\n", " \"Business case\": pnl,\n", " \"Scenario comparison\": scenario_comparison,\n", "}, _ROOT / \"exports\" / f\"ctm_token_calculator_{SCENARIO}.xlsx\")\n", "json_path = _ROOT / \"exports\" / f\"ctm_scenario_{SCENARIO}.json\"\n", "scenario_state_to_json(sites, takeouts, scopes, json_path)\n", "print(f\"Excel → {xlsx}\\nJSON → {json_path}\")" ] }, { "cell_type": "markdown", "id": "ec9f50a0", "metadata": {}, "source": [ "## Scratchpad\n", "\n", "Ad-hoc analysis below — e.g. per-site cost detail:\n", "```python\n", "calculate_consumption_ai_cost(sites, scopes[0], meters[\"Voice Bot\"], scenario, pricing, year=YEAR)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "id": "76d303ce", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.7" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": { "06a1bded636445f6bf53fded75148290": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "2b35efbfa83f4dfb994080acef7b28cc": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "ToggleButtonsModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "ToggleButtonsModel", "_options_labels": [ "1", "2", "3" ], "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "ToggleButtonsView", "button_style": "", "description": "Year", "description_allow_html": false, "disabled": false, "icons": [], "index": 0, "layout": "IPY_MODEL_06a1bded636445f6bf53fded75148290", "style": "IPY_MODEL_f9f37238bba4439dbc32d0ed649e17f9", "tabbable": null, "tooltip": null, "tooltips": [] } }, "3462a88bfec94f01b6aea7530a431884": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "3dab48323eae42f4b02df79e20773531": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "4c9514e9b96142e9a269035bdd0714c4": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "577793de6703445bbac50d16994744b8": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "60707879e2d748d381f46fc74f0afe83": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "VA %", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_d68795b0944341bf8354500e127e4e59", "max": 0.5, "min": 0, "orientation": "horizontal", "readout": true, "readout_format": ".0%", "step": 0.01, "style": "IPY_MODEL_7e58dd9a55e44efd8c5b0d566118304c", "tabbable": null, "tooltip": null, "value": 0.15 } }, "6482ebca307b4d04996420d94f2aa0ac": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "65b0678176734553be6e24141b82f58c": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "69f65b8fab04496fa3f3b45116f421e5": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "ToggleButtonsModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "ToggleButtonsModel", "_options_labels": [ "floor", "realistic", "stretch" ], "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "ToggleButtonsView", "button_style": "", "description": "Scenario", "description_allow_html": false, "disabled": false, "icons": [], "index": 1, "layout": "IPY_MODEL_8afe69103c0948ec805cb3fc5c831d4a", "style": "IPY_MODEL_cc3fc8777cd34c539aa36ea9b125f2a4", "tabbable": null, "tooltip": null, "tooltips": [] } }, "6ce00d0669b94edcbc7574f9e690bb46": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "Bot min", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_3462a88bfec94f01b6aea7530a431884", "max": 5, "min": 0.5, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.1, "style": "IPY_MODEL_da443aae09c44a919b74f57076cd36f9", "tabbable": null, "tooltip": null, "value": 1.5 } }, "712b05a4eb6a4dacb70abd6df8a7dfbf": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "HBoxModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "HBoxModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "HBoxView", "box_style": "", "children": [ "IPY_MODEL_94ae237e32054fbebbab3a3b05563fe1", "IPY_MODEL_6ce00d0669b94edcbc7574f9e690bb46", "IPY_MODEL_60707879e2d748d381f46fc74f0afe83" ], "layout": "IPY_MODEL_3dab48323eae42f4b02df79e20773531", "tabbable": null, "tooltip": null } }, "7cd6b5152e354e418c8a9ee1a738208e": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "HBoxModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "HBoxModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "HBoxView", "box_style": "", "children": [ "IPY_MODEL_d4545b6a131b4490a6b546d9e2b5f1f5", "IPY_MODEL_f4843600b298491eb47c6e21eb2e66f3", "IPY_MODEL_fa90689f37c64ad59800e48ecc3e095b" ], "layout": "IPY_MODEL_fd382d2b7de247f79150b34908bbd6bd", "tabbable": null, "tooltip": null } }, "7e58dd9a55e44efd8c5b0d566118304c": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "8afe69103c0948ec805cb3fc5c831d4a": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "8d83e7fb02114d57adff5f3021cadd24": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "94ae237e32054fbebbab3a3b05563fe1": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "Bot %", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_9fe19d91747e4865a104e65b658b7c8e", "max": 0.7, "min": 0, "orientation": "horizontal", "readout": true, "readout_format": ".0%", "step": 0.01, "style": "IPY_MODEL_65b0678176734553be6e24141b82f58c", "tabbable": null, "tooltip": null, "value": 0.35 } }, "995b326fefa942da94ce18e92254860e": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "9fe19d91747e4865a104e65b658b7c8e": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "a8101d75b1794ba48f5b3ee90c545005": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "cc3fc8777cd34c539aa36ea9b125f2a4": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "ToggleButtonsStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "ToggleButtonsStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "button_width": "", "description_width": "", "font_weight": "" } }, "cf854dec89944ceca7119f9f177abfd5": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "VBoxModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "VBoxModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "VBoxView", "box_style": "", "children": [ "IPY_MODEL_712b05a4eb6a4dacb70abd6df8a7dfbf", "IPY_MODEL_7cd6b5152e354e418c8a9ee1a738208e" ], "layout": "IPY_MODEL_a8101d75b1794ba48f5b3ee90c545005", "tabbable": null, "tooltip": null } }, "d4545b6a131b4490a6b546d9e2b5f1f5": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "Completion", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_fd591354d1214f4b9b7d8850be81a511", "max": 1, "min": 0.3, "orientation": "horizontal", "readout": true, "readout_format": ".0%", "step": 0.01, "style": "IPY_MODEL_577793de6703445bbac50d16994744b8", "tabbable": null, "tooltip": null, "value": 0.7 } }, "d68795b0944341bf8354500e127e4e59": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "da443aae09c44a919b74f57076cd36f9": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "f4843600b298491eb47c6e21eb2e66f3": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "Labour real.", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_4c9514e9b96142e9a269035bdd0714c4", "max": 1, "min": 0.3, "orientation": "horizontal", "readout": true, "readout_format": ".0%", "step": 0.01, "style": "IPY_MODEL_8d83e7fb02114d57adff5f3021cadd24", "tabbable": null, "tooltip": null, "value": 0.8 } }, "f9f37238bba4439dbc32d0ed649e17f9": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "ToggleButtonsStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "ToggleButtonsStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "button_width": "", "description_width": "", "font_weight": "" } }, "fa90689f37c64ad59800e48ecc3e095b": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "Callback", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_995b326fefa942da94ce18e92254860e", "max": 0.3, "min": 0, "orientation": "horizontal", "readout": true, "readout_format": ".0%", "step": 0.01, "style": "IPY_MODEL_6482ebca307b4d04996420d94f2aa0ac", "tabbable": null, "tooltip": null, "value": 0.05 } }, "fd382d2b7de247f79150b34908bbd6bd": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "fd591354d1214f4b9b7d8850be81a511": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } } }, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 5 }