Add configurable locale/display formatting environment variables (`PALLADIUM_CURRENCY_SYMBOL`, `PALLADIUM_THOUSANDS_SEP`, `PALLADIUM_DECIMAL_SEP`) to support regional number formatting in the Streamlit app. Update `.env.example` with documentation for these new variables. Also refresh `00_setup.ipynb` with current execution outputs reflecting a live Athena connection with report templates, a selected client (Global Guardian Insurance, ID=2), and resolved NameError in assumption override cells.
446 lines
18 KiB
Markdown
446 lines
18 KiB
Markdown
# 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 (0–50%) 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
|
||
│ └── 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 |
|