atlasbot: enrich facts summary for LLM
This commit is contained in:
parent
a2f4c51e1d
commit
446115f07a
@ -16,7 +16,7 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: atlasbot
|
app: atlasbot
|
||||||
annotations:
|
annotations:
|
||||||
checksum/atlasbot-configmap: manual-atlasbot-30
|
checksum/atlasbot-configmap: manual-atlasbot-31
|
||||||
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"
|
||||||
|
|||||||
@ -723,24 +723,55 @@ def facts_context(
|
|||||||
"workloads": _workloads_for_facts(workloads or []),
|
"workloads": _workloads_for_facts(workloads or []),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
summary_lines: list[str] = []
|
||||||
|
nodes_info = facts.get("nodes") if isinstance(facts.get("nodes"), dict) else {}
|
||||||
|
if nodes_info.get("total") is not None:
|
||||||
|
summary_lines.append(
|
||||||
|
f"nodes_total={nodes_info.get('total')}, ready={nodes_info.get('ready')}, not_ready={nodes_info.get('not_ready')}"
|
||||||
|
)
|
||||||
|
hottest = facts.get("metrics", {}).get("hottest_nodes") if isinstance(facts.get("metrics"), dict) else {}
|
||||||
|
if isinstance(hottest, dict) and hottest:
|
||||||
|
for key in ("cpu", "ram", "net", "io"):
|
||||||
|
entry = hottest.get(key) if isinstance(hottest.get(key), dict) else {}
|
||||||
|
node = entry.get("node")
|
||||||
|
value = entry.get("value")
|
||||||
|
if node and value is not None:
|
||||||
|
summary_lines.append(f"hottest_{key}={node} ({value})")
|
||||||
|
postgres = facts.get("metrics", {}).get("postgres_connections") if isinstance(facts.get("metrics"), dict) else {}
|
||||||
|
if isinstance(postgres, dict) and postgres:
|
||||||
|
used = postgres.get("used")
|
||||||
|
max_conn = postgres.get("max")
|
||||||
|
if used is not None and max_conn is not None:
|
||||||
|
summary_lines.append(f"postgres_used={used}, postgres_max={max_conn}")
|
||||||
|
hottest_db = postgres.get("hottest_db") if isinstance(postgres.get("hottest_db"), dict) else {}
|
||||||
|
if hottest_db.get("label"):
|
||||||
|
summary_lines.append(f"postgres_hottest_db={hottest_db.get('label')} ({hottest_db.get('value')})")
|
||||||
|
|
||||||
rendered = json.dumps(facts, ensure_ascii=False)
|
rendered = json.dumps(facts, ensure_ascii=False)
|
||||||
if len(rendered) <= MAX_FACTS_CHARS:
|
rendered_parts = []
|
||||||
return "Facts (live snapshot):\n" + rendered
|
if summary_lines:
|
||||||
|
rendered_parts.append("Facts summary:\n" + "\n".join(f"- {line}" for line in summary_lines))
|
||||||
|
rendered_parts.append("Facts (live snapshot JSON):\n" + rendered)
|
||||||
|
combined = "\n\n".join(rendered_parts)
|
||||||
|
if len(combined) <= MAX_FACTS_CHARS:
|
||||||
|
return combined
|
||||||
|
|
||||||
trimmed = dict(facts)
|
trimmed = dict(facts)
|
||||||
trimmed.pop("workloads", None)
|
trimmed.pop("workloads", None)
|
||||||
rendered = json.dumps(trimmed, ensure_ascii=False)
|
rendered = json.dumps(trimmed, ensure_ascii=False)
|
||||||
if len(rendered) <= MAX_FACTS_CHARS:
|
combined = "\n\n".join(rendered_parts[:-1] + ["Facts (live snapshot JSON):\n" + rendered])
|
||||||
return "Facts (live snapshot):\n" + rendered
|
if len(combined) <= MAX_FACTS_CHARS:
|
||||||
|
return combined
|
||||||
|
|
||||||
trimmed_metrics = dict(trimmed.get("metrics") or {})
|
trimmed_metrics = dict(trimmed.get("metrics") or {})
|
||||||
trimmed_metrics.pop("node_usage", None)
|
trimmed_metrics.pop("node_usage", None)
|
||||||
trimmed["metrics"] = trimmed_metrics
|
trimmed["metrics"] = trimmed_metrics
|
||||||
rendered = json.dumps(trimmed, ensure_ascii=False)
|
rendered = json.dumps(trimmed, ensure_ascii=False)
|
||||||
if len(rendered) <= MAX_FACTS_CHARS:
|
combined = "\n\n".join(rendered_parts[:-1] + ["Facts (live snapshot JSON):\n" + rendered])
|
||||||
return "Facts (live snapshot):\n" + rendered
|
if len(combined) <= MAX_FACTS_CHARS:
|
||||||
|
return combined
|
||||||
|
|
||||||
return "Facts (live snapshot):\n" + rendered[:MAX_FACTS_CHARS]
|
return combined[:MAX_FACTS_CHARS]
|
||||||
|
|
||||||
def _inventory_sets(inventory: list[dict[str, Any]]) -> dict[str, Any]:
|
def _inventory_sets(inventory: list[dict[str, Any]]) -> dict[str, Any]:
|
||||||
names = [node["name"] for node in inventory]
|
names = [node["name"] for node in inventory]
|
||||||
@ -1724,6 +1755,7 @@ def _ollama_call(hist_key, prompt: str, *, context: str) -> str:
|
|||||||
"System: You are Atlas, the Titan lab assistant for Atlas/Othrys. "
|
"System: You are Atlas, the Titan lab assistant for Atlas/Othrys. "
|
||||||
"Be helpful, direct, and concise. "
|
"Be helpful, direct, and concise. "
|
||||||
"Use the provided context and facts as your source of truth. "
|
"Use the provided context and facts as your source of truth. "
|
||||||
|
"Treat 'hottest' as highest utilization (CPU/RAM/NET/IO) rather than temperature. "
|
||||||
"If you infer or synthesize, say 'Based on the snapshot' and keep it brief. "
|
"If you infer or synthesize, say 'Based on the snapshot' and keep it brief. "
|
||||||
"Prefer exact repo paths and Kubernetes resource names when relevant. "
|
"Prefer exact repo paths and Kubernetes resource names when relevant. "
|
||||||
"Never include or request secret values. "
|
"Never include or request secret values. "
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user