From a6b70e00a0f86d8ed7d1670a4eb40d3842e9ab84 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Mon, 2 Feb 2026 12:16:51 -0300 Subject: [PATCH] feat: enrich followup evidence with hotspots --- atlasbot/engine/answerer.py | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/atlasbot/engine/answerer.py b/atlasbot/engine/answerer.py index f6c9ec0..6cd337c 100644 --- a/atlasbot/engine/answerer.py +++ b/atlasbot/engine/answerer.py @@ -790,6 +790,7 @@ class AnswerEngine: claim_ids = await self._select_claims(question, state.claims, plan, call_llm) selected = [claim for claim in state.claims if claim.id in claim_ids] if claim_ids else state.claims[:2] evidence_lines = [] + lowered = question.lower() for claim in selected: evidence_lines.append(f"Claim: {claim.claim}") for ev in claim.evidence: @@ -799,6 +800,11 @@ class AnswerEngine: if ev.value_at_claim is not None and current is not None and current != ev.value_at_claim: delta_note = f" (now {current})" evidence_lines.append(f"- {ev.path}: {ev.value_at_claim}{delta_note}") + if any(term in lowered for term in ("hotspot", "hot spot", "hottest", "jetson", "rpi", "amd64", "arm64", "hardware", "class")): + hotspot_lines = _hotspot_evidence(summary) + if hotspot_lines: + evidence_lines.append("HotspotSummary:") + evidence_lines.extend(hotspot_lines) evidence_ctx = "\n".join(evidence_lines) prompt = prompts.FOLLOWUP_PROMPT + "\nFollow-up: " + question + "\nEvidence:\n" + evidence_ctx reply = await call_llm(prompts.FOLLOWUP_SYSTEM, prompt, model=plan.model, tag="followup") @@ -1214,6 +1220,41 @@ def _has_token(text: str, token: str) -> bool: return re.search(rf"\b{re.escape(token)}\b", text) is not None +def _hotspot_evidence(summary: dict[str, Any]) -> list[str]: + hottest = summary.get("hottest") if isinstance(summary.get("hottest"), dict) else {} + if not hottest: + return [] + hardware_by_node = summary.get("hardware_by_node") if isinstance(summary.get("hardware_by_node"), dict) else {} + node_pods_top = summary.get("node_pods_top") if isinstance(summary.get("node_pods_top"), list) else [] + ns_map = {} + for item in node_pods_top: + if not isinstance(item, dict): + continue + node = item.get("node") + namespaces_top = item.get("namespaces_top") if isinstance(item.get("namespaces_top"), list) else [] + ns_map[node] = namespaces_top + lines: list[str] = [] + for metric, info in hottest.items(): + if not isinstance(info, dict): + continue + node = info.get("node") + value = info.get("value") + if not node: + continue + node_class = hardware_by_node.get(node) + ns_parts = [] + for entry in ns_map.get(node, [])[:3]: + if isinstance(entry, (list, tuple)) and len(entry) >= 2: + ns_parts.append(f\"{entry[0]}={entry[1]}\") + ns_text = \", \".join(ns_parts) + value_text = f\"{value:.2f}\" if isinstance(value, (int, float)) else str(value) + line = f\"hotspot.{metric}: node={node} class={node_class or 'unknown'} value={value_text}\" + if ns_text: + line += f\" namespaces_top={ns_text}\" + lines.append(line) + return lines + + def _extract_hottest_facts(lines: list[str], question: str) -> list[str]: if not lines: return []