431 lines
18 KiB
Python
431 lines
18 KiB
Python
"""
|
|
CTM default inputs and the Genesys meter catalogue.
|
|
|
|
⚠️ Site volumes/AHTs/costs outside NAM are PLACEHOLDERS flagged
|
|
ESTIMATED — confirm with CTM data before client use. NAM volumes are
|
|
from the CTM discovery pack. Named users across all sites total the
|
|
contracted licence count (2,088).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .inputs import CostTakeout, FeatureScope, SiteInput
|
|
from .meters import Confidence, MeterType, TokenMeter, TokenPricing
|
|
from .rollout import RolloutPlan
|
|
|
|
# ── Platform ─────────────────────────────────────────────────────────
|
|
|
|
#: Genesys Cloud CX 3 named-user list rate, USD/user/month.
|
|
#: Source: Genesys Cloud public pricing (CX 3 tier), planning figure.
|
|
PLATFORM_RATE_PER_USER_MONTHLY = 111.28
|
|
|
|
#: CTM contracted named-user count — UI warns when site totals diverge.
|
|
CONTRACTED_NAMED_USERS = 2_088
|
|
|
|
#: Business-case discount rate (CTM treasury planning assumption).
|
|
DEFAULT_DISCOUNT_RATE = 0.08
|
|
|
|
#: One-off implementation estimate, amortized straight-line over the
|
|
#: analysis horizon in the P&L. ESTIMATED — confirm with delivery team.
|
|
DEFAULT_IMPLEMENTATION_COST = 0.0
|
|
|
|
_GENESYS_TOKEN_METERS = (
|
|
"https://help.genesys.cloud/articles/genesys-cloud-tokens-model/"
|
|
)
|
|
|
|
# ── Token meters ─────────────────────────────────────────────────────
|
|
# Rates per the published Genesys AI Experience token tables unless
|
|
# flagged otherwise. UNKNOWN meters carry working defaults (clearly
|
|
# labelled) so the model still produces a range.
|
|
|
|
DEFAULT_METERS: dict[str, TokenMeter] = {
|
|
m.feature: m
|
|
for m in [
|
|
# ── Voice / Bot ───────────────────────────────────────────────
|
|
TokenMeter(
|
|
feature="Voice Bot",
|
|
meter_type=MeterType.PER_MINUTE,
|
|
units_per_token=17.0,
|
|
tokens_per_unit=1 / 17, # 0.0588
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="IVR self-service voice bot minutes; 17 min per token.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
TokenMeter(
|
|
feature="Digital Bot",
|
|
meter_type=MeterType.PER_INTERACTION,
|
|
units_per_token=51.0,
|
|
tokens_per_unit=1 / 51, # 0.0196
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="Digital (non-voice) bot sessions; 51 sessions per token.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── Virtual Agent ─────────────────────────────────────────────
|
|
TokenMeter(
|
|
feature="Virtual Agent (legacy)",
|
|
meter_type=MeterType.PER_INTERACTION,
|
|
units_per_token=2.0,
|
|
tokens_per_unit=0.5,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="Legacy (non-agentic) virtual agent; 0.5 tokens per interaction.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
TokenMeter(
|
|
feature="Agentic Virtual Agent",
|
|
meter_type=MeterType.PER_INTERACTION,
|
|
units_per_token=0.833,
|
|
tokens_per_unit=1.2,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="Agentic VA; 1.2 tokens per interaction.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── Agent Copilot (named vs concurrent) ───────────────────────
|
|
TokenMeter(
|
|
feature="Agent Copilot [named]",
|
|
meter_type=MeterType.PER_USER_PER_MONTH,
|
|
units_per_token=0.0,
|
|
tokens_per_unit=40.0,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes=(
|
|
"40 tokens per named user per month. Includes interaction "
|
|
"summarization (covers AI Summary & Insights)."
|
|
),
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
TokenMeter(
|
|
feature="Agent Copilot [concurrent]",
|
|
meter_type=MeterType.PER_USER_PER_MONTH,
|
|
units_per_token=0.0,
|
|
tokens_per_unit=60.0,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes=(
|
|
"60 tokens per concurrent user per month. Includes interaction "
|
|
"summarization (covers AI Summary & Insights)."
|
|
),
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── AI Quality / Analytics ────────────────────────────────────
|
|
TokenMeter(
|
|
feature="AI Scoring",
|
|
meter_type=MeterType.PER_INTERACTION,
|
|
units_per_token=20.0,
|
|
tokens_per_unit=0.05,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="AI-scored quality evaluations; 20 evaluations per token.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
TokenMeter(
|
|
feature="AI Summary & Insights",
|
|
meter_type=MeterType.PER_SUMMARY,
|
|
units_per_token=50.0,
|
|
tokens_per_unit=0.02,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes=(
|
|
"Supervisor standalone summarization; 50 summaries per token. "
|
|
"NOT metered where Agent Copilot is assigned — see cost model."
|
|
),
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── Speech & Text Analytics (named vs concurrent) ─────────────
|
|
TokenMeter(
|
|
feature="Speech & Text Analytics [named]",
|
|
meter_type=MeterType.PER_USER_PER_MONTH,
|
|
units_per_token=0.0,
|
|
tokens_per_unit=30.0,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="STA named licence; 30 tokens per named user per month.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
TokenMeter(
|
|
feature="Speech & Text Analytics [concurrent]",
|
|
meter_type=MeterType.PER_USER_PER_MONTH,
|
|
units_per_token=0.0,
|
|
tokens_per_unit=45.0,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="STA concurrent licence; 45 tokens per concurrent user per month.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── Routing / Engagement ──────────────────────────────────────
|
|
TokenMeter(
|
|
feature="Predictive Routing",
|
|
meter_type=MeterType.PER_INTERACTION,
|
|
units_per_token=17.0,
|
|
tokens_per_unit=1 / 17, # 0.0588
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="Predictive routing; 17 routes per token.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── Messaging ─────────────────────────────────────────────────
|
|
TokenMeter(
|
|
feature="Direct Messaging",
|
|
meter_type=MeterType.PER_MESSAGE,
|
|
units_per_token=400.0,
|
|
tokens_per_unit=0.0025,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes=(
|
|
"Apple Messages for Business, Facebook Messenger, Instagram DM, "
|
|
"WhatsApp, and X (Twitter) DM; 400 inbound or outbound messages "
|
|
"per token. Additional carrier charges apply for WhatsApp and X."
|
|
),
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
TokenMeter(
|
|
feature="Social Listening",
|
|
meter_type=MeterType.PER_MESSAGE,
|
|
units_per_token=400.0,
|
|
tokens_per_unit=0.0025,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="Genesys Cloud Social; 400 social post ingestions per channel per token.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
TokenMeter(
|
|
feature="Social Responses",
|
|
meter_type=MeterType.PER_MESSAGE,
|
|
units_per_token=400.0,
|
|
tokens_per_unit=0.0025,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="Social Post Responses; 400 outbound messages per channel per token.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── Language / Translation ────────────────────────────────────
|
|
TokenMeter(
|
|
feature="AI Translate",
|
|
meter_type=MeterType.PER_INTERACTION,
|
|
units_per_token=2.0,
|
|
tokens_per_unit=0.5,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes="AI translation; 2 translations per token.",
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── Genesys Cloud Copilot ─────────────────────────────────────
|
|
TokenMeter(
|
|
feature="Genesys Cloud Copilot",
|
|
meter_type=MeterType.PER_INTERACTION,
|
|
units_per_token=20.0,
|
|
tokens_per_unit=0.05,
|
|
confidence=Confidence.CONFIRMED,
|
|
notes=(
|
|
"20 AI actions per token; Genesys Cloud knowledge queries "
|
|
"are not charged."
|
|
),
|
|
source_url=_GENESYS_TOKEN_METERS,
|
|
),
|
|
# ── Email AI (rates not yet published) ────────────────────────
|
|
TokenMeter(
|
|
feature="Email AI (Auto-Suggest)",
|
|
meter_type=MeterType.PER_USER_PER_MONTH,
|
|
units_per_token=0.0,
|
|
tokens_per_unit=0.0,
|
|
confidence=Confidence.UNKNOWN,
|
|
notes="Requires Agent Copilot. Token rate not yet published.",
|
|
),
|
|
TokenMeter(
|
|
feature="Email AI (Auto-Respond)",
|
|
meter_type=MeterType.PER_MESSAGE,
|
|
units_per_token=0.0,
|
|
tokens_per_unit=0.0,
|
|
confidence=Confidence.UNKNOWN,
|
|
notes="Feature not yet available; rate TBD.",
|
|
),
|
|
]
|
|
}
|
|
|
|
#: Features metered per named user per month.
|
|
PER_USER_FEATURES = [
|
|
f for f, m in DEFAULT_METERS.items()
|
|
if m.meter_type is MeterType.PER_USER_PER_MONTH
|
|
]
|
|
|
|
# ── Token pricing ────────────────────────────────────────────────────
|
|
# $1/token US list confirmed; other regions default to the same list
|
|
# rate until regional figures are sourced (override in UI).
|
|
|
|
DEFAULT_PRICING: dict[str, TokenPricing] = {
|
|
"US": TokenPricing(region="US", list_rate_per_token=1.0),
|
|
"EU": TokenPricing(region="EU", list_rate_per_token=1.0), # TBD — assumed US list
|
|
"AU": TokenPricing(region="AU", list_rate_per_token=1.0), # TBD — assumed US list
|
|
"APAC": TokenPricing(region="APAC", list_rate_per_token=1.0), # TBD
|
|
}
|
|
|
|
# ── CTM sites ────────────────────────────────────────────────────────
|
|
# NAM figures from CTM discovery. ALL OTHER SITES + every AHT/ACW and
|
|
# labour-cost figure are ESTIMATED placeholders — confirm with CTM.
|
|
# Named users sum to CONTRACTED_NAMED_USERS (2,088).
|
|
|
|
_COMMON = {
|
|
"voice_aht_seconds": 300, # placeholder — flag as estimate
|
|
"email_aht_seconds": 600,
|
|
"chat_aht_seconds": 480,
|
|
"voice_acw_seconds": 60,
|
|
}
|
|
|
|
CTM_DEFAULT_SITES: list[SiteInput] = [
|
|
SiteInput(
|
|
"NAM", "US", agents=890, supervisors=60, # split TBD
|
|
voice_volume_monthly=1_214_358,
|
|
email_volume_monthly=275_800,
|
|
chat_volume_monthly=110,
|
|
sms_volume_monthly=1_040,
|
|
fully_loaded_agent_cost_annual=65_000, # placeholder
|
|
fully_loaded_supervisor_cost_annual=95_000,
|
|
languages=["English", "French", "Spanish"],
|
|
**_COMMON,
|
|
),
|
|
SiteInput(
|
|
"EMEA", "EU", agents=320, supervisors=25,
|
|
voice_volume_monthly=420_000,
|
|
email_volume_monthly=95_000,
|
|
chat_volume_monthly=40,
|
|
sms_volume_monthly=400,
|
|
fully_loaded_agent_cost_annual=60_000,
|
|
fully_loaded_supervisor_cost_annual=88_000,
|
|
languages=["English", "French", "German", "Italian", "Spanish"],
|
|
**_COMMON,
|
|
),
|
|
SiteInput(
|
|
"AUZ", "AU", agents=180, supervisors=15,
|
|
voice_volume_monthly=250_000,
|
|
email_volume_monthly=56_000,
|
|
chat_volume_monthly=25,
|
|
sms_volume_monthly=250,
|
|
fully_loaded_agent_cost_annual=70_000,
|
|
fully_loaded_supervisor_cost_annual=100_000,
|
|
languages=["English"],
|
|
**_COMMON,
|
|
),
|
|
SiteInput(
|
|
"APAC HK", "APAC", agents=120, supervisors=10,
|
|
voice_volume_monthly=160_000,
|
|
email_volume_monthly=38_000,
|
|
chat_volume_monthly=15,
|
|
sms_volume_monthly=150,
|
|
fully_loaded_agent_cost_annual=55_000,
|
|
fully_loaded_supervisor_cost_annual=80_000,
|
|
languages=["English", "Cantonese", "Mandarin"],
|
|
**_COMMON,
|
|
),
|
|
SiteInput(
|
|
"APAC SG", "APAC", agents=110, supervisors=10,
|
|
voice_volume_monthly=150_000,
|
|
email_volume_monthly=34_000,
|
|
chat_volume_monthly=15,
|
|
sms_volume_monthly=120,
|
|
fully_loaded_agent_cost_annual=55_000,
|
|
fully_loaded_supervisor_cost_annual=80_000,
|
|
languages=["English", "Mandarin", "Malay"],
|
|
**_COMMON,
|
|
),
|
|
SiteInput(
|
|
"APAC SH", "APAC", agents=130, supervisors=10,
|
|
voice_volume_monthly=175_000,
|
|
email_volume_monthly=40_000,
|
|
chat_volume_monthly=15,
|
|
sms_volume_monthly=130,
|
|
fully_loaded_agent_cost_annual=35_000,
|
|
fully_loaded_supervisor_cost_annual=55_000,
|
|
languages=["Mandarin"],
|
|
**_COMMON,
|
|
),
|
|
SiteInput(
|
|
"APAC GZ", "APAC", agents=90, supervisors=8,
|
|
voice_volume_monthly=120_000,
|
|
email_volume_monthly=28_000,
|
|
chat_volume_monthly=10,
|
|
sms_volume_monthly=100,
|
|
fully_loaded_agent_cost_annual=35_000,
|
|
fully_loaded_supervisor_cost_annual=55_000,
|
|
languages=["Mandarin", "Cantonese"],
|
|
**_COMMON,
|
|
),
|
|
SiteInput(
|
|
"APAC JP", "APAC", agents=60, supervisors=6,
|
|
voice_volume_monthly=80_000,
|
|
email_volume_monthly=19_000,
|
|
chat_volume_monthly=8,
|
|
sms_volume_monthly=80,
|
|
fully_loaded_agent_cost_annual=60_000,
|
|
fully_loaded_supervisor_cost_annual=85_000,
|
|
languages=["Japanese"],
|
|
**_COMMON,
|
|
),
|
|
SiteInput(
|
|
"APAC TW", "APAC", agents=40, supervisors=4,
|
|
voice_volume_monthly=54_000,
|
|
email_volume_monthly=12_000,
|
|
chat_volume_monthly=5,
|
|
sms_volume_monthly=50,
|
|
fully_loaded_agent_cost_annual=40_000,
|
|
fully_loaded_supervisor_cost_annual=60_000,
|
|
languages=["Mandarin"],
|
|
**_COMMON,
|
|
),
|
|
]
|
|
|
|
ALL_SITE_NAMES = [s.site_name for s in CTM_DEFAULT_SITES]
|
|
|
|
# ── Cost takeouts ────────────────────────────────────────────────────
|
|
|
|
CTM_DEFAULT_TAKEOUTS: list[CostTakeout] = [
|
|
CostTakeout(
|
|
"NICE IEX (NAM)",
|
|
annual_cost=1_300_000,
|
|
start_year=1,
|
|
start_month=7, # can only switch off after NAM go-live (month 6)
|
|
confidence=Confidence.ESTIMATED,
|
|
notes="Mid-band estimate; needs CTM contract confirmation.",
|
|
),
|
|
CostTakeout(
|
|
"Legacy CC platform",
|
|
annual_cost=0,
|
|
start_year=2,
|
|
confidence=Confidence.UNKNOWN,
|
|
notes="Placeholder — populate once retirement scope is confirmed.",
|
|
),
|
|
]
|
|
|
|
# ── Default rollout & ramp ───────────────────────────────────────────
|
|
# 12-month build. Genesys bills the licence commit from contract start;
|
|
# the 6-month ramp gives a 50% first-year credit on the platform commit.
|
|
# AI token usage (and benefits) start only when each region goes live.
|
|
|
|
CTM_DEFAULT_ROLLOUT = RolloutPlan(
|
|
contract_start=None, # set when known — "Date Genesys starts billing"
|
|
build_months=12,
|
|
ramp_months=6,
|
|
first_year_platform_discount=0.50,
|
|
go_live_month={
|
|
"NAM": 6,
|
|
"EMEA": 9,
|
|
"AUZ": 12,
|
|
"APAC HK": 12,
|
|
"APAC SG": 12,
|
|
"APAC SH": 12,
|
|
"APAC GZ": 12,
|
|
"APAC JP": 12,
|
|
"APAC TW": 12,
|
|
},
|
|
)
|
|
|
|
# ── Default feature scoping / phasing ────────────────────────────────
|
|
# Phase = model year the feature switches on. Consumption features ramp
|
|
# via adoption_curve; per-user licences are paid in full from the phase
|
|
# year.
|
|
|
|
_RAMP = {1: 0.70, 2: 1.0, 3: 1.0}
|
|
|
|
CTM_DEFAULT_FEATURE_SCOPES: list[FeatureScope] = [
|
|
FeatureScope("Voice Bot", ALL_SITE_NAMES, phase=1, adoption_curve=_RAMP),
|
|
FeatureScope("Agentic Virtual Agent", ["NAM", "EMEA"], phase=2,
|
|
adoption_curve={2: 0.70, 3: 1.0}),
|
|
# CTM has named licences — use the [named] variant for both STA and Copilot.
|
|
FeatureScope("Speech & Text Analytics [named]", ALL_SITE_NAMES, phase=1),
|
|
FeatureScope("Agent Copilot [named]", ALL_SITE_NAMES, phase=1),
|
|
FeatureScope("AI Summary & Insights", ALL_SITE_NAMES, phase=1,
|
|
adoption_curve=_RAMP),
|
|
FeatureScope("Direct Messaging", ALL_SITE_NAMES, phase=1, adoption_curve=_RAMP),
|
|
FeatureScope("Email AI (Auto-Suggest)", ["NAM", "EMEA"], phase=2),
|
|
FeatureScope("AI Translate",
|
|
["APAC HK", "APAC SG", "APAC SH", "APAC GZ", "APAC JP", "APAC TW"],
|
|
phase=3),
|
|
]
|