A Python-based, AI-enabled actuarial experience-study demo for life insurance
(Term, Whole Life, UL/ULSG/IUL, VUL, Deferred Annuities): A/E results with
credibility, year-on-year movement + driver attribution + trend classification,
rule-based claims fraud screening, AI-proposed assumption factors, a
governed AI analyst, and a multi-level assumption sign-off workflow with
tamper-evident audit. See CLAUDE.md,
docs/demo_refresh_scope.md and
docs/demo_walkthrough.md (the scripted 20–30 min
demo) for full detail.
New here? Start with the User Guide — how to install, run, log in (the four governance roles), and clean/reset the database.
License. Source-available, view-only — all rights reserved. The code is
shared for viewing, evaluation, and reference only; no reuse, modification, or
redistribution without written permission. See LICENSE. All data is
synthetic; default login credentials are illustrative prototype values only.
Dependencies are pinned in requirements.lock, compiled
from requirements.in. Builds install from the lockfile
only (FR-3A-04):
# with uv (recommended)
uv pip sync requirements.lock
# or with pip
pip install --no-deps --require-hashes -r requirements.lockRegenerate the lockfile after changing requirements.in (e.g. when later
sessions add the ML/LLM stack — xgboost, shap, statsmodels, anthropic, openai,
mcp):
uv pip compile requirements.in -o requirements.lock --generate-hashesThe regression gate runs with no LLM API keys in the environment (MockProvider posture; NFR-T-06):
pytest tests/ -v --tb=shortTest artifacts are confined to tests/_artifacts/ (gitignored, NFR-T-01) and
are removed automatically on a successful run. To retain them, pass
--keep-artifacts. To clean up manually (NFR-T-07):
rm -rf tests/_artifactsThe AI layer lives under src/ai/ and is strictly additive: the core
engine never imports from it, and it reads only the Gold layer and writes only
to data/ai_models/ and the AI Gold tables. All AI SQL passes through the
hardened boundary in src/utils/sql_boundary.py.
See src/ai/__init__.py for the enforced contracts.
The runtime AI features — the drafting Skills (A/E memo, SHAP explanation, fraud narrative, management commentary) and the AI Analyst chatbot — call a language-model provider. API keys are read from environment variables only (FR-3B-04): a key is never stored in YAML, on disk, in logs, or in the audit trail. That is why there is intentionally no API-key field in the UI — set the key in your shell before launching the app.
Each provider's key un-greys that provider's models in the model dropdowns:
| Environment variable | Un-greys |
|---|---|
ANTHROPIC_API_KEY |
Claude Opus 4.8, Claude Sonnet 4.6 |
DEEPSEEK_API_KEY |
DeepSeek V4 Pro, DeepSeek V4 Flash |
Set the key(s) you have, then launch Streamlit:
export ANTHROPIC_API_KEY=sk-ant-... # un-greys the two Claude models
export DEEPSEEK_API_KEY=sk-... # un-greys the two DeepSeek models
streamlit run ui/app.pyYou only need one provider's key to use that provider's models; the other simply stays greyed. With a key set, the matching models change from greyed ("— API key not configured") to selectable and the Skill / AI Analyst draft buttons work.
Notes:
- A greyed model in a dropdown means its key is unset. Set the env var and
relaunch rather than selecting the greyed model and clicking (doing so just
surfaces
API key not configured for provider '...'). - The two Skills default to different providers, so with no keys set Draft A/E
memo reports
ANTHROPIC_API_KEYand Explain SHAP results reportsDEEPSEEK_API_KEY— both are the same "key not configured" condition. - Keys live only in the process/shell environment for that run; the app persists nothing. The regression suite is unaffected — it runs with no keys by design (NFR-T-06).