Files
palladium/calculators/Genesys_Token_Calculator/genesyscalc/appendix.py

127 lines
5.0 KiB
Python

"""The machine-readable model state (Mercury Notebook Pattern §5).
Plotly figures export as JavaScript an LLM cannot read, so the exported
``.md`` ends with one JSON block carrying everything the figures showed.
``rate_card.source_date`` is the most important field here: it tells a
consumer of the export *which* published rate card produced these numbers.
A cost figure without its rate-card date is not auditable.
"""
from __future__ import annotations
from typing import Any
from .model import CalculatorInputs, CalculatorResult, cost_per_interaction
from .ratecard import (
RATE_CARD_SOURCE,
RATE_CARD_SOURCE_DATE,
VOICE_BOT_ROUNDUP_SECONDS,
)
from .tts import TTS_SOURCE, TTS_SOURCE_DATE
def result_json(
result: CalculatorResult,
inputs: CalculatorInputs,
meta: dict[str, Any] | None = None,
) -> dict[str, Any]:
"""The export payload: provenance, inputs, lines, totals, warnings."""
totals = result.totals
payload: dict[str, Any] = {
"rate_card": {
"source": RATE_CARD_SOURCE,
"source_date": RATE_CARD_SOURCE_DATE,
"voice_bot_roundup_seconds": VOICE_BOT_ROUNDUP_SECONDS,
},
"tts_source": {"source": TTS_SOURCE, "source_date": TTS_SOURCE_DATE},
"inputs": {
"users": inputs.users,
"licence_model": inputs.licence.value,
"enabled_features": sorted(inputs.enabled),
"apply_allowance": inputs.apply_allowance,
"volumes": {
k: v for k, v in vars(inputs.volumes).items() if not k.startswith("_")
},
"deflection_mix": {
"bot_only_share": inputs.mix.bot_only_share,
"virtual_agent_share": inputs.mix.virtual_agent_share,
"agentic_va_share": inputs.mix.agentic_va_share,
"agent_handled_share": inputs.mix.agent_handled_share,
},
"price": {
"currency": inputs.price.currency,
"list_rate": inputs.price.list_rate,
"contracted_rate": inputs.price.contracted_rate,
"concession_pct": inputs.price.concession_pct,
"effective_rate": inputs.price.effective_rate(),
},
"voice_bot": (
{
"calls_per_month": inputs.voice_bot.calls_per_month,
"avg_bot_seconds_per_call": (
inputs.voice_bot.avg_bot_seconds_per_call
),
}
if inputs.voice_bot is not None
else None
),
"tts": (
{
"calls_monthly": inputs.tts.calls_monthly,
"chars_per_call": inputs.tts.chars_per_call,
"tier": inputs.tts.tier,
}
if inputs.tts is not None
else None
),
},
"lines": [
{
"key": line.key,
"feature": line.feature,
"units_monthly": line.units_monthly,
"unit_label": line.unit_label,
"tokens_monthly": line.tokens_monthly,
"cost_monthly": line.cost_monthly,
"cost_annual": line.cost_annual,
"confidence": line.confidence.value,
}
for line in result.lines
],
"totals": {
"consumption_tokens_monthly": totals.consumption_tokens_monthly,
"subscription_tokens_monthly": totals.subscription_tokens_monthly,
"gross_tokens_monthly": totals.gross_tokens_monthly,
"allowance_tokens_monthly": totals.allowance_tokens_monthly,
"billable_tokens_monthly": totals.billable_tokens_monthly,
"currency": totals.currency,
"effective_rate": totals.effective_rate,
"token_cost_monthly": totals.token_cost_monthly,
"token_cost_annual": totals.token_cost_annual,
"list_cost_annual": totals.list_cost_annual,
"concession_saving_annual": totals.concession_saving_annual,
"tts_cost_annual": result.tts_cost_annual,
"grand_total_annual": result.grand_total_annual,
"cost_per_interaction": cost_per_interaction(result, inputs.volumes),
},
"tts": (
{
"tier": result.tts.tier,
"rate_per_million_chars": result.tts.rate_per_million_chars,
"total_chars_monthly": result.tts.total_chars_monthly,
"free_share": result.tts.free_share,
"billable_chars_monthly": result.tts.billable_chars_monthly,
"billed_millions_monthly": result.tts.billed_millions_monthly,
"cost_monthly": result.tts.cost_monthly,
"cost_annual": result.tts.cost_annual,
}
if result.tts is not None
else None
),
"warnings": list(result.warnings),
}
if meta:
payload["meta"] = meta
return payload