atlasbot: prefer qualified longhorn node subsets

This commit is contained in:
Brad Stein 2026-03-30 17:32:46 -03:00
parent d22648ff27
commit d8c451dc80
2 changed files with 78 additions and 0 deletions

View File

@ -4112,6 +4112,7 @@ 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:
@ -4122,11 +4123,59 @@ def _fallback_fact_answer(prompt: str, context: str) -> str:
cp_nodes = _find_value("control_plane_nodes")
if cp_nodes:
return f"Control-plane nodes: {cp_nodes}."
if wants_longhorn:
for hw in include_hw:
best_nodes: list[str] = []
best_val = ""
for _fact, key, val in parsed_facts:
if not key or not val:
continue
key_tokens = set(_tokens(key))
if "longhorn" not in key_tokens:
continue
if hw not in key_tokens:
continue
nodes = _extract_titan_nodes(val)
if nodes and len(nodes) > len(best_nodes):
best_nodes = nodes
best_val = val
elif not best_nodes and val:
best_val = val
if best_nodes:
return f"{hw} longhorn nodes: {', '.join(best_nodes)}."
if best_val:
return f"{hw} longhorn nodes: {best_val}."
for hw in include_hw:
if wants_longhorn:
continue
hw_line = _find_value(hw)
if hw_line:
return f"{hw} nodes: {hw_line}."
if list_intent and "longhorn" in tokens:
best_nodes: list[str] = []
best_key = ""
best_val = ""
for _fact, key, val in parsed_facts:
if not key or not val:
continue
key_tokens = set(_tokens(key))
if "longhorn" not in key_tokens:
continue
nodes = _extract_titan_nodes(val)
if nodes and len(nodes) > len(best_nodes):
best_nodes = nodes
best_key = key
best_val = val
elif not best_nodes and val:
best_key = key
best_val = val
if best_nodes:
return f"Longhorn nodes: {', '.join(best_nodes)}."
if best_val:
label = (best_key or "Longhorn nodes").replace("_", " ").strip()
return f"{label.capitalize()}: {best_val}."
if list_intent and "control" in q:
cp_nodes = _find_value("control_plane_nodes")
if cp_nodes:

View File

@ -162,3 +162,32 @@ class AtlasbotModeTests(TestCase):
self.assertIn("worker nodes", reply.lower())
self.assertIn("Confidence:", reply)
def test_longhorn_rpi4_subset_beats_generic_rpi4_list(self):
fact_lines = [
"rpi4: titan-12, titan-13, titan-14, titan-15, titan-17, titan-18, titan-19",
"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, "_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)