Files
palladium/studies/202607_CTM_GenesysCX/notebooks/ctm_token_calculator.ipynb

9612 lines
259 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"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 ──────────────────────────────────────────────────────────\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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>site_name</th>\n",
" <th>region_pricing</th>\n",
" <th>agents</th>\n",
" <th>supervisors</th>\n",
" <th>voice_volume_monthly</th>\n",
" <th>email_volume_monthly</th>\n",
" <th>chat_volume_monthly</th>\n",
" <th>sms_volume_monthly</th>\n",
" <th>voice_aht_seconds</th>\n",
" <th>email_aht_seconds</th>\n",
" <th>chat_aht_seconds</th>\n",
" <th>voice_acw_seconds</th>\n",
" <th>fully_loaded_agent_cost_annual</th>\n",
" <th>fully_loaded_supervisor_cost_annual</th>\n",
" <th>licence_type</th>\n",
" <th>languages</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>NAM</td>\n",
" <td>US</td>\n",
" <td>890</td>\n",
" <td>60</td>\n",
" <td>1214358</td>\n",
" <td>275800</td>\n",
" <td>110</td>\n",
" <td>1040</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>65000</td>\n",
" <td>95000</td>\n",
" <td>named</td>\n",
" <td>English, French, Spanish</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>EMEA</td>\n",
" <td>EU</td>\n",
" <td>320</td>\n",
" <td>25</td>\n",
" <td>420000</td>\n",
" <td>95000</td>\n",
" <td>40</td>\n",
" <td>400</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>60000</td>\n",
" <td>88000</td>\n",
" <td>named</td>\n",
" <td>English, French, German, Italian, Spanish</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>AUZ</td>\n",
" <td>AU</td>\n",
" <td>180</td>\n",
" <td>15</td>\n",
" <td>250000</td>\n",
" <td>56000</td>\n",
" <td>25</td>\n",
" <td>250</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>70000</td>\n",
" <td>100000</td>\n",
" <td>named</td>\n",
" <td>English</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>APAC HK</td>\n",
" <td>APAC</td>\n",
" <td>120</td>\n",
" <td>10</td>\n",
" <td>160000</td>\n",
" <td>38000</td>\n",
" <td>15</td>\n",
" <td>150</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>55000</td>\n",
" <td>80000</td>\n",
" <td>named</td>\n",
" <td>English, Cantonese, Mandarin</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>APAC SG</td>\n",
" <td>APAC</td>\n",
" <td>110</td>\n",
" <td>10</td>\n",
" <td>150000</td>\n",
" <td>34000</td>\n",
" <td>15</td>\n",
" <td>120</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>55000</td>\n",
" <td>80000</td>\n",
" <td>named</td>\n",
" <td>English, Mandarin, Malay</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>APAC SH</td>\n",
" <td>APAC</td>\n",
" <td>130</td>\n",
" <td>10</td>\n",
" <td>175000</td>\n",
" <td>40000</td>\n",
" <td>15</td>\n",
" <td>130</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>35000</td>\n",
" <td>55000</td>\n",
" <td>named</td>\n",
" <td>Mandarin</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>APAC GZ</td>\n",
" <td>APAC</td>\n",
" <td>90</td>\n",
" <td>8</td>\n",
" <td>120000</td>\n",
" <td>28000</td>\n",
" <td>10</td>\n",
" <td>100</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>35000</td>\n",
" <td>55000</td>\n",
" <td>named</td>\n",
" <td>Mandarin, Cantonese</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>APAC JP</td>\n",
" <td>APAC</td>\n",
" <td>60</td>\n",
" <td>6</td>\n",
" <td>80000</td>\n",
" <td>19000</td>\n",
" <td>8</td>\n",
" <td>80</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>60000</td>\n",
" <td>85000</td>\n",
" <td>named</td>\n",
" <td>Japanese</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>APAC TW</td>\n",
" <td>APAC</td>\n",
" <td>40</td>\n",
" <td>4</td>\n",
" <td>54000</td>\n",
" <td>12000</td>\n",
" <td>5</td>\n",
" <td>50</td>\n",
" <td>300</td>\n",
" <td>600</td>\n",
" <td>480</td>\n",
" <td>60</td>\n",
" <td>40000</td>\n",
" <td>60000</td>\n",
" <td>named</td>\n",
" <td>Mandarin</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>takeout</th>\n",
" <th>annual_cost</th>\n",
" <th>start_year</th>\n",
" <th>confidence</th>\n",
" <th>notes</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>NICE IEX (NAM)</td>\n",
" <td>1300000</td>\n",
" <td>1</td>\n",
" <td>🟡 estimated</td>\n",
" <td>Mid-band estimate; needs CTM contract confirma...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Legacy CC platform</td>\n",
" <td>0</td>\n",
" <td>2</td>\n",
" <td>🔴 unknown</td>\n",
" <td>Placeholder — populate once retirement scope i...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>feature</th>\n",
" <th>meter_type</th>\n",
" <th>units_per_token</th>\n",
" <th>tokens_per_unit</th>\n",
" <th>confidence</th>\n",
" <th>notes</th>\n",
" <th>source</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Voice Bot</td>\n",
" <td>per_minute</td>\n",
" <td>17</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>IVR self-service voice bot minutes; 17 min per...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Digital Bot</td>\n",
" <td>per_interaction</td>\n",
" <td>51</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>Digital (non-voice) bot sessions; 51 sessions ...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Virtual Agent (legacy)</td>\n",
" <td>per_interaction</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>Legacy (non-agentic) virtual agent; 0.5 tokens...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Agentic Virtual Agent</td>\n",
" <td>per_interaction</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>Agentic VA; 1.2 tokens per interaction.</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Agent Copilot [named]</td>\n",
" <td>per_user_per_month</td>\n",
" <td>NaN</td>\n",
" <td>40</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>40 tokens per named user per month. Includes i...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Agent Copilot [concurrent]</td>\n",
" <td>per_user_per_month</td>\n",
" <td>NaN</td>\n",
" <td>60</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>60 tokens per concurrent user per month. Inclu...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>AI Scoring</td>\n",
" <td>per_interaction</td>\n",
" <td>20</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>AI-scored quality evaluations; 20 evaluations ...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>AI Summary &amp; Insights</td>\n",
" <td>per_summary</td>\n",
" <td>50</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>Supervisor standalone summarization; 50 summar...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>Speech &amp; Text Analytics [named]</td>\n",
" <td>per_user_per_month</td>\n",
" <td>NaN</td>\n",
" <td>30</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>STA named licence; 30 tokens per named user pe...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Speech &amp; Text Analytics [concurrent]</td>\n",
" <td>per_user_per_month</td>\n",
" <td>NaN</td>\n",
" <td>45</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>STA concurrent licence; 45 tokens per concurre...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>Predictive Routing</td>\n",
" <td>per_interaction</td>\n",
" <td>17</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>Predictive routing; 17 routes per token.</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>Direct Messaging</td>\n",
" <td>per_message</td>\n",
" <td>400</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>Apple Messages for Business, Facebook Messenge...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>Social Listening</td>\n",
" <td>per_message</td>\n",
" <td>400</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>Genesys Cloud Social; 400 social post ingestio...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>Social Responses</td>\n",
" <td>per_message</td>\n",
" <td>400</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>Social Post Responses; 400 outbound messages p...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>AI Translate</td>\n",
" <td>per_interaction</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>AI translation; 2 translations per token.</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>Genesys Cloud Copilot</td>\n",
" <td>per_interaction</td>\n",
" <td>20</td>\n",
" <td>0</td>\n",
" <td>🟢 confirmed</td>\n",
" <td>20 AI actions per token; Genesys Cloud knowled...</td>\n",
" <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>Email AI (Auto-Respond)</td>\n",
" <td>per_message</td>\n",
" <td>NaN</td>\n",
" <td>0</td>\n",
" <td>🔴 unknown</td>\n",
" <td>Feature not yet available; rate TBD.</td>\n",
" <td></td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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<br>(14,572,296)",
"Voice Bot<br>(5,100,304)",
"Agentic VA<br>(1,420,799)",
"To agent<br>(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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>layer</th>\n",
" <th>% of total</th>\n",
" <th>annual calls</th>\n",
" <th>labour avoided (raw)</th>\n",
" <th>labour avoided (realized)</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Voice Bot deflection</td>\n",
" <td>35.0%</td>\n",
" <td>5,100,304</td>\n",
" <td>13,282,041</td>\n",
" <td>7,066,046</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Agentic VA deflection (residual)</td>\n",
" <td>9.8%</td>\n",
" <td>1,420,799</td>\n",
" <td>3,699,997</td>\n",
" <td>1,968,398</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Combined (effective)</td>\n",
" <td>44.75%</td>\n",
" <td>6,521,102</td>\n",
" <td>16,982,038</td>\n",
" <td>9,034,444</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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<br>({_annual_calls:,.0f})\",\n",
" f\"Voice Bot<br>({bot_calls:,.0f})\",\n",
" f\"Agentic VA<br>({va_calls:,.0f})\",\n",
" f\"To agent<br>({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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>input</th>\n",
" <th>value</th>\n",
" <th>drives</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Voice Bot deflection (full pool)</td>\n",
" <td>35%</td>\n",
" <td>Voice Bot tokens (cost) + bot deflection benefit</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Voice Bot avg minutes</td>\n",
" <td>1.5 min</td>\n",
" <td>Voice Bot tokens (cost only)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Agentic VA deflection (residual)</td>\n",
" <td>15%</td>\n",
" <td>Agentic VA tokens (cost) + VA deflection benefit</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Effective combined deflection</td>\n",
" <td>44.75%</td>\n",
" <td>Total share of voice calls deflected</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Realization factor</td>\n",
" <td>53.2%</td>\n",
" <td>Haircut on labour avoided (70% × 80% × 95%)</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>model</th>\n",
" <th>Y2 benefit</th>\n",
" <th>vs corrected</th>\n",
" <th>note</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Original (broken) — additive on full base, no ...</td>\n",
" <td>29,993,898</td>\n",
" <td></td>\n",
" <td>Counts bot + VA on the same call pool, 100% la...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Corrected — layered + 'claim' params (no hairc...</td>\n",
" <td>24,900,726</td>\n",
" <td>-17.0%</td>\n",
" <td>Layered model alone removes double-count</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Corrected — layered + realistic haircuts (curr...</td>\n",
" <td>13,247,186</td>\n",
" <td>-55.8%</td>\n",
" <td>Production-calibrated; this is what flows into...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>cost_line</th>\n",
" <th>scope</th>\n",
" <th>annual_cost</th>\n",
" <th>confidence</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Genesys CX 3 platform licences</td>\n",
" <td>all sites</td>\n",
" <td>2,788,232</td>\n",
" <td>confirmed</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Agent Copilot [named]</td>\n",
" <td>NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...</td>\n",
" <td>1,002,240</td>\n",
" <td>confirmed</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Speech &amp; Text Analytics [named]</td>\n",
" <td>NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...</td>\n",
" <td>751,680</td>\n",
" <td>confirmed</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Voice Bot</td>\n",
" <td>NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...</td>\n",
" <td>680,592</td>\n",
" <td>confirmed</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Direct Messaging</td>\n",
" <td>NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...</td>\n",
" <td>132</td>\n",
" <td>confirmed</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Agentic Virtual Agent</td>\n",
" <td>—</td>\n",
" <td>0</td>\n",
" <td>confirmed</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>AI Summary &amp; Insights</td>\n",
" <td>—</td>\n",
" <td>0</td>\n",
" <td>confirmed</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>AI Translate</td>\n",
" <td>—</td>\n",
" <td>0</td>\n",
" <td>confirmed</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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]<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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]<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>benefit_line</th>\n",
" <th>scope</th>\n",
" <th>annual_value</th>\n",
" <th>confidence</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Voice Bot deflection (labour avoided)</td>\n",
" <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
" <td>6,981,080</td>\n",
" <td>estimated</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Voice ACW (summarization)</td>\n",
" <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
" <td>2,099,573</td>\n",
" <td>estimated</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Voice AHT (knowledge surfacing)</td>\n",
" <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
" <td>1,237,248</td>\n",
" <td>estimated</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>STA coaching (AHT)</td>\n",
" <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
" <td>562,386</td>\n",
" <td>estimated</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Supervisor time (AI summaries/insights)</td>\n",
" <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
" <td>318,500</td>\n",
" <td>estimated</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>line</th>\n",
" <th>Y1</th>\n",
" <th>Y2</th>\n",
" <th>Y3</th>\n",
" <th>3-yr Total</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Genesys CX 3 platform licences</td>\n",
" <td>2,788,232</td>\n",
" <td>2,788,232</td>\n",
" <td>2,788,232</td>\n",
" <td>8,364,695</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Voice Bot</td>\n",
" <td>680,592</td>\n",
" <td>972,240</td>\n",
" <td>972,240</td>\n",
" <td>2,625,072</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Agentic Virtual Agent</td>\n",
" <td>0</td>\n",
" <td>1,606,248</td>\n",
" <td>2,294,640</td>\n",
" <td>3,900,888</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Speech &amp; Text Analytics [named]</td>\n",
" <td>751,680</td>\n",
" <td>751,680</td>\n",
" <td>751,680</td>\n",
" <td>2,255,040</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Agent Copilot [named]</td>\n",
" <td>1,002,240</td>\n",
" <td>1,002,240</td>\n",
" <td>1,002,240</td>\n",
" <td>3,006,720</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>AI Summary &amp; Insights</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Direct Messaging</td>\n",
" <td>132</td>\n",
" <td>144</td>\n",
" <td>144</td>\n",
" <td>420</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>AI Translate</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>4,434,000</td>\n",
" <td>4,434,000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>NICE IEX (NAM)</td>\n",
" <td>650,000</td>\n",
" <td>1,300,000</td>\n",
" <td>1,300,000</td>\n",
" <td>3,250,000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Legacy CC platform</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>Voice Bot deflection (labour avoided)</td>\n",
" <td>6,981,080</td>\n",
" <td>11,169,728</td>\n",
" <td>13,264,052</td>\n",
" <td>31,414,859</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>STA coaching (AHT)</td>\n",
" <td>562,386</td>\n",
" <td>899,817</td>\n",
" <td>1,068,533</td>\n",
" <td>2,530,735</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>Voice AHT (knowledge surfacing)</td>\n",
" <td>1,237,248</td>\n",
" <td>1,979,597</td>\n",
" <td>2,350,772</td>\n",
" <td>5,567,617</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>Voice ACW (summarization)</td>\n",
" <td>2,099,573</td>\n",
" <td>3,359,317</td>\n",
" <td>3,989,188</td>\n",
" <td>9,448,078</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>Supervisor time (AI summaries/insights)</td>\n",
" <td>318,500</td>\n",
" <td>509,600</td>\n",
" <td>605,150</td>\n",
" <td>1,433,250</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>Agentic Virtual Agent deflection (labour avoided)</td>\n",
" <td>0</td>\n",
" <td>2,077,459</td>\n",
" <td>2,466,982</td>\n",
" <td>4,544,441</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>TOTAL COSTS</td>\n",
" <td>5,222,876</td>\n",
" <td>7,120,784</td>\n",
" <td>12,243,176</td>\n",
" <td>24,586,835</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>TOTAL TAKEOUTS</td>\n",
" <td>650,000</td>\n",
" <td>1,300,000</td>\n",
" <td>1,300,000</td>\n",
" <td>3,250,000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>TOTAL BENEFITS</td>\n",
" <td>11,198,787</td>\n",
" <td>19,995,517</td>\n",
" <td>23,744,677</td>\n",
" <td>54,938,980</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>NET</td>\n",
" <td>6,625,911</td>\n",
" <td>14,174,734</td>\n",
" <td>12,801,501</td>\n",
" <td>33,602,145</td>\n",
" </tr>\n",
" <tr>\n",
" <th>20</th>\n",
" <td>Cumulative net</td>\n",
" <td>6,625,911</td>\n",
" <td>20,800,644</td>\n",
" <td>33,602,145</td>\n",
" <td>61,028,701</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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 01), 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}<br>3-yr NPV ($)=%{y}<extra></extra>",
"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.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.0,
"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.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.0,
"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.0,
"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.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
}