seriffic Claude Opus 4.7 (1M context) commited on
Commit
bf7ea70
·
1 Parent(s): 5b8e335

fix(prithvi): drop .view() on lists; enrich warmup traceback

Browse files

Diag output from the previous deploy:

warm/prithvi: AttributeError: 'list' object has no attribute 'view'

The yaml-instantiated GenericNonGeoSegmentationDataModule stores
`means` and `stds` as Python lists (verified against the v2
config). The previous patch chained `_old.means.view(-1)
.detach().clone()` BEFORE handing them to _DictNormalize, which
crashed on the .view() call before reaching the conversion logic
inside the class.

Fix: pass `_old.means` and `_old.stds` to _DictNormalize raw.
The class's `_torch.as_tensor(mean).view(-1, 1, 1).float()` handles
list-to-tensor conversion internally — same end state, no
precondition that assumes the inputs are already tensors.

Also: lifespan warmup now stores a 5-line traceback tail in
_LAST_ERR so the next regression surfaces with a real stack
location through /healthz and /v1/diag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

app/flood_layers/prithvi_live.py CHANGED
@@ -233,10 +233,14 @@ def _ensure_model():
233
  std = self.std.to(sample.device)
234
  return (sample - mean) / std
235
 
236
- m.datamodule.aug = _DictNormalize(
237
- _old.means.view(-1).detach().clone(),
238
- _old.stds.view(-1).detach().clone(),
239
- )
 
 
 
 
240
  log.info("prithvi_live: patched v2 datamodule transforms "
241
  "for IBM inference.py compat (dict-aware Normalize)")
242
  else:
 
233
  std = self.std.to(sample.device)
234
  return (sample - mean) / std
235
 
236
+ # `_old.means` / `_old.stds` come from the
237
+ # yaml as Python lists — calling `.view()` on
238
+ # them is what tripped the original
239
+ # `'list' object has no attribute 'view'`.
240
+ # _DictNormalize handles the conversion via
241
+ # torch.as_tensor internally; just pass the
242
+ # raw values whatever their type.
243
+ m.datamodule.aug = _DictNormalize(_old.means, _old.stds)
244
  log.info("prithvi_live: patched v2 datamodule transforms "
245
  "for IBM inference.py compat (dict-aware Normalize)")
246
  else:
services/riprap-models/main.py CHANGED
@@ -173,10 +173,13 @@ def _load_prithvi():
173
  std = self.std.to(sample.device)
174
  return (sample - mean) / std
175
 
176
- m.datamodule.aug = _DictNormalize(
177
- _old.means.view(-1).detach().clone(),
178
- _old.stds.view(-1).detach().clone(),
179
- )
 
 
 
180
  log.info("prithvi: patched v2 datamodule transforms "
181
  "for IBM inference.py compat (dict-aware Normalize)")
182
  else:
@@ -803,10 +806,15 @@ async def lifespan(_app: FastAPI):
803
  fn()
804
  log.info("startup %s ok", stage)
805
  except Exception as e: # noqa: BLE001
 
 
806
  log.exception("startup %s failed: %s", stage, e)
807
- _LAST_ERR[stage] = {"ok": False,
808
- "err": f"{type(e).__name__}: {e}",
809
- "stage": stage}
 
 
 
810
  yield
811
  log.info("riprap-models stopping")
812
 
 
173
  std = self.std.to(sample.device)
174
  return (sample - mean) / std
175
 
176
+ # `_old.means` / `_old.stds` come from the yaml as
177
+ # Python lists — calling `.view()` on them is what
178
+ # tripped the original `'list' object has no attribute
179
+ # 'view'`. _DictNormalize handles the conversion via
180
+ # torch.as_tensor internally; just pass the raw values
181
+ # whatever their type.
182
+ m.datamodule.aug = _DictNormalize(_old.means, _old.stds)
183
  log.info("prithvi: patched v2 datamodule transforms "
184
  "for IBM inference.py compat (dict-aware Normalize)")
185
  else:
 
806
  fn()
807
  log.info("startup %s ok", stage)
808
  except Exception as e: # noqa: BLE001
809
+ import traceback
810
+ tb = traceback.format_exc()
811
  log.exception("startup %s failed: %s", stage, e)
812
+ _LAST_ERR[stage] = {
813
+ "ok": False,
814
+ "err": f"{type(e).__name__}: {e}",
815
+ "stage": stage,
816
+ "traceback_tail": tb.splitlines()[-5:],
817
+ }
818
  yield
819
  log.info("riprap-models stopping")
820