Repository navigation
fix(slm-frontend): monitoring hardcodes GPU as absent — "no GPU nodes in fleet" is asserted in a composable while the schema models nvidia-gpu and amd-gpu per node #15226
Description
Child of #15184 (hardware-aware deployment). This is the monitoring surface of the same defect:
fleet composition is assumed rather than observed.
Problem
autobot-slm-frontend/src/composables/usePrometheusMetrics.ts:381-390 returns fixed values and
states a fleet-wide claim as a code comment:
async function fetchGPUDetails(): Promise<void> {
// No GPU metrics endpoint in SLM backend - no GPU nodes in fleet
gpuDetails.value = {
available: false,
utilization_percent: 0,
memory_utilization_percent: 0,
temperature_celsius: 0,
power_watts: 0,
}
}So /slm/monitoring/ reports GPU unavailable, 0% utilisation, 0°C, 0W on every deployment,
regardless of what hardware is attached. Nothing queries anything.
The same file also stubs recommendations at :375-378 — recommendations.value = [] with
"SLM doesn't have a recommendations endpoint yet" — so that panel is permanently empty by
construction rather than by data.
Three layers disagree
| Layer | State |
|---|---|
Schema — autobot-slm-backend/models/schemas.py:2123-2125 |
models INTEL_NPU, NVIDIA_GPU, AMD_GPU as accelerator types per node |
| Backend API | exposes /npu/nodes; no GPU endpoint anywhere in autobot-slm-backend/api/ |
| Frontend | hardcodes GPU absent and says so in a comment |
The data model already anticipates NVIDIA and AMD GPUs in the fleet. The comment asserting there
are none contradicts the schema sitting two layers below it.
The NPU path shows what the fix looks like
Immediately below, fetchNPUDetails() at :392-400 does it correctly:
// Issue #835 - query actual NPU node status from SLM backend
const data = await slmApiClient.get<NpuNodesWire>('/npu/nodes', POLL_OPTS)NPU was presumably stubbed the same way and #835 replaced the stub with a real query. GPU never
received the equivalent treatment, so the two accelerator families are monitored to different
standards in the same composable.
Why this matters beyond an empty panel
- It is a false negative, not a blank: the panel reports
available: falsewith concrete
zeroes, which reads as "measured and idle" rather than "not implemented". An operator cannot
distinguish a fleet with no GPUs from a fleet whose GPUs are unmonitored. - It compounds fix(monitoring): two definitions of "GPU available" — the monitoring API reports a driver probe while every compute path gates on torch.cuda, so the GUI claims acceleration that is not happening #15180, where the main backend already reports GPU presence from an
nvidia-smiprobe. The two surfaces can therefore disagree with each other about the same host. - It contradicts the platform's dual-target claim recorded in [Umbrella] Hardware-aware deployment — detect the host's accelerators once, install and report per what is actually there #15184 — Intel NPU and CUDA.
Direction
- Add a GPU metrics endpoint to the SLM backend, or extend the existing node-metrics endpoint to
carry accelerator data keyed by theAcceleratorTypethe schema already defines. Corrected 2026-10-03:AcceleratorTypehas zero occurrences repo-wide onorigin/main— the schema does not define it. The delivered fix typed the GPU read from the generated contract (GPUNodeStatus/GPUMetrics) instead, which is why AC4 below cannot be ticked as written. - Replace the stub with a real query, following the
/npu/nodespattern. - Distinguish three states in the UI — no GPU present, GPU present but unmonitored, and
GPU metrics — so an unimplemented path never renders as a measurement. - Give
fetchRecommendations()the same treatment: an absent endpoint should surface as
unavailable, not as an empty list.
Acceptance criteria
- GPU metrics come from the backend, not a literal.
- A host with an NVIDIA GPU shows it in
/slm/monitoring/. - "Not implemented" and "none present" are visually distinct; neither renders as measured zeroes.
- The
AcceleratorTypeenum is the shared vocabulary across schema, API and UI. — unsatisfiable as written: the enum does not exist (zero occurrences onorigin/main). Needs re-scoping to the vocabulary that was actually delivered, or the enum introduced deliberately. See the decision comment on this issue. -
fetchRecommendationsno longer fabricates an empty result for a missing endpoint.
References
autobot-slm-frontend/src/composables/usePrometheusMetrics.ts:375-390 (the stubs), :392-400
(the correct NPU pattern, #835), autobot-slm-backend/models/schemas.py:2123-2125
(INTEL_NPU / NVIDIA_GPU / AMD_GPU), autobot-slm-frontend/src/views/monitoring/SystemMonitor.vue.
Parent: #15184. Related: #15180 (the main backend's conflicting GPU-availability probe), #15162.
Activity
mrveiss commentedon Sep 11, 2026
Re-scope from reading the code (base 65609f9). The monitoring page has no native GPU panel.
views/monitoring/SystemMonitor.vue:37) embeds the Grafana dashboardautobot-performance(components/monitoring/GrafanaDashboard.vue:53).usePrometheusMetrics'gpuDetailsorgpuUsage. The composable is their only reference. So the "GPU unavailable, 0%, 0 °C, 0 W" described above is a literal that nothing displays.autobot_gpu_*series per node.What that means for each AC
autobot_gpu_*{node=...}from each heartbeat. The composable's literal goes as well:fetchGPUDetailswill readGET /api/monitoring/gpu/nodes(feat(slm): nodes report their GPUs in the heartbeat, and the SLM serves them per node (#16280, #16281) #16292)./slm/monitoring/. Grafana needs fix(monitoring): Grafana dashboards reference a Prometheus datasource uid that no provisioning defines #16290 too, because the dashboard's datasource uid is provisioned nowhere. Under the no-deletion rule, the unrendered composable data gets wired in: a GPU card in the monitoring "details" view, fed by the new endpoint. That meets this AC natively, without waiting on Grafana.autobot_gpu_available{node}=0. The native card renders the endpoint's three states,not_reported,noneandpresent, withmonitored: falsedevices shown as unmonitored rather than as zeroes.GPUDevice.device_typeisNPUDeviceTypein the SLM schema. After feat(slm): nodes report their GPUs in the heartbeat, and the SLM serves them per node (#16280, #16281) #16292's generated-types refresh, the UI uses the generated type in place of the hand-copied union attypes/slm.ts:616.fetchRecommendations. Unchanged: a missing endpoint surfaces as unavailable, not as an empty list.Plan
One PR after #16292 lands, on top of its regenerated
src/types/generated/api.ts. It covers:fetchGPUDetailsreading the endpoint;en.jsonkeys (the SLM's only locale);fetchRecommendationsreporting unavailable;Blocked by #16292. #16290 is needed for the Grafana tab to render at all.
feat(slm-frontend): the monitoring view shows each node's GPU, and sa…
feat(slm-frontend): type the GPU nodes read from the generated contra…
feat(slm-frontend): the monitoring view shows each node's GPU, and sa…
feat(slm-frontend): type the GPU nodes read from the generated contra…
mrveiss commentedon Sep 28, 2026
Chunk triage —
v0.9.2 node plane and deploy. Read-only atorigin/main7adaca8c29; nothing labelled or moved.The premise has moved: the hardcoded literal is gone.
The body quotes
usePrometheusMetrics.ts:381-390returningavailable: false, utilization_percent: 0behind the comment "No GPU metrics endpoint in SLM backend - no GPU nodes in fleet". On currentmain:the literal and its comment are gone —
git grep "no GPU nodes in fleet"overautobot-slm-frontendreturns nothing;the composable (now 622 lines) imports
GPUNodeStatus(:18) andGPUMetrics(:25), summarises measured per-node state viasummariseGpus(nodes: GPUNodeStatus…)(:215), and:242carries the comment "fix(slm-frontend): monitoring hardcodes GPU as absent — "no GPU nodes in fleet" is asserted in a composable while the schema models nvidia-gpu and amd-gpu per node #15226: each node's GPU state fro…".Pre-filters: merged
db5ee69730— "feat(slm-frontend): type the GPU nodes read from the generated co…" — plus PR#16292 and PR#15244 merged.What that does not settle: AC3 ("'Not implemented' and 'none present' are visually distinct; neither renders as measured zeroes") is a rendering claim, and AC2 (a host with an NVIDIA GPU shows it) is an observation. So this is mixed: the data-path criteria look delivered, the distinguishability one is a frontend-test question, and the GPU-host one belongs in
v0.9-host.Recommendation: a closure pass with the frontend test, not an implementation slot. AC3 is the one worth keeping — it is the same absent versus zero distinction as bug(slm): five node-health sites turn a failed measurement into a real-looking value — including eleven lines from the file's own correct pattern #17660 in this chunk, one layer up in the UI.
mrveiss commentedon Sep 28, 2026
Pre-filter (read-only, v0.9.2): partial — the literal is gone, the shared vocabulary was never added
Anchored at
origin/mainab05ba3aef. Two commits carry(#15226), both 2026-09-11:Progressed: the hardcoded absence is gone — no
no GPU nodes/noGpuNodesliteral remains anywhere underautobot-slm-frontend/src, and the second commit's subject is AC1 and AC3 in one line (shows each node's GPU, and says when it can't).AC4 is definitively unmet: "The
AcceleratorTypeenum is the shared vocabulary across schema, API and UI" —AcceleratorTypeappears zero times in the entire repository. Not in the SLM frontend, not in the backend, not inautobot_shared. So whatever vocabulary those three layers currently share, it is not that enum, and the criterion cannot be ticked against any existing symbol.AC2 (an NVIDIA host shows it in
/slm/monitoring/) is host evidence. AC5 (fetchRecommendationsno longer fabricating an empty result) I did not verify.mrveiss commentedon Sep 28, 2026
Per-AC pass at
origin/mainae0e73e343— the headline defect is fixed; AC4 asks for a type that was never created. Not closable as written; AC4 is re-scopable.Landed via
db5ee69730"feat(slm-frontend): type the GPU nodes read from the generated co…" (PR#16292, PR#15244).available: falseblock and its "No GPU metrics endpoint in SLM backend - no GPU nodes in fleet" comment are gone;usePrometheusMetrics.ts:215summariseGpus(nodes: GPUNodeStatus…)summarises measured per-node state, with:242commented "#15226: each node's GPU state fro…"/slm/monitoring/v0.9-hostAcceleratorTypeenum is the shared vocabulary across schema, API and UIgit grep -c AcceleratorTypeoverautobot-backend,autobot-slm-backend,autobot-slm-frontendandautobot_sharedreturns zero occurrencesfetchRecommendationsno longer fabricates an empty result for a missing endpointAC4 is re-scopable, and here is the honest shape of it
The fix took a different route to the same goal: instead of introducing an
AcceleratorTypeenum, it types the GPU read from the generated contract —GPUNodeStatus(:18) andGPUMetrics(:25), which are shared across schema, API and UI by construction because they are generated from the backend's schema rather than hand-mirrored.So the criterion's intent — one shared vocabulary rather than three hand-kept ones — is satisfied by a better mechanism than the one it named. Re-scope AC4 to the generated types, and it is met. Leave it as written, and the issue cannot close without creating an enum whose only purpose is to satisfy a criterion the delivered design made unnecessary — which is #17693's warning in the other direction: a call site added to satisfy a guard, for work nobody wants.
Recommendation: re-scope AC4 to
GPUNodeStatus/GPUMetrics, move AC2 tov0.9-host, and the remainder is two frontend assertions (AC3, AC5). That is a small, closable issue. As it stands, it is not closable.mrveiss commentedon Sep 28, 2026
Decision needed (re-scope of AC4), options + recommendation — see a4's table above. AC4 names
AcceleratorType, which has zero occurrences repo-wide; the delivered fix types the GPU read from the generated contract (GPUNodeStatus/GPUMetrics), shared across schema/API/UI by construction. Options: A re-scope AC4 to the generated types (met), move AC2 (a GPU host) tov0.9-host, leaving two frontend assertions (AC3, AC5) as the closable remainder; B keep AC4 as written, which requires creating an enum whose only purpose is to satisfy the criterion. Recommendation: A. Owner answers here; posted by the coordinating session.