fix(prithvi): drop .view() on lists; enrich warmup traceback
Browse filesDiag 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>
|
@@ -233,10 +233,14 @@ def _ensure_model():
|
|
| 233 |
std = self.std.to(sample.device)
|
| 234 |
return (sample - mean) / std
|
| 235 |
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 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:
|
|
@@ -173,10 +173,13 @@ def _load_prithvi():
|
|
| 173 |
std = self.std.to(sample.device)
|
| 174 |
return (sample - mean) / std
|
| 175 |
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 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] = {
|
| 808 |
-
|
| 809 |
-
|
|
|
|
|
|
|
|
|
|
| 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 |
|