@@ -40,6 +40,7 @@ def _load_native_module():
4040try :
4141 run_mcp_server = _native_module .run_mcp_server
4242except AttributeError :
43+
4344 def run_mcp_server (* args , ** kwargs ):
4445 raise RuntimeError ("run_mcp_server requires the 'grpc' feature (maturin develop --features full)" )
4546
@@ -863,6 +864,7 @@ def __init__(self, node_feat_dim=None, edge_feat_dim=None, hidden_size=16, n_lay
863864 # Load PyTorch implementation if torch is installed.
864865 try :
865866 from .torch_predecoder import TorchGNNPredecoder
867+
866868 self ._torch_model = TorchGNNPredecoder (nfd , efd , hidden_size , n_layers )
867869 self ._torch_model .double () # Cast to float64 to match Rust f64.
868870 self .use_torch = True
@@ -873,6 +875,7 @@ def _sync_to_rust(self):
873875 if self .use_torch :
874876 import tempfile
875877 import os
878+
876879 with tempfile .NamedTemporaryFile (suffix = ".safetensors" , delete = False ) as tmp :
877880 tmp_path = tmp .name
878881 try :
@@ -886,6 +889,7 @@ def _sync_to_torch(self):
886889 if self .use_torch :
887890 import tempfile
888891 import os
892+
889893 with tempfile .NamedTemporaryFile (suffix = ".safetensors" , delete = False ) as tmp :
890894 tmp_path = tmp .name
891895 try :
@@ -936,6 +940,7 @@ def forward(self, graph):
936940 """Predict adjusted edge weights for a DetectorGraph."""
937941 if self .use_torch :
938942 import torch
943+
939944 self ._torch_model .eval ()
940945 with torch .no_grad ():
941946 node_feats = torch .tensor (graph .node_features , dtype = torch .float64 )
@@ -954,17 +959,18 @@ def train(self, graphs, targets, n_epochs):
954959 raise ImportError ("PyTorch is required to train GNNPredecoder" )
955960 import torch
956961 import torch .optim as optim
962+
957963 optimizer = optim .SGD (self ._torch_model .parameters (), lr = self .learning_rate , weight_decay = self .l2_lambda )
958964 self ._torch_model .train ()
959-
965+
960966 for epoch in range (n_epochs ):
961967 for graph , target in zip (graphs , targets ):
962968 node_feats = torch .tensor (graph .node_features , dtype = torch .float64 )
963969 edge_feats = torch .tensor (graph .edge_features , dtype = torch .float64 )
964970 edge_src = torch .tensor (graph .edge_src , dtype = torch .long )
965971 edge_dst = torch .tensor (graph .edge_dst , dtype = torch .long )
966972 target_t = torch .tensor (target , dtype = torch .float64 )
967-
973+
968974 optimizer .zero_grad ()
969975 preds = self ._torch_model (node_feats , edge_feats , edge_src , edge_dst )
970976 loss = F .mse_loss (preds , target_t )
@@ -979,35 +985,35 @@ def predict_with_node_probs(self, graph):
979985 """Predict edge weights and node error probabilities."""
980986 if self .use_torch :
981987 import torch
988+
982989 self ._torch_model .eval ()
983990 with torch .no_grad ():
984991 node_feats = torch .tensor (graph .node_features , dtype = torch .float64 )
985992 edge_feats = torch .tensor (graph .edge_features , dtype = torch .float64 )
986993 edge_src = torch .tensor (graph .edge_src , dtype = torch .long )
987994 edge_dst = torch .tensor (graph .edge_dst , dtype = torch .long )
988-
995+
989996 weights = self ._torch_model (node_feats , edge_feats , edge_src , edge_dst )
990-
997+
991998 N = node_feats .size (0 )
992999 node_probs = torch .zeros (N , dtype = torch .float64 )
9931000 node_counts = torch .zeros (N , dtype = torch .float64 )
994-
1001+
9951002 node_probs .scatter_add_ (0 , edge_src , weights )
9961003 node_probs .scatter_add_ (0 , edge_dst , weights )
997-
1004+
9981005 node_counts .scatter_add_ (0 , edge_src , torch .ones_like (edge_src , dtype = torch .float64 ))
9991006 node_counts .scatter_add_ (0 , edge_dst , torch .ones_like (edge_dst , dtype = torch .float64 ))
1000-
1007+
10011008 mask = node_counts > 0
10021009 node_probs [mask ] /= node_counts [mask ]
10031010 node_probs = 1.0 / (1.0 + (- node_probs + 1.0 ).exp ())
1004-
1011+
10051012 return weights .cpu ().numpy ().tolist (), node_probs .cpu ().numpy ().tolist ()
10061013 else :
10071014 return self ._inner .predict_with_node_probs (graph ._inner if isinstance (graph , DetectorGraph ) else graph )
10081015
10091016
1010-
10111017class DetectorGraph :
10121018 """Detector graph used by the GNN and hybrid decoder paths."""
10131019
0 commit comments