Files
palladium/README.md
Robert Helewka 64fb83257d feat: add GenesysCX study and fix Streamlit chart key collisions
- Add 202512_GenesysCX TEI study (config, seed data, notebooks, README)
  with NPV $10.8M / ROI 266% including AI-token cost line
- Add explicit `key` parameter to all chart wrappers in app/components
  to prevent StreamlitDuplicateElementId errors when the same figure
  type renders across Summary/Benefits/Costs tabs
- Render benefits bar and cost pie charts on their respective tabs
- Add benefits_vs_costs_by_year chart wrapper
2026-06-10 14:26:49 -04:00

450 lines
18 KiB
Markdown
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.
# Palladium
**TEI (Total Economic Impact) Calculator** — The strategic artifact that protects the business case.
Palladium is a Jupyter notebook + Streamlit toolkit for building Total Economic Impact analyses. It connects to [Athena](https://athena.nttdata.com) for data persistence, performs financial calculations (NPV, ROI, payback period), and exports structured data for the report generation pipeline.
> *In Greek mythology, the Palladium was a sacred artifact of Athena that protected Troy. Whoever possessed it held strategic advantage. In our ecosystem, Palladium protects the deal — transforming discovery inputs into a financial case no CFO can ignore.*
## Architecture
```
┌──────────────────────────────────────────────────────────────────┐
│ Palladium │
│ │
│ studies/202602_AmazonConnect/ ← one folder per TEI study │
│ studies/YYYYMM_<Vendor>/ │
│ ├─ notebooks/ ─┐ │
│ ├─ seed_data.py │ │
│ └─ config.py │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ core/ │ ←─ │ app/ │ │
│ │ shared logic │ │ Streamlit │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ ▼ ▼ │
│ tei_client → ───────────────────► Athena API │
│ calculations │
│ export ──────────────────────────► export.json │
│ notebook_helpers │
│ cli │
└──────────────────────────────────────────────────────────────────┘
```
### Components
| Component | Purpose |
|-----------|---------|
| **`core/tei_client`** | Python API client for Athena's TEI endpoints |
| **`core/calculations`** | Financial logic — NPV, ROI, payback, risk adjustment, scenarios |
| **`core/export`** | Builds the structured JSON envelope consumed by the report pipeline |
| **`core/notebook_helpers`** | Pandas tables, Plotly charts, IPython display widgets |
| **`core/cli`** | `python -m palladium` command-line interface |
| **`app/`** | Streamlit data-entry UI with version management — *study-agnostic* |
| **`studies/`** | One folder per TEI engagement (notebooks, seed data, config, source PDF) |
---
## Quick Start — Jupyter Lab first
Palladium is a **Jupyter Lab-first** environment. Everything starts from a
notebook; the Streamlit app and CLI are companions, not prerequisites.
```bash
git clone https://github.com/nttdata/palladium.git
cd palladium
make setup # venv + deps + editable install (one time)
make lab # launches Jupyter Lab
```
Then open **`00_setup.ipynb`** at the repo root. It will:
1. Prompt for your Athena API key (hidden input) and save it to `.env`
2. Test the connection
3. Show what report templates and tools exist in the instance
Current target instance: **https://athena.ouranos.helu.ca** (Ouranos sandbox —
no production data, safe to experiment).
From any notebook, setup is one import:
```python
from core.bootstrap import init
pal = init(study="202602_AmazonConnect") # loads .env, connects, imports study
pal.client.list_reports()
pal.seed_data.BENEFITS
```
### Configuration
All credentials and IDs live in `<repo>/.env` (gitignored). `00_setup.ipynb`
writes it for you; to do it by hand:
```bash
# .env
ATHENA_BASE_URL=https://athena.ouranos.helu.ca
ATHENA_API_KEY=your-api-key-here
# written by the provisioning notebook:
PALLADIUM_REPORT_PUBLIC_ID=...
PALLADIUM_TOOL_PUBLIC_ID=...
PALLADIUM_PROPOSAL_ID=... # or PALLADIUM_ENGAGEMENT_ID — a TEI tool
# attaches to exactly one of the two
```
### Verify Connection
In a notebook: `init()` prints the connection status. From a shell:
```bash
python -m palladium test
```
---
## Usage
### Run a study end-to-end
Each study lives in `studies/<slug>/`. The reference study is the
February 2026 Forrester *Total Economic Impact™ Of Amazon Connect*:
```bash
make lab # then browse to studies/202602_AmazonConnect/notebooks/
```
| Notebook | Purpose |
|----------|---------|
| `00_provision.ipynb` | **Run first** — creates the report template + fields, lets you select the CRM client and the Proposal/Engagement to attach to (pulling the client's profile to avoid re-entry), creates the tool, seeds the published values, calculates, and verifies the totals |
| `01_benefits.ipynb` | Quantify and risk-adjust benefit categories |
| `02_costs.ipynb` | Document implementation and ongoing costs |
| `03_business_case.ipynb` | Financial summary, scenario analysis, visualizations |
| `04_export.ipynb` | Generate report-ready JSON for the html2docx pipeline |
The Amazon Connect notebooks reproduce the published study totals within
rounding: **NPV $78.7M • ROI 342% • Payback <6 months**.
### Streamlit application (study-agnostic)
Interactive UI for data entry and version management. Works for any TEI
study because field definitions come from Athena at runtime:
```bash
streamlit run app/main.py
```
### CLI
```bash
# Test connection
python -m palladium test
# List TEI tool instances
python -m palladium list
# List available report templates
python -m palladium reports
# Show financial summary for a tool
python -m palladium summary <public_id>
# Trigger server-side recalculation
python -m palladium calculate <public_id>
# Export for the report pipeline
python -m palladium export <public_id> -o export.json
```
### Tests
```bash
pytest tests/ -v
```
50 tests cover the API client (mocked HTTP), the financial math, and the
export envelope shape. The Amazon Connect seed data is asserted against
the published Forrester totals.
---
## Adding a new study
```bash
cp -r studies/202602_AmazonConnect studies/202612_GenesysCloud
cd studies/202612_GenesysCloud
```
1. **`README.md`** — update the title, source citation, key numbers.
2. **`seed_data.py`** — replace `BENEFITS` and `COSTS` with the new study's rows.
3. **`config.py`** — set `STUDY_SLUG`, leave `TOOL_PUBLIC_ID` blank until provisioned.
4. **`docs/`** — drop the source PDF here.
5. Open the notebooks; the imports (`core.calculations`, `core.notebook_helpers`,
`core.tei_client`) are study-agnostic. Update the markdown narrative.
The shared `core/` package and the `app/` Streamlit UI need no changes —
they introspect the TEI Report template via the API.
---
## TEI Methodology
Palladium implements the Forrester TEI™ framework.
### Benefit Categories
Benefits are quantified across categories, risk-adjusted, and discounted to present value:
| Category | Examples |
|----------|----------|
| **Cost Savings** | Legacy license elimination, reduced headcount, lower telecom |
| **Productivity** | Reduced handle time, faster training, automated QA |
| **Revenue** | Improved retention, better conversion, new channel revenue |
| **Risk Reduction** | Compliance automation, reduced legal exposure, audit readiness |
### Risk Adjustment
Each benefit carries a risk-adjustment factor (050%) reflecting implementation uncertainty.
A 20% risk adjustment on a $10M benefit yields a risk-adjusted value of $8M.
**Costs** are risk-adjusted **upward** by the same factor (higher risk → higher modelled cost).
### Financial Metrics
| Metric | Description |
|--------|-------------|
| **NPV** | Net Present Value — total risk-adjusted benefits minus costs, discounted |
| **ROI** | Return on Investment — `(benefits costs) / costs × 100` |
| **Payback** | Months until cumulative benefits exceed cumulative costs |
The initial investment (year 0) is **not** discounted. Year-N cashflows are
discounted at the end of the year: `PV = CF_n / (1 + r)^n`. This matches
the Forrester methodology used in the published studies.
### Scenario Analysis
Three scenarios model uncertainty in adoption and realization
(see `core.calculations.SCENARIOS`):
| Scenario | Adoption | Risk delta | Effect |
|----------|----------|------------|--------|
| Conservative | 80% | +10pp on benefits | Lower benefits, higher modelled cost |
| Moderate | 100% | 0 | Base case (= published study) |
| Aggressive | 115% | 5pp on benefits | Higher benefits, lower padding on cost |
---
## Project Structure
```
palladium/
├── 00_setup.ipynb # ← START HERE: credentials + connection
├── Makefile # make setup / lab / app / test
├── core/ # Shared, study-agnostic Python package
│ ├── bootstrap.py # one-import notebook setup (init, save_credentials)
│ ├── tei_client/ # Athena API client
│ │ ├── client.py # TEIClient with all /api/v1/tei/ methods
│ │ └── models.py # Optional dataclasses for typed access
│ ├── calculations/ # Pure-python financial math
│ │ ├── npv.py
│ │ ├── roi.py
│ │ ├── payback.py
│ │ └── scenarios.py
│ ├── export/
│ │ └── report_data.py # JSON envelope for the report pipeline
│ ├── notebook_helpers/
│ │ ├── tables.py # Pandas dataframe builders
│ │ ├── charts.py # Plotly figures
│ │ └── display.py # IPython KPI cards, alerts
│ └── cli/
│ └── main.py # `python -m palladium ...`
├── palladium/ # CLI shim (just exposes `python -m palladium`)
│ └── __main__.py
├── app/ # Streamlit UI — works with any TEI study
│ ├── main.py # entry point
│ ├── views/ # benefits, costs, summary, versions (NOT `pages/` — avoids Streamlit auto-multipage)
│ └── components/ # tables, charts
├── studies/ # One folder per TEI engagement
│ ├── 202512_GenesysCX/ # CX Cloud (Genesys + Salesforce) TEI
│ │ ├── README.md # NPV $10.8M · ROI 266% + AI-token line
│ │ ├── config.py / seed_data.py # study-scoped PALLADIUM_GENESYSCX_* keys
│ │ └── notebooks/ # 00_provision, 01_business_case
│ └── 202602_AmazonConnect/
│ ├── README.md
│ ├── config.py # TOOL_PUBLIC_ID, REPORT_PUBLIC_ID
│ ├── seed_data.py # 5 benefits + 3 costs from the PDF
│ ├── notebooks/
│ │ ├── 00_provision.ipynb # creates template+tool in Athena, seeds & verifies
│ │ ├── 01_benefits.ipynb
│ │ ├── 02_costs.ipynb
│ │ ├── 03_business_case.ipynb
│ │ └── 04_export.ipynb
│ ├── exports/ # generated; .gitignored
│ └── docs/
│ └── 202602_TEI Report Amazon Connect.pdf
├── tests/ # 50 tests for core/
│ ├── test_client.py
│ ├── test_calculations.py
│ └── test_export.py
├── Athena API.yaml # OpenAPI reference
├── .env.example
├── requirements.txt
├── pyproject.toml
└── README.md
```
---
## Athena Integration
Palladium connects to Athena's TEI module for data persistence and cross-tool reporting.
### API Endpoints Used
All endpoints are under `/api/v1/tei/` and require `Authorization: Api-Key {key}`.
| Endpoint | Purpose |
|----------|---------|
| `GET /api/v1/tei/reports/` | List available TEI report templates |
| `GET /api/v1/tei/reports/{public_id}/` | Get a report template |
| `GET /api/v1/tei/reports/{public_id}/fields/` | Get field definitions for a template |
| `POST /api/v1/tei/tools/` | Create a new TEI tool instance |
| `GET /api/v1/tei/tools/{public_id}/` | Get instance metadata |
| `PATCH /api/v1/tei/tools/{public_id}/` | Update name/status |
| `GET /api/v1/tei/tools/{public_id}/values/` | Get current field values |
| `PUT /api/v1/tei/tools/{public_id}/values/` | Bulk-update values |
| `PATCH /api/v1/tei/tools/{public_id}/values/{field_key}/` | Patch a single value |
| `POST /api/v1/tei/tools/{public_id}/calculate/` | Trigger calculation |
| `GET /api/v1/tei/tools/{public_id}/summary/` | Get financial summary |
| `GET /api/v1/tei/tools/{public_id}/versions/` | List version snapshots |
| `POST /api/v1/tei/tools/{public_id}/versions/` | Save a new version |
| `GET /api/v1/tei/tools/{public_id}/versions/{n}/` | Get a specific version |
| `GET /api/v1/tei/tools/{public_id}/export/` | Export for the report pipeline |
| `GET /api/v1/tei/summary/` | Aggregate NPV across all tools |
### Object model
| Athena object | Notes |
|---|---|
| **Opportunity** | Top-level sales record. Owns one or more **Proposals**. |
| **Proposal** | A specific bid/offer to a client. **A TEI tool is linked to a Proposal.** |
| **Engagement** | Optional — for active client engagements. A TEI tool may also link here. |
| **TEIReport** | Template (e.g. *Amazon Connect 2026*) — defines fields, discount rate, analysis horizon. |
| **TEITool** | Instance of a Report bound to a Proposal — holds values, summaries, versions. |
### Authentication
```
Authorization: Api-Key {your-api-key}
```
API keys are provisioned in Athena's admin interface per user/service account.
### Methodology conventions (Palladium ↔ Athena)
Two places where the Forrester methodology and the Athena TEI API differ, and
how Palladium bridges them:
| Topic | Athena behaviour | Palladium convention |
|---|---|---|
| **Cost risk adjustment** | Costs are never risk-adjusted server-side | Cost values are pushed pre-multiplied by `(1 + risk_adj)`; field-level adjustment stays 0 |
| **Year-0 "Initial" costs** | No year-0 concept; non-annual values are folded into Year 1 | Each cost gets a companion non-annual `<key>_initial` field. `TEIClient` folds them back into an `initial` key on read. Athena discounts these as Year 1 (Forrester doesn't discount Year 0) — expect ≈0.15% drift on cost PV |
---
## Report Pipeline Integration
Palladium's export produces structured JSON consumed by the LLM report generation pipeline:
```
Palladium Export (JSON)
Peitho — LLM generates HTML (following HTML_DOCUMENT_FORMAT.md)
html2docx converts to native Word
Professional TEI Report (.docx)
```
The export envelope (`core.export.build_report_data`) includes:
- All benefit categories with risk-adjusted values
- All cost categories with yearly breakdown (and Initial column)
- Financial summary (NPV, ROI, payback, yearly cashflow)
- Conservative / moderate / aggressive scenario analysis
- Metadata (study slug, proposal, engagement, generator stamp)
- The raw Athena `/export/` payload for reference
---
## Version Management
Palladium manages version history through both the API and the Streamlit UI:
1. **Save Version** — Snapshots current values + summary with a descriptive note
2. **View History** — All versions with headline metrics (NPV, ROI)
3. **Compare Versions** — Side-by-side diff of value changes between any two versions
4. **Restore Version** — Load a previous version's values as the current state
Version notes should capture:
- Assumptions made and their sources
- Which scenario the version represents
- What changed since the previous version
- Client confirmations or corrections
---
## Development
### Running Tests
```bash
pytest tests/ -v
```
Tests are designed to run without an Athena connection — HTTP is mocked
and the calculation suite uses the Amazon Connect seed data to verify the
Forrester numbers reproduce within rounding.
### Code Style
```bash
ruff check .
ruff format .
```
### Adding a New Benefit Category
1. Define the field in Athena's TEI Report admin (field name, type, category, defaults)
2. The field automatically appears in Palladium via the API — no client changes
3. Update notebook prose if category-specific commentary is needed
4. If the report template exposes a new structure, extend the envelope in
`core/export/report_data.py`
---
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| `requests` | ≥2.31 | HTTP client for Athena API |
| `python-dotenv` | ≥1.0 | Environment configuration |
| `jupyter` | ≥1.0 | Notebook environment |
| `streamlit` | ≥1.30 | Data entry application |
| `pandas` | ≥2.0 | Data manipulation |
| `plotly` | ≥5.18 | Interactive visualizations |
| `numpy` | ≥1.26 | Financial calculations |
| `pytest` | ≥7.4 | Testing |
| `ruff` | ≥0.1 | Linting and formatting |
---
## Related Projects
| Project | Relationship |
|---------|-------------|
| **Athena** | Platform API — data persistence, cross-tool reporting |
| **Peitho** | Document generation — consumes Palladium's export JSON |
| **html2docx** | Converts LLM-generated HTML to native Word documents |