atlasbot: enforce longhorn-qualified fallback matches

This commit is contained in:
Brad Stein 2026-03-30 17:38:20 -03:00
parent 97f7073f82
commit fd0d03b0dd
2 changed files with 54 additions and 1 deletions

View File

@ -2125,6 +2125,9 @@ def _doc_intent(query: str) -> bool:
"triage",
"recover",
"remediate",
"longhorn",
"astreae",
"asteria",
)
)
@ -4061,6 +4064,7 @@ def _fallback_fact_answer(prompt: str, context: str) -> str:
hottest_intent = any(word in q for word in ("hottest", "highest", "most", "top", "busiest"))
metric = _detect_metric(q)
include_hw, _exclude_hw = _detect_hardware_filters(q)
wants_longhorn = any(word in tokens for word in ("longhorn", "astreae", "asteria"))
if hottest_intent and metric in {"cpu", "ram", "net", "io"}:
hottest_val = _find_value(f"hottest_{metric}")
@ -4099,6 +4103,18 @@ def _fallback_fact_answer(prompt: str, context: str) -> str:
return f"Not ready nodes: {match.group(1)}."
if count_intent and include_hw:
if wants_longhorn:
for hw in include_hw:
for fact, key, val in parsed_facts:
key_tokens = set(_tokens(key or fact))
if "longhorn" not in key_tokens:
continue
if hw not in key_tokens:
continue
nodes = _extract_titan_nodes(val or fact)
if nodes:
return f"{hw} longhorn nodes: {len(nodes)}."
return ""
counts_line = _find_value("nodes_by_hardware_count")
if counts_line:
counts = _parse_counts(counts_line)
@ -4112,7 +4128,6 @@ def _fallback_fact_answer(prompt: str, context: str) -> str:
return f"{hw} nodes: {len(items)}."
if list_intent and include_hw:
wants_longhorn = "longhorn" in tokens
if "control" in q:
cp_by_hw = _find_value("control_plane_by_hardware")
if cp_by_hw:
@ -4206,6 +4221,10 @@ def _fallback_fact_answer(prompt: str, context: str) -> str:
best_fact = ""
best_score = -1
for fact in facts:
if wants_longhorn:
fact_tokens = set(_tokens(fact))
if not ({"longhorn", "astreae", "asteria"} & fact_tokens):
continue
key_match = re.match(r"^([\w\s/.-]+):\s*(.+)$", fact)
if not key_match:
key_match = re.match(r"^([\w\s/.-]+)=\s*(.+)$", fact)

View File

@ -191,3 +191,37 @@ class AtlasbotModeTests(TestCase):
self.assertNotIn("titan-14", reply)
self.assertNotIn("titan-18", reply)
self.assertIn("Confidence:", reply)
def test_longhorn_query_uses_kb_context_when_snapshot_only_has_generic_rpi4(self):
fact_lines = [
"rpi4: titan-12, titan-13, titan-14, titan-15, titan-17, titan-18, titan-19",
]
kb_detail = (
"Atlas KB (retrieved):\n"
"- metis (knowledge/metis.md)\n"
"rpi4 armbian longhorn: titan-13/15/17/19"
)
with (
mock.patch.object(self.bot, "_fact_pack_lines", return_value=fact_lines),
mock.patch.object(self.bot, "kb_retrieve", return_value=kb_detail),
mock.patch.object(self.bot, "_ollama_call", side_effect=AssertionError("LLM should not be called")),
):
reply = self.bot.open_ended_answer(
"which nodes in titan are the rpi4 longhorn nodes?",
inventory=[],
snapshot=None,
workloads=[],
history_lines=[],
mode="smart",
allow_tools=True,
)
self.assertIn("titan-13", reply)
self.assertIn("titan-15", reply)
self.assertIn("titan-17", reply)
self.assertIn("titan-19", reply)
self.assertNotIn("titan-12", reply)
self.assertNotIn("titan-14", reply)
self.assertNotIn("titan-18", reply)
self.assertIn("Confidence:", reply)