173 lines
8.8 KiB
Markdown
173 lines
8.8 KiB
Markdown
# Genesys Cloud AI — Token Calculator
|
||
|
||
A **Calculator** — a reusable vendor-pricing master (see
|
||
[`docs/Calculator_Pattern_V1-00.md`](../../docs/Calculator_Pattern_V1-00.md))
|
||
— built on the
|
||
[Mercury Notebook Deliverable Pattern](../../docs/Mercury_Notebook_Pattern_V1-00.md).
|
||
It prices what Genesys Cloud AI **costs to run**, from the vendor's own
|
||
published rate card. Unlike a TEI study it computes no benefits and no NPV:
|
||
its "numbers" are a run-rate, a per-feature breakdown, and a range.
|
||
|
||
The Mercury stage is the screen you share with a client while you size their
|
||
AI footprint together; the consultant run-book, the verification gate, and the
|
||
machine-readable appendix live backstage and export as LLM input for a
|
||
downstream business case.
|
||
|
||
## The anchor: the vendor's published rate card
|
||
|
||
The meters are Genesys' own, transcribed verbatim into
|
||
[`genesyscalc/ratecard.py`](genesyscalc/ratecard.py):
|
||
|
||
| Source | Published | What it gives |
|
||
|---|---|---|
|
||
| [Genesys Cloud tokens model](https://help.genesys.cloud/articles/genesys-cloud-tokens-model/) | **2026-07-12** | 20 token meters, the free monthly allowance, the highest-tier rule, the Copilot exclusion |
|
||
| [Genesys Enhanced TTS pricing](https://help.genesys.cloud/articles/genesys-enhanced-tts-pricing/) | **2026-05-22** | $/million characters — **not** token-metered |
|
||
|
||
That file is **immutable**. When Genesys republishes, re-anchoring is a
|
||
deliberate act with its own protocol — see *Re-anchoring* below.
|
||
|
||
### Four published rules the obvious arithmetic gets wrong
|
||
|
||
Each is enforced in the engine, pinned by a test, and reported in the
|
||
notebook's warnings rather than silently applied:
|
||
|
||
1. **The 15-second per-call round-up.** *"Genesys rounds up each call to the
|
||
next 15-second increment."* Applied per call and then summed — averaging
|
||
first understates the bill. A 40-second average bills as 45 (+12.5%); a
|
||
5-second bot greeting bills as 15 (3× its duration).
|
||
2. **The free monthly allowance.** 250 tokens named / 350 concurrent, which
|
||
*"renew each month and do not carry over"* — so it is a real deduction, and
|
||
an unused remainder is discarded, never banked.
|
||
3. **The highest-tier rule.** *"Genesys bases charges on the highest tier
|
||
(price) resource…"* — so the deflection shares are a **partition**, not
|
||
overlapping rates. An interaction is charged once, at the highest tier it
|
||
touched. Summing tiers independently over-bills.
|
||
4. **Copilot covers Supervisor summaries.** Enabling Agent Copilot makes AI
|
||
Summary & Insights free; billing both double-charges.
|
||
|
||
## What the client sees (the stage)
|
||
|
||
The **published rate card** as the vendor prints it, then three KPI cards
|
||
(token cost, text-to-speech, total run-rate with a $/interaction figure), the
|
||
allowance shown as the deduction it is, a per-feature cost breakdown, the
|
||
list-price → negotiated walk, text-to-speech as its own clearly separated
|
||
line, an adoption scenario range, and a tornado of what actually moves the
|
||
number.
|
||
|
||
Text-to-speech is **never** folded silently into the token subtotal: the grand
|
||
total always shows tokens and TTS as two labelled components.
|
||
|
||
You drive it from the sidebar — licence model, currency, token price and
|
||
concession, the three deflection shares, average bot seconds, and a
|
||
per-feature enable. Every change re-renders the numbers (Mercury re-runs the
|
||
cells below the widgets).
|
||
|
||
## Where the content lives: in the notebook
|
||
|
||
Two tagged cells of
|
||
[`notebooks/genesys_token_calculator.ipynb`](notebooks/genesys_token_calculator.ipynb)
|
||
carry everything a consultant edits — **in Jupyter, never in a `.py` file**:
|
||
|
||
- **`topic-bank`** — the **feature catalogue**: each priced capability's
|
||
client-facing title, what it does for them, and the sizing question to ask.
|
||
The `key` slugs must match published meter keys (a test pins this), and they
|
||
are stable identities the widgets, notes and JSON export all key off.
|
||
- **`engagement-data`** — the client facts: volumes by channel, headcount,
|
||
licence model, and the **negotiated** commercial terms (contracted rate,
|
||
concession). **Illustrative placeholders in this master**; filled in the
|
||
engagement copy.
|
||
|
||
The published **rates** are deliberately *not* content — nobody in this repo
|
||
authors them, and editing them is forbidden. They are the vendor's record, so
|
||
they live in the engine as an anchor. See the Calculator Pattern for the full
|
||
boundary.
|
||
|
||
`genesyscalc/` holds **code only** — the meter schema, the anchor, and the
|
||
arithmetic. The test suite reads the tagged cells straight out of the notebook
|
||
(no kernel) and pins content shape, so `pytest` guards the catalogue exactly
|
||
as shipped.
|
||
|
||
## Layout
|
||
|
||
```
|
||
notebooks/genesys_token_calculator.ipynb # THE deliverable — content + data + presentation
|
||
# tagged: topic-bank · engagement-data ·
|
||
# presentation ×8 · gate · data-appendix
|
||
genesyscalc/ # the engine — code only, no content, mypy --strict
|
||
ratecard.py # THE VERBATIM ANCHOR — published meters, 2026-07-12
|
||
meters.py # schema: Confidence, LicenceModel, MeterBasis, Tier, Meter, TokenPrice
|
||
usage.py # volumes → units → tokens (round-up, tier partition, Copilot rule)
|
||
billing.py # tokens → dollars (ceil, allowance, price, concession)
|
||
tts.py # the NON-token line — own source, own rounding, EOS/EOL
|
||
model.py # orchestration: CalculatorInputs → CalculatorResult
|
||
sensitivity.py # sweeps + tornado data (no plotting)
|
||
appendix.py # the machine-readable JSON payload
|
||
staging.py # stage/backstage detection (+ backstage_md)
|
||
scripts/export_report.py # execute once → exports/*.html + LLM-ready *.md
|
||
tests/ # rate-card tripwire, hand-checked arithmetic, content pins, staging
|
||
exports/ # generated report sources (never committed)
|
||
```
|
||
|
||
## Run
|
||
|
||
```bash
|
||
python -m venv .venv && source .venv/bin/activate
|
||
pip install -e ".[dev]"
|
||
|
||
mercury --working-dir . # serve the stage (share this screen)
|
||
jupyter lab # analyst view
|
||
pytest # rate card + engine + content + staging pins
|
||
mypy # strict
|
||
jupyter nbconvert --to notebook --execute --inplace notebooks/genesys_token_calculator.ipynb
|
||
python scripts/export_report.py # exports/*.html + *.md for the LLM handoff
|
||
```
|
||
|
||
The `.md` export opens with a generated preamble (what the document is, the
|
||
engagement line, **which rate card produced the numbers**) and ends with the
|
||
**Model state (JSON)** block — the machine source of truth, carrying
|
||
`rate_card.source_date`. A cost figure without its rate-card date is not
|
||
auditable.
|
||
|
||
## Re-anchoring — when Genesys republishes
|
||
|
||
The rate card is a *living* anchor: immutable until the vendor changes it,
|
||
then updated deliberately. Never partially re-anchor, and never bump the date
|
||
without the pins.
|
||
|
||
1. Diff the published table against `genesyscalc/ratecard.py`.
|
||
2. Update the meters **and** `RATE_CARD_SOURCE_DATE` in the same edit.
|
||
3. Update the pins in `tests/test_rate_card.py` in the same commit.
|
||
4. Re-execute the notebook; update the gate's live-state pins if the defaults moved.
|
||
5. Report the cost moves honestly.
|
||
6. **Show-first** — the user sees the rate diff and the KPI move before it lands.
|
||
|
||
`tests/test_rate_card.py` is the tripwire: it pins all 20 rows by exact
|
||
feature wording *and* exact rate string, so a silent transcription drift or an
|
||
un-noticed republication breaks the build rather than quietly moving a
|
||
client-facing number.
|
||
|
||
## Extending
|
||
|
||
New or reshaped catalogue content is an edit to the notebook's `topic-bank`
|
||
cell in JupyterLab, then re-run the notebook (the **gate** recounts the
|
||
catalogue and checks every key against the published meters) and re-pin
|
||
`tests/test_catalogue.py`. New *logic* goes in `genesyscalc/` with pins in
|
||
`tests/`, **before** the notebook section that renders it.
|
||
|
||
## Non-goals
|
||
|
||
- **Not a business case.** No benefits, no NPV, no payback, no ROI, no P&L. If
|
||
a client needs those, that is a **Study** — see [`studies/`](../../studies/).
|
||
A calculator that grows a benefit model has stopped being a calculator.
|
||
- **Not contractual pricing.** A planning model at list rates unless a
|
||
contracted rate is entered. Genesys quotes; this estimates.
|
||
- **Not a platform TCO.** Genesys Cloud CX seat licensing is out of scope —
|
||
this prices the **AI** meters and Enhanced TTS only.
|
||
|
||
**Running this for a client?** Don't fill client data into this master —
|
||
copy the directory out of Palladium, stamp it
|
||
`YYYYMM_Client_Genesys_Token_Calculator`, provision a fresh venv there, fill
|
||
the `engagement-data` cell in the copy, and treat the copy as confidential
|
||
(CLAUDE.md § Confidentiality). A test in this master fails if a client name
|
||
lands in `engagement-data` here.
|