Skip to content

Repository files navigation

Energy Supply Chain — Resilience Platform

An AI-driven energy supply chain resilience platform that transforms real-time geopolitical signals into probability-weighted disruption risk assessments, scenario simulations, optimal procurement re-allocations, and strategic reserve drawdown decisions — scoped specifically to India's crude oil import dependency.

Energy Supply Chain Resilience Platform — Risk Map

Table of Contents

# Section
1 Overview
2 Judging Criteria Alignment
3 Problem & Solution
4 Deliverables
5 Technology Stack
6 System Architecture
7 Key Features
8 Quick Start
9 Development Setup
10 API Documentation
11 Project Structure
12 Environment Variables
13 Performance Specifications
14 Design Principles
15 Limitations & Honest Scope

Overview

Energy Supply Chain Resilience Platform is a full-stack, 5-component system that provides end-to-end decision support for India's crude oil supply chain under geopolitical disruption. It ingests multi-source signals (GDELT, NewsAPI, sanctions data, crude price feeds), processes them through a dual-LLM causal reasoning pipeline, simulates disruption scenarios with Monte Carlo uncertainty bands, re-optimizes procurement allocations using CP-SAT constraint programming, and computes optimal Strategic Petroleum Reserve (SPR) drawdown decisions using a Teisberg-derived cost optimizer.

5 Integrated Components:

# Component Purpose
1 Risk Intelligence Agent Ingest signals → extract events → causal reasoning → probability-weighted risk assessments
2 Disruption Scenario Modeller Template-driven cascade simulations with Monte Carlo p10/p50/p90 bands
3 Adaptive Procurement Orchestrator CP-SAT optimizer for cost-minimized crude allocation under disrupted capacity
4 Strategic Reserve Optimizer Teisberg-derived SPR drawdown with scenario-tree probability bridge
5 Operations Dashboard Real-time visualization, explainability drill-down, and interactive map

The platform is grounded in India's actual crude oil import structure — real corridors (Strait of Hormuz, Red Sea/Bab-el-Mandeb, Cape of Good Hope, Suez Canal), real suppliers (Iraq, Saudi Arabia, Russia, UAE, USA, Nigeria), real refineries (Reliance Jamnagar, Nayara Vadinar, BPCL Kochi, IOCL Panipat, HPCL Vizag), and real SPR sites (Visakhapatnam, Mangalore, Padur).

Judging Criteria Alignment

Submission: ET AI Hackathon 2026 — Problem Statement 2: AI-Driven Energy Supply Chain Resilience for Import-Dependent Economies

