diff --git a/atlasbot/llm/prompts.py b/atlasbot/llm/prompts.py index f5de38c..74eae38 100644 --- a/atlasbot/llm/prompts.py +++ b/atlasbot/llm/prompts.py @@ -99,7 +99,9 @@ EVIDENCE_FIX_PROMPT = ( "Check the draft against the context. " "If the draft says data is missing but the context includes relevant values, " "rewrite the answer to include those values. " - "If data is truly missing, keep the draft concise and honest." + "If data is truly missing, keep the draft concise and honest. " + "If AllowedRunbooks are provided, use an exact path from that list when answering " + "documentation or checklist questions and do not invent new paths." ) DRAFT_SELECT_PROMPT = ( diff --git a/atlasbot/snapshot/builder.py b/atlasbot/snapshot/builder.py index d55ce2b..eaec939 100644 --- a/atlasbot/snapshot/builder.py +++ b/atlasbot/snapshot/builder.py @@ -104,6 +104,7 @@ def build_summary(snapshot: dict[str, Any] | None) -> dict[str, Any]: summary.update(_build_workloads(snapshot)) summary.update(_build_flux(snapshot)) _merge_cluster_summary(snapshot, summary) + _augment_lexicon(summary) return summary @@ -131,6 +132,37 @@ def _merge_cluster_summary(snapshot: dict[str, Any], summary: dict[str, Any]) -> summary["cross_stats"] = cross_stats +def _augment_lexicon(summary: dict[str, Any]) -> None: + lexicon = summary.get("lexicon") + if not isinstance(lexicon, dict): + lexicon = {"terms": [], "aliases": {}} + terms = list(lexicon.get("terms") or []) + aliases = dict(lexicon.get("aliases") or {}) + hardware = summary.get("hardware") if isinstance(summary.get("hardware"), dict) else {} + hardware_map = { + "rpi5": "Raspberry Pi 5 nodes", + "rpi4": "Raspberry Pi 4 nodes", + "rpi": "Raspberry Pi nodes", + "jetson": "NVIDIA Jetson nodes", + "amd64": "AMD64 nodes", + } + existing_terms = {entry.get("term") for entry in terms if isinstance(entry, dict)} + for key, meaning in hardware_map.items(): + if key not in hardware: + continue + if key not in existing_terms: + terms.append({"term": key, "meaning": meaning}) + if key not in aliases: + aliases[key] = meaning + if "raspberry pi 5" not in aliases and "rpi5" in hardware: + aliases["raspberry pi 5"] = "rpi5" + if "raspberry pi 4" not in aliases and "rpi4" in hardware: + aliases["raspberry pi 4"] = "rpi4" + lexicon["terms"] = terms + lexicon["aliases"] = aliases + summary["lexicon"] = lexicon + + def _nodes_detail(snapshot: dict[str, Any]) -> list[dict[str, Any]]: items = snapshot.get("nodes_detail") return items if isinstance(items, list) else []