adamkahle commited on
Commit
735ec0d
·
verified ·
1 Parent(s): 22cb452

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -15
app.py CHANGED
@@ -169,7 +169,14 @@ def run_forecast(
169
  nixtla_api_key,
170
  xcols,
171
  future_x_file,
 
 
 
 
172
  ):
 
 
 
173
  try:
174
  season_length = _to_int(season_length, "season_length")
175
  cv_h = _to_int(cv_h, "cv_h")
@@ -179,7 +186,7 @@ def run_forecast(
179
 
180
  df, candidate_xcols, msg = load_training_data(train_file)
181
  if df is None:
182
- return None, None, None, msg, None
183
 
184
  if use_timegpt and (not xcols) and candidate_xcols:
185
  xcols = list(candidate_xcols)
@@ -220,15 +227,17 @@ def run_forecast(
220
  uni_models.append(m)
221
 
222
  needs_future_x = use_exog and (bool(exog_models) or use_timegpt)
223
- X_future = None
224
  X_future_h = None
225
  df_exog = None
226
 
227
  if needs_future_x:
228
  X_future, xmsg = load_future_x(future_x_file, xcols)
229
  if X_future is None:
230
- return None, None, None, xmsg, None
231
- X_future_h = align_future_x_to_horizon(df_y, X_future, xcols, future_h)
 
 
 
232
  df_exog = df[["unique_id", "ds", "y"] + list(xcols)].copy()
233
  for c in xcols:
234
  if not pd.api.types.is_numeric_dtype(df_exog[c]):
@@ -247,18 +256,26 @@ def run_forecast(
247
  future_parts.append(fc_u)
248
 
249
  if exog_models:
 
 
250
  sf_x = StatsForecast(models=exog_models, freq=freq, n_jobs=-1)
251
  fc_x = sf_x.forecast(df=df_exog, h=future_h, X_df=X_future_h)
252
  future_parts.append(fc_x)
253
 
254
  if use_timegpt:
255
  if not nixtla_api_key:
256
- return None, None, None, "TimeGPT selected but no Nixtla API key provided.", None
257
- from nixtla import NixtlaClient
258
- client = NixtlaClient(api_key=nixtla_api_key)
 
 
259
 
 
260
  df_tgpt = df_exog if use_exog else df_y
261
 
 
 
 
262
  tgpt_fc = client.forecast(
263
  df=df_tgpt,
264
  h=future_h,
@@ -279,7 +296,7 @@ def run_forecast(
279
  future_parts.append(tgpt)
280
 
281
  if not future_parts and not eval_parts:
282
- return None, None, None, "No models selected.", None
283
 
284
  eval_df = pd.concat(eval_parts, ignore_index=True) if eval_parts else None
285
  cv_df = pd.concat(cv_parts, ignore_index=True) if cv_parts else None
@@ -291,21 +308,19 @@ def run_forecast(
291
  future_df = future_df.sort_values(["unique_id", "ds"]).reset_index(drop=True)
292
 
293
  fig = create_future_plot(future_df, df_y, title="Forecast")
294
-
295
  files = export_results(eval_df, cv_df, future_df)
296
 
297
  status = msg
298
  if use_timegpt and use_exog:
299
  status += f" | TimeGPT using predictors: {', '.join(xcols)}"
300
  elif use_exog:
301
- status += f" | Predictors selected: {', '.join(xcols)}"
302
 
303
- return eval_df, fig, future_df, status, files
304
 
305
  except Exception as e:
306
- tb = traceback.format_exc()
307
- print(tb)
308
- return None, None, None, f"Run failed: {type(e).__name__}: {e}", None
309
 
310
 
311
  def on_train_upload(file_obj):
@@ -353,6 +368,11 @@ Training CSV required columns: unique_id, ds, y
353
  use_timegpt = gr.Checkbox(value=False, label="Enable TimeGPT")
354
  nixtla_api_key = gr.Textbox(label="Nixtla API Key", type="password")
355
 
 
 
 
 
 
356
  run_btn = gr.Button("Run Forecast", variant="primary")
357
 
358
  eval_df_out = gr.Dataframe(label="Evaluation metrics")
@@ -384,8 +404,22 @@ Training CSV required columns: unique_id, ds, y
384
  nixtla_api_key,
385
  xcols,
386
  future_x_file,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  ],
388
- outputs=[eval_df_out, plot_out, future_df_out, status, files_out],
389
  )
390
 
391
  demo.queue().launch()
 
169
  nixtla_api_key,
170
  xcols,
171
  future_x_file,
172
+ last_eval,
173
+ last_fig,
174
+ last_future,
175
+ last_files,
176
  ):
177
+ def keep(msg):
178
+ return last_eval, last_fig, last_future, msg, last_files, last_eval, last_fig, last_future, last_files
179
+
180
  try:
181
  season_length = _to_int(season_length, "season_length")
182
  cv_h = _to_int(cv_h, "cv_h")
 
186
 
187
  df, candidate_xcols, msg = load_training_data(train_file)
188
  if df is None:
189
+ return keep(msg)
190
 
191
  if use_timegpt and (not xcols) and candidate_xcols:
192
  xcols = list(candidate_xcols)
 
227
  uni_models.append(m)
228
 
229
  needs_future_x = use_exog and (bool(exog_models) or use_timegpt)
 
230
  X_future_h = None
231
  df_exog = None
232
 
233
  if needs_future_x:
234
  X_future, xmsg = load_future_x(future_x_file, xcols)
235
  if X_future is None:
236
+ return keep(xmsg)
237
+ try:
238
+ X_future_h = align_future_x_to_horizon(df_y, X_future, xcols, future_h)
239
+ except Exception as e:
240
+ return keep(f"Future predictors invalid: {type(e).__name__}: {e}")
241
  df_exog = df[["unique_id", "ds", "y"] + list(xcols)].copy()
242
  for c in xcols:
243
  if not pd.api.types.is_numeric_dtype(df_exog[c]):
 
256
  future_parts.append(fc_u)
257
 
258
  if exog_models:
259
+ if not needs_future_x or X_future_h is None:
260
+ return keep("Predictors selected for an exogenous model, but X_df is missing/invalid.")
261
  sf_x = StatsForecast(models=exog_models, freq=freq, n_jobs=-1)
262
  fc_x = sf_x.forecast(df=df_exog, h=future_h, X_df=X_future_h)
263
  future_parts.append(fc_x)
264
 
265
  if use_timegpt:
266
  if not nixtla_api_key:
267
+ return keep("TimeGPT selected but no Nixtla API key provided.")
268
+ try:
269
+ from nixtla import NixtlaClient
270
+ except Exception as e:
271
+ return keep(f"TimeGPT selected but nixtla import failed: {type(e).__name__}: {e}")
272
 
273
+ client = NixtlaClient(api_key=nixtla_api_key)
274
  df_tgpt = df_exog if use_exog else df_y
275
 
276
+ if use_exog and X_future_h is None:
277
+ return keep("TimeGPT predictors detected/selected, but X_df is missing/invalid.")
278
+
279
  tgpt_fc = client.forecast(
280
  df=df_tgpt,
281
  h=future_h,
 
296
  future_parts.append(tgpt)
297
 
298
  if not future_parts and not eval_parts:
299
+ return keep("No models selected.")
300
 
301
  eval_df = pd.concat(eval_parts, ignore_index=True) if eval_parts else None
302
  cv_df = pd.concat(cv_parts, ignore_index=True) if cv_parts else None
 
308
  future_df = future_df.sort_values(["unique_id", "ds"]).reset_index(drop=True)
309
 
310
  fig = create_future_plot(future_df, df_y, title="Forecast")
 
311
  files = export_results(eval_df, cv_df, future_df)
312
 
313
  status = msg
314
  if use_timegpt and use_exog:
315
  status += f" | TimeGPT using predictors: {', '.join(xcols)}"
316
  elif use_exog:
317
+ status += f" | Predictors used: {', '.join(xcols)}"
318
 
319
+ return eval_df, fig, future_df, status, files, eval_df, fig, future_df, files
320
 
321
  except Exception as e:
322
+ print(traceback.format_exc())
323
+ return keep(f"Run failed: {type(e).__name__}: {e}")
 
324
 
325
 
326
  def on_train_upload(file_obj):
 
368
  use_timegpt = gr.Checkbox(value=False, label="Enable TimeGPT")
369
  nixtla_api_key = gr.Textbox(label="Nixtla API Key", type="password")
370
 
371
+ last_eval = gr.State(None)
372
+ last_fig = gr.State(None)
373
+ last_future = gr.State(None)
374
+ last_files = gr.State([])
375
+
376
  run_btn = gr.Button("Run Forecast", variant="primary")
377
 
378
  eval_df_out = gr.Dataframe(label="Evaluation metrics")
 
404
  nixtla_api_key,
405
  xcols,
406
  future_x_file,
407
+ last_eval,
408
+ last_fig,
409
+ last_future,
410
+ last_files,
411
+ ],
412
+ outputs=[
413
+ eval_df_out,
414
+ plot_out,
415
+ future_df_out,
416
+ status,
417
+ files_out,
418
+ last_eval,
419
+ last_fig,
420
+ last_future,
421
+ last_files,
422
  ],
 
423
  )
424
 
425
  demo.queue().launch()