atlasbot: strengthen subjective insights

This commit is contained in:
Brad Stein 2026-01-27 19:37:20 -03:00
parent 8842662239
commit 20364a262c
2 changed files with 40 additions and 20 deletions

View File

@ -16,7 +16,7 @@ spec:
labels: labels:
app: atlasbot app: atlasbot
annotations: annotations:
checksum/atlasbot-configmap: manual-atlasbot-66 checksum/atlasbot-configmap: manual-atlasbot-67
vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "comms" vault.hashicorp.com/role: "comms"
vault.hashicorp.com/agent-inject-secret-turn-secret: "kv/data/atlas/comms/turn-shared-secret" vault.hashicorp.com/agent-inject-secret-turn-secret: "kv/data/atlas/comms/turn-shared-secret"

View File

@ -579,6 +579,10 @@ def _detect_entity(q: str) -> str | None:
or "architecture" in q or "architecture" in q
or "machine" in q or "machine" in q
or "machines" in q or "machines" in q
or "host" in q
or "hosts" in q
or "hostname" in q
or "hostnames" in q
or TITAN_NODE_RE.search(q) or TITAN_NODE_RE.search(q)
): ):
return "node" return "node"
@ -1775,20 +1779,29 @@ def _format_insight_text(key: str, text: str) -> str:
.strip() .strip()
.strip(".") .strip(".")
) )
has_jetson = "jetson=" in counts
has_amd64 = "amd64=" in counts
detail = f"mixed hardware stack ({counts})" detail = f"mixed hardware stack ({counts})"
flavor = "It blends low-power Pis with Jetson accelerators and a couple of AMD64 nodes." if has_jetson and has_amd64:
flavor = "It blends low-power Pis with Jetson accelerators and a couple of AMD64 boxes."
elif has_jetson:
flavor = "It pairs low-power Pis with Jetson accelerators for edge and AI workloads."
elif has_amd64:
flavor = "It mixes low-power Pis with a couple of heavier AMD64 nodes."
else:
flavor = "It is a pretty uniform hardware stack, which is rare for a homelab."
return f"{detail}. {flavor}" return f"{detail}. {flavor}"
if key == "postgres": if key == "postgres":
detail = cleaned.replace("Postgres is at ", "") detail = cleaned.replace("Postgres is at ", "")
return f"Postgres is at {detail}; that suggests moderate load." return f"Postgres is at {detail}; that feels like healthy, steady load rather than strain."
if key == "pods": if key == "pods":
detail = cleaned.replace("There are ", "") detail = cleaned.replace("There are ", "")
return f"Pods look steady ({detail}); the workload mix looks healthy." return f"Pods look steady ({detail}); nothing looks stuck or unhealthy."
if key == "availability": if key == "availability":
return cleaned + " That suggests the cluster is stable right now." return cleaned + " That is the kind of stability I like to see."
if key in ("cpu", "ram"): if key in ("cpu", "ram"):
suffix = ( suffix = (
" If you're chasing hotspots, that's the busiest workload right now." " If you're chasing hotspots, that's the node I'd watch first."
if key == "cpu" if key == "cpu"
else " That box is carrying the heaviest memory load right now." else " That box is carrying the heaviest memory load right now."
) )
@ -1799,19 +1812,19 @@ def _format_insight_text(key: str, text: str) -> str:
def _insight_prefix(prompt: str) -> str: def _insight_prefix(prompt: str) -> str:
q = normalize_query(prompt) q = normalize_query(prompt)
if "coolest" in q: if "coolest" in q:
return "If I had to pick the coolest detail: " return "If I had to pick the coolest detail, I'd say "
if "favorite" in q or "favourite" in q: if "favorite" in q or "favourite" in q:
return "My favorite detail: " return "My favorite detail is "
if "trivia" in q: if "trivia" in q:
return "A bit of trivia I like: " return "A bit of trivia I like: "
if "most interesting" in q: if "most interesting" in q:
return "The most interesting detail to me: " return "The most interesting detail to me is "
if any(word in q for word in ("another", "else", "different", "other")): if any(word in q for word in ("another", "else", "different", "other")):
return "Another interesting detail: " return "Another interesting detail: "
if any(word in q for word in ("unconventional", "weird", "odd", "unique", "surprising")): if any(word in q for word in ("unconventional", "weird", "odd", "unique", "surprising")):
return "What stands out is that " return "What stands out to me is that "
if any(word in q for word in ("interesting", "notable", "fun", "cool")): if any(word in q for word in ("interesting", "notable", "fun", "cool")):
return "One thing I'd highlight: " return "One thing I'd call out is "
return "" return ""
@ -2389,6 +2402,21 @@ def _normalize_reply(value: Any) -> str:
return _ensure_confidence(text) return _ensure_confidence(text)
def _history_payload_lines(history_payload: list[Any]) -> list[str]:
lines: list[str] = []
if not isinstance(history_payload, list):
return lines
for item in history_payload[-12:]:
if isinstance(item, dict):
for key in ("content", "message", "text", "prompt", "question", "body", "answer", "reply", "response"):
val = item.get(key)
if isinstance(val, str) and val.strip():
lines.append(val.strip())
elif isinstance(item, str) and item.strip():
lines.append(item.strip())
return [line for line in lines if line]
# Internal HTTP endpoint for cluster answers (website uses this). # Internal HTTP endpoint for cluster answers (website uses this).
class _AtlasbotHandler(BaseHTTPRequestHandler): class _AtlasbotHandler(BaseHTTPRequestHandler):
server_version = "AtlasbotHTTP/1.0" server_version = "AtlasbotHTTP/1.0"
@ -2439,15 +2467,7 @@ class _AtlasbotHandler(BaseHTTPRequestHandler):
inventory = _snapshot_inventory(snapshot) or node_inventory_live() inventory = _snapshot_inventory(snapshot) or node_inventory_live()
workloads = _snapshot_workloads(snapshot) workloads = _snapshot_workloads(snapshot)
history_payload = payload.get("history") or [] history_payload = payload.get("history") or []
history_lines: list[str] = [] history_lines = _history_payload_lines(history_payload)
if isinstance(history_payload, list):
for item in history_payload[-10:]:
if isinstance(item, dict):
content = item.get("content") or item.get("message") or ""
if isinstance(content, str) and content.strip():
history_lines.append(content.strip())
elif isinstance(item, str) and item.strip():
history_lines.append(item.strip())
history_cluster = _history_mentions_cluster( history_cluster = _history_mentions_cluster(
history_lines, history_lines,
inventory=inventory, inventory=inventory,