Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
CHANGED
|
@@ -477,6 +477,20 @@ def load_pipeline():
|
|
| 477 |
print(f"Error details: {str(e)}")
|
| 478 |
raise RuntimeError(f"Failed to load model: {str(e)}")
|
| 479 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 480 |
def is_market_open() -> bool:
|
| 481 |
"""Check if the US stock market is currently open (legacy function for backward compatibility)"""
|
| 482 |
return market_status_manager.get_status('US_STOCKS').is_open
|
|
@@ -990,190 +1004,26 @@ def make_prediction_enhanced(symbol: str, timeframe: str = "1d", prediction_days
|
|
| 990 |
|
| 991 |
# Use predict_quantiles with proper formatting
|
| 992 |
with torch.amp.autocast('cpu'):
|
| 993 |
-
# Ensure
|
| 994 |
-
context = context.to(device)
|
| 995 |
-
|
| 996 |
-
# Ensure context is properly shaped and on CPU
|
| 997 |
if len(context.shape) == 1:
|
| 998 |
context = context.unsqueeze(0)
|
| 999 |
context = context.to(device)
|
| 1000 |
-
|
| 1001 |
-
|
| 1002 |
-
pipe.model = pipe.model.to(device)
|
| 1003 |
-
|
| 1004 |
-
# Move model to evaluation mode
|
| 1005 |
-
pipe.model.eval()
|
| 1006 |
-
|
| 1007 |
-
# Move all model parameters and buffers to CPU
|
| 1008 |
-
for param in pipe.model.parameters():
|
| 1009 |
-
param.data = param.data.to(device)
|
| 1010 |
-
for buffer in pipe.model.buffers():
|
| 1011 |
-
buffer.data = buffer.data.to(device)
|
| 1012 |
-
|
| 1013 |
-
# Move all model submodules to CPU
|
| 1014 |
-
for module in pipe.model.modules():
|
| 1015 |
-
if hasattr(module, 'to'):
|
| 1016 |
-
module.to(device)
|
| 1017 |
-
|
| 1018 |
-
# Move all model attributes to CPU
|
| 1019 |
-
for name, value in pipe.model.__dict__.items():
|
| 1020 |
-
if isinstance(value, torch.Tensor):
|
| 1021 |
-
pipe.model.__dict__[name] = value.to(device)
|
| 1022 |
-
|
| 1023 |
-
# Move all model config tensors to CPU
|
| 1024 |
-
if hasattr(pipe.model, 'config'):
|
| 1025 |
-
for key, value in pipe.model.config.__dict__.items():
|
| 1026 |
-
if isinstance(value, torch.Tensor):
|
| 1027 |
-
setattr(pipe.model.config, key, value.to(device))
|
| 1028 |
-
|
| 1029 |
-
# Move all pipeline tensors to CPU
|
| 1030 |
-
for name, value in pipe.__dict__.items():
|
| 1031 |
-
if isinstance(value, torch.Tensor):
|
| 1032 |
-
setattr(pipe, name, value.to(device))
|
| 1033 |
-
|
| 1034 |
-
# Ensure all model states are on CPU
|
| 1035 |
-
if hasattr(pipe.model, 'state_dict'):
|
| 1036 |
-
state_dict = pipe.model.state_dict()
|
| 1037 |
-
for key in state_dict:
|
| 1038 |
-
if isinstance(state_dict[key], torch.Tensor):
|
| 1039 |
-
state_dict[key] = state_dict[key].to(device)
|
| 1040 |
-
pipe.model.load_state_dict(state_dict)
|
| 1041 |
-
|
| 1042 |
-
# Move any additional components to CPU
|
| 1043 |
-
if hasattr(pipe, 'tokenizer'):
|
| 1044 |
-
# Move tokenizer to CPU if it supports it
|
| 1045 |
-
if hasattr(pipe.tokenizer, 'to'):
|
| 1046 |
-
pipe.tokenizer = pipe.tokenizer.to(device)
|
| 1047 |
-
|
| 1048 |
-
# Move all tokenizer tensors to CPU
|
| 1049 |
-
for name, value in pipe.tokenizer.__dict__.items():
|
| 1050 |
-
if isinstance(value, torch.Tensor):
|
| 1051 |
-
setattr(pipe.tokenizer, name, value.to(device))
|
| 1052 |
-
|
| 1053 |
-
# Handle MeanScaleUniformBins specific attributes
|
| 1054 |
-
if hasattr(pipe.tokenizer, 'bins'):
|
| 1055 |
-
if isinstance(pipe.tokenizer.bins, torch.Tensor):
|
| 1056 |
-
pipe.tokenizer.bins = pipe.tokenizer.bins.to(device)
|
| 1057 |
-
|
| 1058 |
-
if hasattr(pipe.tokenizer, 'scale'):
|
| 1059 |
-
if isinstance(pipe.tokenizer.scale, torch.Tensor):
|
| 1060 |
-
pipe.tokenizer.scale = pipe.tokenizer.scale.to(device)
|
| 1061 |
-
|
| 1062 |
-
if hasattr(pipe.tokenizer, 'mean'):
|
| 1063 |
-
if isinstance(pipe.tokenizer.mean, torch.Tensor):
|
| 1064 |
-
pipe.tokenizer.mean = pipe.tokenizer.mean.to(device)
|
| 1065 |
-
|
| 1066 |
-
# Move any additional tensors in the tokenizer's attributes to CPU
|
| 1067 |
-
for name, value in pipe.tokenizer.__dict__.items():
|
| 1068 |
-
if isinstance(value, torch.Tensor):
|
| 1069 |
-
pipe.tokenizer.__dict__[name] = value.to(device)
|
| 1070 |
-
|
| 1071 |
-
# Remove the EOS token handling since MeanScaleUniformBins doesn't use it
|
| 1072 |
-
if hasattr(pipe.tokenizer, '_append_eos_token'):
|
| 1073 |
-
# Create a wrapper that just returns the input tensors
|
| 1074 |
-
def wrapped_append_eos(token_ids, attention_mask):
|
| 1075 |
-
return token_ids, attention_mask
|
| 1076 |
-
pipe.tokenizer._append_eos_token = wrapped_append_eos
|
| 1077 |
-
|
| 1078 |
-
# Force synchronization for CPU (no-op for CPU)
|
| 1079 |
-
# torch.cuda.synchronize() # Not needed for CPU
|
| 1080 |
-
|
| 1081 |
-
# Ensure all model components are in eval mode
|
| 1082 |
-
pipe.model.eval()
|
| 1083 |
-
|
| 1084 |
# Fix generation configuration to prevent min_length errors
|
| 1085 |
if hasattr(pipe.model, 'config'):
|
| 1086 |
-
|
| 1087 |
-
if
|
| 1088 |
-
# Reset generation config to safe defaults
|
| 1089 |
-
pipe.model.config.generation_config.min_length = 0
|
| 1090 |
-
pipe.model.config.generation_config.max_length = 512
|
| 1091 |
-
pipe.model.config.generation_config.do_sample = False
|
| 1092 |
-
pipe.model.config.generation_config.num_beams = 1
|
| 1093 |
-
else:
|
| 1094 |
-
# Create a safe generation config if it doesn't exist
|
| 1095 |
pipe.model.config.generation_config = GenerationConfig(
|
| 1096 |
-
min_length=0,
|
| 1097 |
-
max_length=512,
|
| 1098 |
-
do_sample=False,
|
| 1099 |
-
num_beams=1
|
| 1100 |
)
|
| 1101 |
-
|
| 1102 |
-
|
| 1103 |
-
|
| 1104 |
-
|
| 1105 |
-
|
| 1106 |
-
|
| 1107 |
-
|
| 1108 |
-
# Move any additional tensors in the model's state dict to CPU
|
| 1109 |
-
if hasattr(pipe.model, 'state_dict'):
|
| 1110 |
-
state_dict = pipe.model.state_dict()
|
| 1111 |
-
for key in state_dict:
|
| 1112 |
-
if isinstance(state_dict[key], torch.Tensor):
|
| 1113 |
-
state_dict[key] = state_dict[key].to(device)
|
| 1114 |
-
pipe.model.load_state_dict(state_dict)
|
| 1115 |
-
|
| 1116 |
-
# Move any additional tensors in the model's buffers to CPU
|
| 1117 |
-
for name, buffer in pipe.model.named_buffers():
|
| 1118 |
-
if buffer is not None:
|
| 1119 |
-
pipe.model.register_buffer(name, buffer.to(device))
|
| 1120 |
-
|
| 1121 |
-
# Move any additional tensors in the model's parameters to CPU
|
| 1122 |
-
for name, param in pipe.model.named_parameters():
|
| 1123 |
-
if param is not None:
|
| 1124 |
-
param.data = param.data.to(device)
|
| 1125 |
-
|
| 1126 |
-
# Move any additional tensors in the model's attributes to GPU
|
| 1127 |
-
for name, value in pipe.model.__dict__.items():
|
| 1128 |
-
if isinstance(value, torch.Tensor):
|
| 1129 |
-
pipe.model.__dict__[name] = value.to(device)
|
| 1130 |
-
|
| 1131 |
-
# Move any additional tensors in the model's modules to GPU
|
| 1132 |
-
for name, module in pipe.model.named_modules():
|
| 1133 |
-
if hasattr(module, 'to'):
|
| 1134 |
-
module.to(device)
|
| 1135 |
-
# Move any tensors in the module's __dict__
|
| 1136 |
-
for key, value in module.__dict__.items():
|
| 1137 |
-
if isinstance(value, torch.Tensor):
|
| 1138 |
-
setattr(module, key, value.to(device))
|
| 1139 |
-
|
| 1140 |
-
# Force synchronization for CPU (no-op for CPU)
|
| 1141 |
-
# torch.cuda.synchronize() # Not needed for CPU
|
| 1142 |
-
|
| 1143 |
-
# Ensure tokenizer is on GPU and all its tensors are on GPU
|
| 1144 |
-
if hasattr(pipe, 'tokenizer'):
|
| 1145 |
-
# Move tokenizer to CPU if it supports it
|
| 1146 |
-
if hasattr(pipe.tokenizer, 'to'):
|
| 1147 |
-
pipe.tokenizer = pipe.tokenizer.to(device)
|
| 1148 |
-
|
| 1149 |
-
# Move all tokenizer tensors to CPU
|
| 1150 |
-
for name, value in pipe.tokenizer.__dict__.items():
|
| 1151 |
-
if isinstance(value, torch.Tensor):
|
| 1152 |
-
setattr(pipe.tokenizer, name, value.to(device))
|
| 1153 |
-
|
| 1154 |
-
# Handle MeanScaleUniformBins specific attributes
|
| 1155 |
-
if hasattr(pipe.tokenizer, 'bins'):
|
| 1156 |
-
if isinstance(pipe.tokenizer.bins, torch.Tensor):
|
| 1157 |
-
pipe.tokenizer.bins = pipe.tokenizer.bins.to(device)
|
| 1158 |
-
|
| 1159 |
-
if hasattr(pipe.tokenizer, 'scale'):
|
| 1160 |
-
if isinstance(pipe.tokenizer.scale, torch.Tensor):
|
| 1161 |
-
pipe.tokenizer.scale = pipe.tokenizer.scale.to(device)
|
| 1162 |
-
|
| 1163 |
-
if hasattr(pipe.tokenizer, 'mean'):
|
| 1164 |
-
if isinstance(pipe.tokenizer.mean, torch.Tensor):
|
| 1165 |
-
pipe.tokenizer.mean = pipe.tokenizer.mean.to(device)
|
| 1166 |
-
|
| 1167 |
-
# Move any additional tensors in the tokenizer's attributes to CPU
|
| 1168 |
-
for name, value in pipe.tokenizer.__dict__.items():
|
| 1169 |
-
if isinstance(value, torch.Tensor):
|
| 1170 |
-
pipe.tokenizer.__dict__[name] = value.to(device)
|
| 1171 |
-
|
| 1172 |
-
# Force synchronization for CPU (no-op for CPU)
|
| 1173 |
-
# torch.cuda.synchronize() # Not needed for CPU
|
| 1174 |
-
|
| 1175 |
# Make prediction with proper parameters
|
| 1176 |
-
# Use the standard quantile levels as per Chronos documentation
|
| 1177 |
try:
|
| 1178 |
quantiles, mean = pipe.predict_quantiles(
|
| 1179 |
context=context,
|
|
|
|
| 477 |
print(f"Error details: {str(e)}")
|
| 478 |
raise RuntimeError(f"Failed to load model: {str(e)}")
|
| 479 |
|
| 480 |
+
def _ensure_pipeline_cpu(pipe):
|
| 481 |
+
"""Ensure Chronos pipeline model/tokenizer are on CPU and in eval mode."""
|
| 482 |
+
try:
|
| 483 |
+
pipe.model = pipe.model.to(torch.device("cpu"))
|
| 484 |
+
pipe.model.eval()
|
| 485 |
+
except Exception:
|
| 486 |
+
pass
|
| 487 |
+
try:
|
| 488 |
+
tok = getattr(pipe, 'tokenizer', None)
|
| 489 |
+
if tok is not None and hasattr(tok, 'to'):
|
| 490 |
+
pipe.tokenizer = tok.to(torch.device("cpu"))
|
| 491 |
+
except Exception:
|
| 492 |
+
pass
|
| 493 |
+
|
| 494 |
def is_market_open() -> bool:
|
| 495 |
"""Check if the US stock market is currently open (legacy function for backward compatibility)"""
|
| 496 |
return market_status_manager.get_status('US_STOCKS').is_open
|
|
|
|
| 1004 |
|
| 1005 |
# Use predict_quantiles with proper formatting
|
| 1006 |
with torch.amp.autocast('cpu'):
|
| 1007 |
+
# Ensure inputs and pipeline are on CPU
|
|
|
|
|
|
|
|
|
|
| 1008 |
if len(context.shape) == 1:
|
| 1009 |
context = context.unsqueeze(0)
|
| 1010 |
context = context.to(device)
|
| 1011 |
+
_ensure_pipeline_cpu(pipe)
|
| 1012 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1013 |
# Fix generation configuration to prevent min_length errors
|
| 1014 |
if hasattr(pipe.model, 'config'):
|
| 1015 |
+
gen_cfg = getattr(pipe.model.config, 'generation_config', None)
|
| 1016 |
+
if gen_cfg is None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1017 |
pipe.model.config.generation_config = GenerationConfig(
|
| 1018 |
+
min_length=0, max_length=512, do_sample=False, num_beams=1
|
|
|
|
|
|
|
|
|
|
| 1019 |
)
|
| 1020 |
+
else:
|
| 1021 |
+
gen_cfg.min_length = 0
|
| 1022 |
+
gen_cfg.max_length = 512
|
| 1023 |
+
gen_cfg.do_sample = False
|
| 1024 |
+
gen_cfg.num_beams = 1
|
| 1025 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1026 |
# Make prediction with proper parameters
|
|
|
|
| 1027 |
try:
|
| 1028 |
quantiles, mean = pipe.predict_quantiles(
|
| 1029 |
context=context,
|