How it works · Data flow & architecture
From source data to AI-grounded board narrative — under 300ms per page
End-to-end flow · 4 layers
Seed data → Models → AI service → Templates. Caching at every boundary keeps real-time pages cheap to render.
01 · Source data
What the system knows
seed_data.py— segments, customers, plants, competitors, PESTLE, ESG, levers (~ 2,500 lines, illustrative)ad.db— SQLite cache for AI responses (per-context, hashed key, TTL)- Live DDGS news feed — 12 categories searched, 6h per-category cache
→
02 · Domain models
models.py — typed accessors
get_company·get_horizons·get_povget_top_customers·list_competitors·get_plantsget_growth_geos·get_ebitda_bridge·get_margin_leversget_ai_cache·set_ai_cache— SQLite read/write
→
03 · AI service
ai_service.py — Azure OpenAI orchestration
chat_persona· per-CXO multi-turn dialog (GPT-4o)insights_actions(context)· 360-page insights + RACI actionsexternal_news_ticker· DDGS search → AI impact taggingtranscribe_audio·synthesize_speech· Whisper + TTSweekly_insights·follow_up_questions·analyst_qa_prep
→
04 · Presentation
Flask templates + JS
base.html· 3-tier sidebar, news ticker, copilot drawer- 11 × 360 templates (Customer / Competition / Growth / EBITDA / …)
- Chart.js — bar, line, doughnut, radar, bubble, sparkline
- Leaflet — 8 world maps with circle markers + popups
Each layer is independently cacheable; AI responses are keyed by SHA-256 of inputs so identical requests return without an Azure call.
Coverage · AVY lines of business
All 7 product lines surfaced in Business 360 · 11 × 360 lenses cut across them all
| Segment | Product line | FY25 rev | Op margin | Where to drill |
|---|---|---|---|---|
| Materials Group · $6.62B | Label & Graphic Materials | $5.4B | 14.5% | Business 360 · Profitability 360 |
| Performance Tapes | $0.9B | 15.2% | Business 360 | |
| Vancive Medical | $0.3B | 18.0% | Business 360 | |
| Solutions Group · $2.24B | Intelligent Labels (RFID) | $1.4B | 11.0% | Growth 360 · Customer 360 |
| atma.io platform | $0.12B | 28% | Markets 360 · Profitability 360 | |
| Apparel branding & embellishments | $0.7B | 6.0% | Customer 360 | |
| DPPaaS · Burton lighthouse | $0.02B | 35% | External 360 · ESG 360 |
Estimates triangulated from AVY 10-K + segment disclosures.
API surface · 18 endpoints
JSON-first APIs power both the page templates and the live copilot
| Endpoint | Method | What it does |
|---|---|---|
/api/chat/<persona> | POST | Persona-conditioned chat turn (GPT-4o · multi-turn) |
/api/chat/<persona>/history | GET | Session-scoped conversation history |
/api/chat/<persona>/clear | POST | Reset the persona conversation |
/api/chat/<persona>/followups | POST | 3 AI-generated follow-up prompts after each reply |
/api/stt | POST | Audio → text (Azure OpenAI Whisper) |
/api/tts | POST | Text → MP3 (Azure OpenAI TTS, 6 voices) |
/api/news-ticker | GET | DDGS news fan-out · 12 categories · AI-tagged impact |
/api/insights-actions/<context> | GET | 3 insights + 3 actions for a 360 context |
/api/ask | POST | Single-turn context-aware Q&A |
/api/explain/<initiative> | POST | Drivers + risks for an initiative |
/api/scenario/<code>/run | POST | Run a scenario with lever values |
/api/drill/<key> | GET | Drill-down content for any tagged element |
/api/compare | POST | Compare any two entities (initiative · competitor · persona) |
/api/qa-prep | POST | Analyst-grade Q&A preparation for any topic |
/api/health | GET | Service health + AI configuration status |
All endpoints return JSON · all AI responses cached by SHA-256 of inputs in
ad.db.Voice loop · how the copilot listens and speaks
Browser captures audio → server transcribes → GPT-4o answers → server synthesizes → browser plays — all over Azure OpenAI
1
Mic press → MediaRecorder
Browser captures a WebM/Opus blob
↓
2
POST /api/stt
ai_service.transcribe_audio → Azure OpenAI Whisper deployment → text↓
3
POST /api/chat/<persona>
chat_persona · system prompt = persona role · GPT-4o · session history↓
4
Render bubble + auto-speak
Render in drawer; if auto-speak ON → POST /api/tts → MP3 → <audio>
↓
5
POST /api/chat/<persona>/followups
3 dynamic suggested next questions appear as chips
Set
AZURE_OPENAI_DEPLOYMENT_WHISPER and AZURE_OPENAI_DEPLOYMENT_TTS to your Azure deployment names to enable voice.Caching strategy · why pages stay snappy
Three TTLs · keyed by SHA-256 of inputs · same input never costs a second Azure call
| Cache | TTL | Key inputs | Why |
|---|---|---|---|
| AI response cache (SQLite) | Indefinite | kind + payload SHA-256 | Same prompt + same data ⇒ identical answer; no need to re-bill Azure. |
| News-ticker · per-category | 6 hours | category + 6h bucket | Survives DDG rate limits; ticker always renders even if 4/12 categories 429. |
| News-ticker · full payload | 30 minutes | 30-min bucket | Shared across all users; refresh button busts the bucket on demand. |
| Insights & actions | Indefinite | context name | Per-360 view; ↻ button on the card busts cache and re-asks GPT-4o. |
| Follow-up prompts | Indefinite | persona + last-Q + last-A SHA-256 | Same conversational state ⇒ same follow-ups. |
What's next · a working plan
Beyond illustrative data — wire to real systems
- Replace seed_data.py with live ERP/CRM feeds — SAP, Oracle, Salesforce; refresh nightly.
- Add row-level security per persona — board sees the lot; line GMs see their slice.
- Streaming chat — server-side events from Azure OpenAI so replies render token-by-token.
- Real-time scenario engine — push lever changes into the live financial model, not a static waterfall.
- Production observability — track AI cost-per-page, cache-hit rate, model latency p50/p95.