fix(intern-decision-serve): code-review fixes

- a failure while building the response (a non-finite number included) is a 500 inside the
  envelope, never a 422 or a render crash outside it
- an engine ValueError keeps its message but is released and raised unchained, like an OOM
- the prompt is built (and the model's own validation run) before the forward
- the row cap is counted before any ordering is built
- /health reads a device name cached at load, so it makes no driver call off the inference thread
This commit is contained in:
vh
2026-09-30 09:30:40 -07:00
parent 618390c5fa
commit 21d16d7ad8
5 changed files with 110 additions and 21 deletions
@@ -80,6 +80,8 @@ class TorchEngine:
self._torch, self._engine, self._inference, self._tokenizer = torch, engine, inference, tokenizer
self.metadata, self._settings = metadata, settings
self._release_above = release_above_bytes
# Asked once, here, on the inference thread: /health then reads only allocator counters.
self._device_name = torch.cuda.get_device_name(0) if settings.device == "cuda" else None
@classmethod
def load(cls, settings: Settings, *, torch: Any = None,
@@ -167,7 +169,7 @@ class TorchEngine:
info = dict(self.metadata)
if self._settings.device == "cuda":
cuda = self._torch.cuda
info["device_name"] = cuda.get_device_name(0)
info["device_name"] = self._device_name
info["allocated_gib"] = round(cuda.memory_allocated(0) / 2**30, 3)
info["reserved_gib"] = round(cuda.memory_reserved(0) / 2**30, 3)
if hasattr(cuda, "max_memory_reserved"):
@@ -181,12 +183,15 @@ class TorchEngine:
self._torch.cuda.empty_cache()
def predict(self, request: dict) -> tuple[dict, str]:
"""One call: the model's own predict(), then the prompt hash (INV-8). Returns (response, sha)."""
"""One call: the prompt hash (INV-8; this also runs the model's own validation before any GPU
work), then the model's own predict(). Returns (response, sha)."""
sha = hashlib.sha256(self._prompt_text(request).encode()).hexdigest()
try:
response = self._engine.predict(request)
sha = hashlib.sha256(self._prompt_text(request).encode()).hexdigest()
except ValueError:
raise # the model's validation: raised before any GPU work
except ValueError as exc:
# Usually the token limit, found before the forward; but transformers raises ValueError
# from inside a forward too. Either way, keep the message and release like any failure.
failure, message = ValueError, str(exc)
except self._torch.cuda.OutOfMemoryError as exc:
failure, message = OutOfMemory, _first_line(exc) or "CUDA out of memory"
except Exception as exc: # noqa: BLE001 — every other failure is released and reported below