The business problem
McKinsey research shows that supply chain disruptions cost the average Fortune 500 company $184 million annually. The global semiconductor shortage, Suez Canal blockage, and pandemic-era supply chain failures demonstrated that most companies have poor visibility into their multi-tier supply networks. They know their direct (Tier-1) suppliers but not the Tier-2 and Tier-3 dependencies that create hidden single points of failure.
Why flat ML fails
- No multi-tier visibility: Flat models assess each supplier independently. They cannot see that Supplier A and Supplier B both depend on the same Tier-2 raw material provider, creating a hidden concentration risk.
- No cascade modeling: A disruption at a critical Tier-3 supplier can halt production of hundreds of finished products. Flat models assess direct supplier risk, not the cascading impact through the BOM hierarchy.
- Alternative supplier blindness: Risk depends on whether alternatives exist. A single-source component is critical; a commodity with 5 qualified suppliers is not. The graph captures this structural context.
- Geographic concentration: Multiple suppliers in the same geographic region share disaster risk. The graph reveals this concentration even when suppliers appear independent at the surface level.
The relational schema
Node types:
Product (id, category, revenue_impact, lead_time)
Component (id, type, criticality, alt_source_count)
Supplier (id, country, financial_score, quality_rating)
Region (id, disaster_risk, political_risk, logistics_score)
Edge types:
Product --[contains]--> Component (quantity, substitutable)
Component --[supplied_by]--> Supplier (lead_time, cost)
Supplier --[located_in]--> Region
Supplier --[depends_on]--> Supplier (material_type)The BOM hierarchy (product-contains-component) combined with supplier dependencies creates a multi-tier risk graph.
PyG architecture: SAGEConv for risk propagation
import torch
import torch.nn.functional as F
from torch_geometric.nn import SAGEConv, HeteroConv, Linear
class SupplierRiskGNN(torch.nn.Module):
def __init__(self, hidden_dim=64):
super().__init__()
self.product_lin = Linear(-1, hidden_dim)
self.component_lin = Linear(-1, hidden_dim)
self.supplier_lin = Linear(-1, hidden_dim)
self.region_lin = Linear(-1, hidden_dim)
# 3 layers for multi-tier propagation
self.convs = torch.nn.ModuleList()
for _ in range(3):
conv = HeteroConv({
('product', 'contains', 'component'): SAGEConv(
hidden_dim, hidden_dim),
('component', 'supplied_by', 'supplier'): SAGEConv(
hidden_dim, hidden_dim),
('supplier', 'located_in', 'region'): SAGEConv(
hidden_dim, hidden_dim),
('supplier', 'depends_on', 'supplier'): SAGEConv(
hidden_dim, hidden_dim),
}, aggr='sum')
self.convs.append(conv)
self.risk_head = torch.nn.Sequential(
Linear(hidden_dim, 32),
torch.nn.ReLU(),
Linear(32, 1),
)
def forward(self, x_dict, edge_index_dict):
x_dict['product'] = self.product_lin(x_dict['product'])
x_dict['component'] = self.component_lin(
x_dict['component'])
x_dict['supplier'] = self.supplier_lin(x_dict['supplier'])
x_dict['region'] = self.region_lin(x_dict['region'])
for conv in self.convs:
x_dict = {k: F.relu(v) for k, v in
conv(x_dict, edge_index_dict).items()}
# Risk score per supplier
return torch.sigmoid(
self.risk_head(x_dict['supplier']).squeeze(-1))3-layer SAGEConv propagates risk through multi-tier dependencies. Geographic risk from regions flows to suppliers, then through the BOM hierarchy to products.
Expected performance
- Supplier scorecard (heuristic): ~55 AUROC
- LightGBM (flat-table): 62.44 AUROC
- GNN (3-layer SAGEConv): 75.83 AUROC
- KumoRFM (zero-shot): 76.71 AUROC
Or use KumoRFM in one line
PREDICT disruption_risk FOR supplier
USING supplier, component, product, region, purchase_orderOne PQL query. KumoRFM maps multi-tier dependencies, propagates geographic and financial risk signals, and scores each supplier.