Criterion (Weight) How We Address It README Section
Innovation (25%) Dual-LLM causal reasoning pipeline (not sentiment classification), Teisberg-derived reserve optimizer with scenario-tree probability bridge, CP-SAT procurement solver with piecewise demand penalties, Monte Carlo uncertainty bands on all scenario outputs Key Features, Design Principles
Business Impact (25%) End-to-end signal→recommendation in <35s (closes McKinsey's 47-day stabilization gap), executable procurement re-allocations with demand fulfillment % and cost scoring, SPR drawdown recommendations with physical constraint enforcement Problem & Solution, Evaluation Focus
Technical Excellence (20%) Schema-validated LLM outputs via instructor+Pydantic v2, Neo4j knowledge graph with India-specific entity relationships, Qdrant vector store for policy corpus grounding, Langfuse end-to-end LLM observability, immutable snapshot architecture (branch, never mutate) Technology Stack, System Architecture
Scalability (15%) Docker Compose 4-service orchestration, stateless API design, unlimited snapshot history via append-only tables, extensible knowledge graph (24 nodes → national scale) Scalability
User Experience (15%) 5-page operations dashboard with keep-alive state preservation, interactive Leaflet map with live risk overlays across 4 corridors, full explainability drill-down (raw signal → extracted event → reasoning → scenarios), one-click scenario simulation with Monte Carlo visualization Key Features — Dashboard

Problem & Solution

The Challenge: Energy Supply Chain Resilience Under Geopolitical Disruption

Context & Problem: India sources approximately 88% of its crude oil from imports, with 40–45% of that volume transiting through the Strait of Hormuz — a structural vulnerability that geopolitical events repeatedly stress-test. The 2025 US-Iran standoff sent Brent crude up over 8% in a single session and forced Indian refiners onto spot markets at steep premiums; through early 2026, renewed US sanctions pressure on Iranian oil exports, Persian Gulf maritime incidents, and escalating Houthi attacks on Red Sea shipping lanes have kept the supply threat live. India's Strategic Petroleum Reserves provide roughly 9.5 days of national consumption cover — a buffer that would be exhausted quickly in any sustained disruption. A McKinsey analysis of past energy supply shocks found that economies without automated rerouting and demand-management capability took an average of 47 days longer to stabilise supply than those with integrated response intelligence. Today, analysts manually monitor news feeds, run ad-hoc spreadsheet models, and make reactive procurement decisions with incomplete information. Traditional supply chain planning tools were designed for predictable environments — they have no ability to model geopolitical scenario impacts in real time, dynamically evaluate alternative procurement corridors, or orchestrate coordinated response across refiners, logistics providers, and strategic reserves. That intelligence layer is what this platform builds.

Goal of the System: Provide an integrated, AI-powered decision support platform that:

  • Continuously ingests and reasons about geopolitical signals with full causal traceability
  • Simulates "what-if" disruption scenarios with transparent, formula-based cascade models
  • Automatically re-optimizes procurement allocations under disrupted conditions
  • Recommends optimal strategic reserve drawdown with stochastic cost minimization

Decision Flow — From Signal to Action

Step 1 — Signal Ingestion & Risk Assessment (Component 1)

  • Trigger: Geopolitical event occurs (sanctions announcement, military action, price shock)
  • Action: Multi-source ingestion (GDELT, NewsAPI, sanctions snapshots, price feeds) → LLM-powered event extraction → causal reasoning chain
  • System Response: Probability-weighted disruption risk per corridor with full explainability trace (raw signal → extracted event → reasoning → scenarios)

Step 2 — Scenario Simulation (Component 2)

  • Trigger: Analyst selects a disruption template (contained, partial disruption, or full closure)
  • Action: Deterministic cascade formula computes refinery run-rate impact, price delta, and SPR drawdown — Monte Carlo wrapper adds p10/p50/p90 uncertainty bands
  • System Response: Side-by-side scenario comparison with explicit, inspectable assumptions

Scenario Explorer — Template Selection & Run History

Step 3 — Procurement Re-Optimization (Component 3)

  • Trigger: Scenario reveals capacity reduction on a corridor
  • Action: CP-SAT optimizer re-allocates crude flows across suppliers, corridors, and refineries — minimizing cost while respecting disrupted capacity constraints
  • System Response: Optimal allocation plan with demand fulfillment %, cost score, and per-refinery breakdown

Procurement Allocation — CP-SAT Optimizer Results

Step 4 — Reserve Drawdown Decision (Component 4)

  • Trigger: Procurement solve reveals unmet demand (shortfall)
  • Action: Teisberg-derived optimizer balances immediate shortfall coverage against future stockout risk using scenario-tree probabilities
  • System Response: Optimal drawdown percentage, barrels released, days of cover remaining, and physical constraint binding status

Reserve Optimizer — SPR Drawdown Decision

Example Use Case

An analyst monitoring the Strait of Hormuz sees a new Iranian sanctions signal ingested at 65% disruption probability. They run a "full_closure" scenario simulation showing a 48.8% capacity reduction, $24.16/bbl price spike, and 2.55 SPR days remaining. The procurement solver re-allocates 1.2M bpd away from Hormuz-dependent suppliers toward Russia and Nigeria via Cape of Good Hope, achieving 94% demand fulfillment at $11.28/bbl average cost. The reserve optimizer recommends a 3.2% SPR drawdown (1.22M barrels) to cover the remaining shortfall while preserving 8.1 days of strategic cover.

Evaluation Focus — How We Measure Up

The five evaluation metrics specified for Problem Statement 2, mapped to our system's demonstrated capabilities:

Evaluation Metric Our Evidence Source
Disruption signal detection lead time and accuracy Full pipeline (ingest → extract → reason) completes in <30s; dual-LLM chain with instructor + Pydantic v2 ensures schema-validated extraction accuracy; Langfuse traces provide per-signal audit trail Performance Specs
Quality and executability of procurement alternatives CP-SAT optimizer produces allocation[supplier][corridor][refinery] with demand_fulfillment_pct, cost_score, and weighted_score; piecewise demand penalties guarantee a complete, gracefully-degraded plan is always returned — never a bare "no solution" failure C3 Features
Scenario model fidelity (assumptions explicit and testable) Every cascade parameter (refinery_runrate_sensitivity, price_passthrough_rate, spr_drawdown_rate) is named, sourced (PPAC FY24, MSCI benchmarks), and exposed in assumptions_json; Monte Carlo adds p10/p50/p90 uncertainty bands with triangular distribution over ±15% perturbation C2 Features
Geospatial evidence depth Leaflet map with 4 corridor routes, 6 supplier terminals, 5 refineries, 3 SPR sites, color-coded risk overlays with live disruption probability labels; Neo4j knowledge graph encodes Supplier→Corridor→Port→Refinery→SPR entity relationships with real PPAC import-share data C5 Features
End-to-end response time from signal to recommendation Signal ingestion <30s + scenario simulation <200ms + procurement solve <2s + reserve optimization <50ms = under 35 seconds from raw signal to actionable, executable recommendation Performance Specs

Deliverables

# Deliverable Status
1 Working Prototype Run locally via docker compose up + npm run dev — see Quick Start
2 Architecture Diagram System Architecture (in this README)
3 Presentation Deck Included as et.pptx in the repository root
4 Demo Video [ADD LINK]

Technology Stack

Component Technology Purpose
Frontend React 19 + Vite 8 + TypeScript Interactive operations dashboard
Mapping Leaflet + React-Leaflet Geospatial corridor & infrastructure visualization
Charts Recharts Monte Carlo bands, scenario comparison, allocation charts
Icons Lucide React Consistent iconography across all views
Backend Python FastAPI REST API, pipeline orchestration, all 4 backend components
LLM Google Gemini 2.5 Flash Event extraction (Call #1) + causal reasoning (Call #2)
Structured Output instructor + Pydantic v2 Schema-validated LLM responses, no manual JSON parsing
Knowledge Graph Neo4j Community Edition India-specific supply chain entity graph
Vector Store Qdrant Semantic retrieval for policy corpus grounding
Relational DB PostgreSQL 16 Signals, events, assessments, scenarios, solves, decisions
Constraint Solver Google OR-Tools CP-SAT Procurement allocation optimization
Reserve Optimizer Grid search (Teisberg model) SPR drawdown cost minimization
Observability Langfuse Cloud End-to-end LLM trace observability
Containerization Docker Compose 4-service orchestration (Neo4j, Qdrant, Postgres, API)

Component Architecture Mapping

Component Backend Module Dashboard Page Core Algorithm
C1 — Risk Intelligence ingestion/, extraction/, reasoning/ Risk Map, Explainability Dual-LLM causal chain
C2 — Scenario Modeller scenarios/ Scenario Explorer Cascade formula + Monte Carlo
C3 — Procurement procurement/ Procurement Allocation CP-SAT flow optimization
C4 — Reserve reserve/ Reserve Optimizer Teisberg expected-cost grid search
C5 — Dashboard All 5 pages React + Leaflet + Recharts

System Architecture

End-to-End Pipeline

┌──────────────────────────────────────────────────────────────────────────────────┐
│                        COMPONENT 1: Risk Intelligence Agent                      │
│                                                                                  │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌──────────┐                           │
│  │  GDELT  │  │ NewsAPI │  │ Price   │  │Sanctions │    Multi-Source Ingestion   │
│  │   API   │  │  / RSS  │  │  Feed   │  │ Snapshot │                            │
│  └────┬────┘  └────┬────┘  └────┬────┘  └────┬─────┘                           │
│       └────────────┼───────────┼────────────┘                                   │
│                    ▼                                                              │
│         ┌──────────────────┐      ┌──────────────────┐                          │
│         │   LLM Call #1    │      │   Context Assembly │                         │
│         │ Event Extraction │      │  Neo4j + Qdrant   │                         │
│         │ (Gemini 2.5)     │      │  + Extracted Event │                        │
│         └────────┬─────────┘      └────────┬──────────┘                         │
│                  └──────────┬──────────────┘                                     │
│                             ▼                                                    │
│                  ┌──────────────────┐                                            │
│                  │   LLM Call #2    │──→  Langfuse Traces                        │
│                  │ Causal Reasoning │                                            │
│                  │ (Gemini 2.5)     │                                            │
│                  └────────┬─────────┘                                            │
│                           ▼                                                      │
│              Risk Assessments (per corridor)                                     │
│              • disruption_probability                                            │
│              • capacity_reduction_pct                                            │
│              • 2-4 named scenarios                                               │
└──────────────────────────┬───────────────────────────────────────────────────────┘
                           ▼
┌──────────────────────────────────────────────────────────────────────────────────┐
│                    COMPONENT 2: Disruption Scenario Modeller                     │
│                                                                                  │
│  Template Selection → Cascade Formula → Monte Carlo (2000 iterations)           │
│                                                                                  │
│  Outputs per scenario run:                                                       │
│  • Refinery run-rate impact (%)    — p10 / p50 / p90                            │
│  • Price delta (USD/bbl)           — p10 / p50 / p90                            │
│  • SPR days remaining              — p10 / p50 / p90                            │
│  • Optional LLM narrative                                                        │
└──────────────────────────┬───────────────────────────────────────────────────────┘
                           ▼
┌──────────────────────────────────────────────────────────────────────────────────┐
│                 COMPONENT 3: Adaptive Procurement Orchestrator                   │
│                                                                                  │
│  CP-SAT Optimizer: minimize(cost + shortfall_penalty + stability_penalty)        │
│                                                                                  │
│  Decision variables: allocation[supplier][corridor][refinery] = quantity_bpd     │
│  Subject to: disrupted corridor capacity, refinery demand, grade compatibility   │
│                                                                                  │
│  Outputs: optimal allocation, demand_fulfillment_pct, cost_score, solve_score    │
└──────────────────────────┬───────────────────────────────────────────────────────┘
                           ▼
┌──────────────────────────────────────────────────────────────────────────────────┐
│                  COMPONENT 4: Strategic Reserve Optimization Agent               │
│                                                                                  │
│  Teisberg Cost Model: min[ shortfall_cost(d) + expected_stockout_cost(d) ]      │
│                                                                                  │
│  Grid search at 0.5% increments over scenario-tree probability branches          │
│  Physical constraint: max 150,000 bpd extraction rate                            │
│                                                                                  │
│  Outputs: optimal_drawdown_pct, drawdown_bbl, reserve_after_drawdown,           │
│           cost_breakdown, scenario_branches with drain_fractions                  │
└──────────────────────────────────────────────────────────────────────────────────┘

India-Specific Knowledge Graph

(Supplier) ──[EXPORTS_VIA]──→ (Corridor) ──[ROUTES_TO]──→ (Port) ──[SUPPLIES]──→ (Refinery) ──[FEEDS_RESERVE]──→ (SPRSite)

Seeded entities:

  • Corridors (4): Strait of Hormuz, Red Sea/Bab-el-Mandeb, Cape of Good Hope, Suez Canal
  • Suppliers (6): Iraq (22.5%), Saudi Arabia (17.8%), UAE (7.2%), Russia (35%), USA (5.5%), Nigeria (3.8%)
  • Ports (6): Vadinar, Sikka, Paradip, JNPT Mumbai, Chennai, Kochi
  • Refineries (5): Reliance Jamnagar (1.24M bpd), Nayara Vadinar (400K), BPCL Kochi (310K), IOCL Panipat (300K), HPCL Vizag (166K)
  • SPR Sites (3): Visakhapatnam (10M bbl), Mangalore (11M bbl), Padur (17M bbl) — Total: 38M bbl, ~9.5 days cover

Key Features

Component 1 — Risk Intelligence Agent

Multi-Source Signal Ingestion

  • GDELT API: Real-time geopolitical event monitoring with relevance filtering
  • NewsAPI + RSS: Energy-sector news aggregation from curated feeds
  • Price Data: Brent crude spot price via Alpha Vantage
  • Sanctions Snapshots: OFAC-style sanctions event loader for embargo/sanctions scenarios

Dual-LLM Causal Reasoning

  • LLM Call #1 (Event Extraction): Gemini 2.5 Flash + instructor extracts structured event objects (actor, event type, severity, confidence, affected suppliers) from raw signals
  • LLM Call #2 (Causal Reasoning): Assembles context from Neo4j knowledge graph + Qdrant policy corpus + extracted event → produces probability-weighted corridor risk assessment with 2–4 named scenarios
  • Full Explainability: Every output traceable from raw source → extracted event → reasoning chain → final assessment

India-Specific Grounding

  • All entities, prompts, and corpora scoped to India's actual import structure
  • Policy corpus includes synthetic-representative documents mirroring OFAC notices, PPAC statistics, and IEA supply analyses
  • Knowledge graph encodes real supplier–corridor–port–refinery–SPR relationships

Component 2 — Disruption Scenario Modeller

Transparent Cascade Formula

  • No black-box ML — every number traceable to an explicit formula with named assumptions
  • 3 downstream metrics: refinery run-rate impact (%), price delta (USD/bbl), SPR days remaining
  • 12 seed templates: 3 severity levels (contained, partial_disruption, full_closure) × 4 corridors
  • Assumption parameters: sourced from PPAC FY24 data, MSCI corridor benchmarks, and documented illustrative estimates

Monte Carlo Uncertainty Bands

  • 2000 iterations per run (~50ms) with triangular distribution
  • ±15% perturbation on assumption parameters
  • p10/p50/p90 output for each metric (optimistic/central/pessimistic)
  • Immutable snapshot architecture: every run creates a new row — rows are never updated (branch, never mutate)

Optional LLM Narrative

  • Gemini-generated plain-English summary of scenario results
  • Key driver identification and caveat disclosure

Component 3 — Adaptive Procurement Orchestrator

CP-SAT Constraint Optimization

  • Decision variables: allocation[supplier][corridor][refinery] = quantity_bpd
  • Objective: minimize total cost + piecewise demand shortfall penalties + stability deviation
  • Piecewise demand: Tier 1 (0–30% shortfall, moderate penalty) + Tier 2 (>30%, 5× escalation) + miss penalty (extreme)
  • Always returns a plan: gracefully-degraded allocation, never a bare "no solution" failure

Base-Plan Stability

  • When base_plan_solve_id provided, solver penalizes large deviations from prior allocation
  • Supports meaningful scenario-to-scenario comparison with minimal, targeted changes

Post-Solve Scoring

  • demand_fulfillment_pct: volume-weighted supply coverage
  • cost_score: average delivered cost vs. worst-case unit cost
  • miss_penalty_ratio: fraction of refineries receiving zero supply
  • weighted_score: 50% fulfillment + 30% cost + 20% miss avoidance

Component 4 — Strategic Reserve Optimization Agent

Teisberg-Derived Cost Optimizer

  • Cost function: total_cost(d) = immediate_shortfall_cost + expected_stockout_cost
  • Quadratic stockout penalty: creates convex cost curve with interior optimum — the key advantage over naive threshold rules
  • Grid search: 0.5% increments, ~200 evaluations, sub-millisecond solve time

Probability Bridge

  • Component 1's LLM-generated scenarios matched to Component 2's fixed severity templates via severity-range matching (not name-string matching)
  • Stochastic scenario-tree with probability-weighted branches feeds the expected stockout cost

Physical Constraints

  • Max SPR extraction rate: 150,000 bpd (US SPR benchmark × 60% rock-cavern discount)
  • Reserve state: stateless by default (assumes full 38M bbl), explicit override supported for chained depletion analysis

Component 5 — Operations Dashboard

Interactive Risk Map

  • Leaflet-based geospatial view with corridor routes, chokepoint markers, supplier terminals, refineries, and SPR sites
  • Real-time risk overlay: color-coded corridors (green/amber/red) with disruption probability labels
  • Corridor cards: live disruption %, capacity cut %, baseline capacity, supplier badges

Scenario Explorer

  • Run disruption simulations with template selection (contained, partial_disruption, full_closure)
  • View point estimates and Monte Carlo p10/p50/p90 bands
  • Full run history with side-by-side comparison
  • Optional narrative generation toggle

Procurement Allocation

  • Select any scenario run → solve optimal procurement allocation
  • Per-refinery demand fulfillment breakdown with cost metrics
  • Solve scoring with transparent formula display

Reserve Optimizer

  • SPR status display (total capacity, fill level, extraction rates)
  • Optimal drawdown recommendation with cost breakdown
  • Scenario-tree probability branches visualization

Explainability Drill-Down

  • 4-step pipeline view: Raw Signal → Extracted Event → Causal Reasoning → Risk Scenarios
  • Full causal chain for each corridor with Langfuse trace ID
  • Expandable raw signal content with source attribution

Explainability View — 4-Step Causal Chain

Quick Start

Prerequisites

  • Docker & Docker Compose
  • Node.js 18+ and npm
  • Google AI Studio API key (for Gemini LLM)
  • Langfuse Cloud account (free tier: https://cloud.langfuse.com)
  • (Optional) NewsAPI key, Alpha Vantage key

1. Clone the repository

git clone https://github.com/joshuakarthik2005/et.git
cd et

2. Configure backend environment

cd risk-agent
cp .env.example .env
# Edit .env with your API keys (GOOGLE_API_KEY, LANGFUSE keys)

3. Start all backend services

docker compose up -d

This starts 4 services:

  • Neo4j — Knowledge graph (ports 7474, 7687)
  • Qdrant — Vector store (port 6333)
  • PostgreSQL — Relational storage (port 5432)
  • Risk Agent API — FastAPI application (port 8000)

4. Seed the knowledge graph and vector store

docker compose exec risk-agent python -m seed_data.load_graph
docker compose exec risk-agent python -m seed_data.seed_vectors

5. Start the dashboard

cd ../dashboard
npm install
npm run dev

6. Verify

# Backend health check
curl http://localhost:8000/health

# View corridor risks
curl http://localhost:8000/risk/corridors

# Open dashboard
open http://localhost:3000

Development Setup

Backend (FastAPI)

cd risk-agent
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000

Frontend (React + Vite)

cd dashboard
npm install
npm run dev

Running Tests

cd risk-agent
pytest tests/ -v

API Documentation

Interactive Documentation

Key Endpoints

Component Endpoint Method Purpose
C1 /ingest/run POST Trigger multi-source signal ingestion
C1 /process/{signal_id} POST Run extraction + reasoning pipeline for a signal
C1 /risk/corridors GET Current risk state for all corridors
C1 /risk/corridors/{id}/trace GET Full explainability trace (raw → event → reasoning → scenarios)
C2 /scenarios/run POST Run a disruption scenario simulation
C2 /scenarios/runs/{corridor_id} GET Historical scenario runs for a corridor
C2 /scenarios/runs/{corridor_id}/compare GET Side-by-side diff of scenario runs
C3 /procurement/solve POST Run CP-SAT procurement optimizer
C3 /procurement/solves/{scenario_run_id} GET Historical solves for a scenario
C3 /procurement/solves/compare GET Side-by-side diff of procurement solves
C4 /reserve/optimize POST Run SPR drawdown optimizer
C4 /reserve/spr-status GET Current SPR fill levels and constraints
C4 /reserve/decisions/latest/{corridor_id} GET Most recent reserve decision
/health GET Service health check (Neo4j, Qdrant, Postgres)

Project Structure

et/
├── risk-agent/                          # Backend — FastAPI (Components 1–4)
│   ├── app/
│   │   ├── main.py                      # FastAPI application (all endpoints)
│   │   ├── config.py                    # Environment settings (Pydantic)
│   │   ├── pipeline.py                  # Pipeline orchestrator (C1)
│   │   ├── models/
│   │   │   └── schemas.py               # Pydantic v2 schemas (C1)
│   │   ├── ingestion/                   # C1 — Multi-source signal ingestion
│   │   │   ├── gdelt_client.py          # GDELT API connector
│   │   │   ├── news_client.py           # NewsAPI + RSS connector
│   │   │   ├── price_client.py          # Brent crude price connector
│   │   │   └── sanctions_client.py      # Sanctions snapshot loader
│   │   ├── extraction/
│   │   │   └── extractor.py             # LLM Call #1 (event extraction)
│   │   ├── reasoning/
│   │   │   └── reasoner.py              # LLM Call #2 (causal reasoning)
│   │   ├── graph/
│   │   │   └── queries.py               # Neo4j client + queries
│   │   ├── vectorstore/
│   │   │   └── retrieve.py              # Qdrant semantic retrieval
│   │   ├── storage/
│   │   │   ├── models.py                # SQLAlchemy ORM models (C1)
│   │   │   └── repository.py            # Postgres CRUD (C1)
│   │   ├── scenarios/                   # C2 — Disruption Scenario Modeller
│   │   │   ├── cascade.py               # Deterministic cascade formula
│   │   │   ├── monte_carlo.py           # Monte Carlo uncertainty wrapper
│   │   │   ├── narrative.py             # LLM narrative generation
│   │   │   ├── models.py                # SQLAlchemy ORM (scenario tables)
│   │   │   ├── repository.py            # Postgres CRUD (scenarios)
│   │   │   └── schemas.py               # Pydantic request/response
│   │   ├── procurement/                 # C3 — Procurement Orchestrator
│   │   │   ├── solver.py                # CP-SAT optimizer
│   │   │   ├── data.py                  # Cost parameters & supplier data
│   │   │   ├── models.py                # SQLAlchemy ORM (procurement)
│   │   │   ├── repository.py            # Postgres CRUD (solves)
│   │   │   └── schemas.py               # Pydantic request/response
│   │   ├── reserve/                     # C4 — Reserve Optimizer
│   │   │   ├── optimizer.py             # Teisberg grid-search optimizer
│   │   │   ├── data.py                  # SPR parameters & physical constraints
│   │   │   ├── narrative.py             # LLM narrative for decisions
│   │   │   ├── models.py                # SQLAlchemy ORM (decisions)
│   │   │   ├── repository.py            # Postgres CRUD (decisions)
│   │   │   └── schemas.py               # Pydantic request/response
│   │   └── tracing/
│   │       └── tracer.py                # Langfuse wrapper
│   ├── seed_data/
│   │   ├── corridors.json               # 4 shipping corridors
│   │   ├── suppliers.json               # 6 crude oil suppliers
│   │   ├── refineries.json              # 5 Indian refineries
│   │   ├── ports.json                   # 6 Indian ports
│   │   ├── spr_sites.json              # 3 SPR sites (38M bbl total)
│   │   ├── sanctions_events.json        # Sanctions event data
│   │   ├── grade_compatibility.json     # Refinery-supplier compatibility matrix
│   │   ├── schema.sql                   # PostgreSQL init schema
│   │   ├── scenario_schema.sql          # Scenario DDL
│   │   ├── load_graph.py                # Neo4j seed script
│   │   ├── seed_vectors.py              # Qdrant seed script
│   │   └── policy_corpus/
│   │       └── documents.json           # Synthetic-representative policy corpus
│   ├── tests/
│   │   ├── test_scenarios.py            # Scenario modeller tests
│   │   ├── test_procurement.py          # Procurement solver tests
│   │   └── test_reserve.py              # Reserve optimizer tests
│   ├── docker-compose.yml               # 4-service orchestration
│   ├── Dockerfile                       # API container
│   ├── requirements.txt                 # Python dependencies
│   └── .env.example                     # Environment template
│
├── dashboard/                           # Frontend — React + Vite (Component 5)
│   ├── src/
│   │   ├── App.tsx                      # Router and page registry
│   │   ├── main.tsx                     # React entry point
│   │   ├── index.css                    # Design system (vanilla CSS)
│   │   ├── api/
│   │   │   └── client.ts               # API client (all backend endpoints)
│   │   ├── context/
│   │   │   └── CorridorContext.tsx       # Global corridor state provider
│   │   ├── components/
│   │   │   ├── Layout.tsx               # App shell (header, nav, footer)
│   │   │   └── ui.tsx                   # Shared UI components
│   │   ├── pages/
│   │   │   ├── CorridorMap.tsx           # Risk Map with Leaflet
│   │   │   ├── ScenarioExplorer.tsx      # Scenario simulation & history
│   │   │   ├── ProcurementView.tsx       # Procurement allocation solver
│   │   │   ├── ReserveView.tsx           # SPR drawdown optimizer
│   │   │   └── ExplainabilityView.tsx    # 4-step causal chain drill-down
│   │   └── data/
│   │       └── geodata.ts               # Geospatial coordinates & risk utils
│   ├── package.json                     # Node.js dependencies
│   ├── vite.config.ts                   # Vite configuration
│   └── index.html                       # HTML entry point
│
└── README.md                            # This file

Environment Variables

Variable Description Required
GOOGLE_API_KEY Google AI Studio API key for Gemini 2.5 Flash
GEMINI_PROVIDER google_ai or vertex_ai
NEO4J_URI Neo4j Bolt URI (default: bolt://neo4j:7687)
NEO4J_USER Neo4j username (default: neo4j)
NEO4J_PASSWORD Neo4j password (default: riskagent2024)
QDRANT_HOST Qdrant hostname (default: qdrant)
QDRANT_PORT Qdrant port (default: 6333)
POSTGRES_USER PostgreSQL username (default: riskagent)
POSTGRES_PASSWORD PostgreSQL password (default: riskagent2024)
POSTGRES_DB PostgreSQL database (default: riskagent)
POSTGRES_HOST PostgreSQL hostname (default: postgres)
LANGFUSE_PUBLIC_KEY Langfuse Cloud public key
LANGFUSE_SECRET_KEY Langfuse Cloud secret key
LANGFUSE_HOST Langfuse Cloud host URL
NEWSAPI_KEY NewsAPI key for news ingestion Optional
ALPHA_VANTAGE_KEY Alpha Vantage key for price data Optional
VITE_API_URL Backend API URL for dashboard (default: http://localhost:8000) Optional

Performance Specifications

Response Times

Operation Target Notes
Corridor risk fetch < 200ms Neo4j graph read
Explainability trace < 500ms Single corridor trace assembly
Scenario run (point estimate) < 100ms Deterministic cascade formula
Scenario run (Monte Carlo) < 200ms 2000 triangular iterations
Scenario run (with narrative) < 10s Includes Gemini LLM call
Procurement solve < 2s CP-SAT with soft demand constraints
Reserve optimization < 50ms Grid search, ~200 evaluations
Signal ingestion (full pipeline) < 30s Multi-source fetch + LLM extraction + reasoning

System Requirements

Resource Specification
Memory 4GB minimum (8GB recommended for Neo4j + Qdrant)
CPU 2 vCPUs minimum
Storage 2GB for Docker images + database volumes
Network Outbound access for Gemini API, Langfuse, GDELT, NewsAPI

Scalability

Metric Specification
Concurrent dashboard users 10+ per API instance
Historical scenario runs Unlimited (immutable snapshot architecture)
Procurement solves Unlimited (snapshot-per-solve pattern)
Knowledge graph entities 24 seeded nodes, extensible
Policy corpus documents Vector-indexed, unlimited capacity

Scalability — From Prototype to National Deployment

The current prototype models 4 corridors, 6 suppliers, 5 refineries, 6 ports, and 3 SPR sites — India's core import infrastructure. National-scale deployment would expand to:

  • 12+ corridors (including pipeline routes from Central Asia and Myanmar)
  • 20+ suppliers (full PPAC importer registry)
  • 23 refineries (India's complete refining capacity of ~5.4M bpd)
  • Real-time AIS vessel tracking integration for live corridor utilization
  • Horizontal API scaling via container orchestration (Kubernetes) — the stateless, snapshot-per-decision architecture already supports this without schema changes
  • Multi-tenant isolation for simultaneous use by MoPNG, PPAC, and individual refinery procurement teams

All database tables use immutable append-only patterns (branch, never mutate), so scaling historical depth adds zero contention to live operations.

Design Principles

  1. Causal reasoning, not sentiment classification — Multi-step chain: event → transmission mechanism → India-specific corridor/supplier/refinery impact → probability-weighted scenarios
  2. Scenario distributions, not single scores — 2–4 named scenarios per corridor with probabilities summing to ~1.0
  3. Full explainability — Every output traceable from raw source → extracted event → reasoning chain → final assessment
  4. No black-box ML — Transparent, formula-based cascade models with named, inspectable assumptions (matching Resilinc/Everstream/Interos approach)
  5. Branch, never mutate — Every scenario run, procurement solve, and reserve decision creates a new immutable row (Kinaxis-inspired architecture)
  6. India-specific grounding — All entities, prompts, and corpora scoped to India's actual crude oil import structure
  7. Schema-validated structured outputs — All LLM outputs via instructor + Pydantic v2, no manual JSON parsing

Limitations & Honest Scope

Category What's Real What's Illustrative/Synthetic
Corridors 4 real shipping corridors (Hormuz, Red Sea/Bab-el-Mandeb, COGH, Suez) with real geographic coordinates
Suppliers 6 real supplier nations with real PPAC FY24 import share percentages
Refineries 5 real Indian refineries with real nameplate capacities (PPAC data)
SPR Sites 3 real SPR sites with real storage capacities (ISPRL data); 9.5-day cover validated against national import rate
Sanctions events seed_data/sanctions_events.json — structured synthetic events mirroring real OFAC/EU sanctions patterns
Policy corpus seed_data/policy_corpus/documents.json — synthetic-representative documents labeled "source_type": "synthetic_representative", mirroring OFAC notices, PPAC statistics, IEA analyses
Scenario assumptions refinery_runrate_sensitivity sourced from PPAC FY24 import-share data price_passthrough_rate, spr_drawdown_rate — documented illustrative estimates (see scenario_templates.json source_note fields)
Grade compatibility All 30 refinery-supplier cells confirmed true via Phase 1 research (web-sourced, with citations) processing_cost_multiplier (1.0–1.05 range) — illustrative, not sourced from refinery margin data
SPR extraction rate 150,000 bpd — illustrative assumption derived from US SPR benchmark × 60% rock-cavern discount (see reserve/data.py)

For detailed component documentation:

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages