atlasbot: route subjective queries to LLM
This commit is contained in:
parent
18e543d95a
commit
9e06d7afc8
@ -16,7 +16,7 @@ spec:
|
||||
labels:
|
||||
app: atlasbot
|
||||
annotations:
|
||||
checksum/atlasbot-configmap: manual-atlasbot-68
|
||||
checksum/atlasbot-configmap: manual-atlasbot-69
|
||||
vault.hashicorp.com/agent-inject: "true"
|
||||
vault.hashicorp.com/role: "comms"
|
||||
vault.hashicorp.com/agent-inject-secret-turn-secret: "kv/data/atlas/comms/turn-shared-secret"
|
||||
|
||||
@ -1911,19 +1911,6 @@ def cluster_answer(
|
||||
history_lines: list[str] | None = None,
|
||||
) -> str:
|
||||
metrics_summary = snapshot_context(prompt, snapshot)
|
||||
if _is_insight_query(prompt):
|
||||
candidates = _insight_candidates(inventory, snapshot)
|
||||
used_keys = _recent_insight_keys(history_lines or [])
|
||||
selected = _select_insight(prompt, candidates, used_keys=used_keys)
|
||||
if selected:
|
||||
key, raw_text, confidence = selected
|
||||
formatted = _format_insight_text(key, raw_text)
|
||||
if not formatted:
|
||||
formatted = raw_text
|
||||
prefix = _insight_prefix(prompt)
|
||||
if prefix:
|
||||
formatted = prefix + formatted
|
||||
return _format_confidence(formatted, confidence)
|
||||
structured = structured_answer(
|
||||
prompt,
|
||||
inventory=inventory,
|
||||
@ -2422,6 +2409,17 @@ def _history_payload_lines(history_payload: list[Any]) -> list[str]:
|
||||
return [line for line in lines if line]
|
||||
|
||||
|
||||
def _append_history_context(context: str, history_lines: list[str]) -> str:
|
||||
lines = [line.strip() for line in history_lines if isinstance(line, str) and line.strip()]
|
||||
if not lines:
|
||||
return context
|
||||
snippet = "\n".join(lines[-6:])
|
||||
combined = context + "\nRecent chat:\n" + snippet if context else "Recent chat:\n" + snippet
|
||||
if len(combined) > MAX_CONTEXT_CHARS:
|
||||
combined = combined[: MAX_CONTEXT_CHARS - 3].rstrip() + "..."
|
||||
return combined
|
||||
|
||||
|
||||
# Internal HTTP endpoint for cluster answers (website uses this).
|
||||
class _AtlasbotHandler(BaseHTTPRequestHandler):
|
||||
server_version = "AtlasbotHTTP/1.0"
|
||||
@ -2493,15 +2491,25 @@ class _AtlasbotHandler(BaseHTTPRequestHandler):
|
||||
)
|
||||
fallback = "I don't have enough data to answer that."
|
||||
if cluster_query:
|
||||
answer = cluster_answer(
|
||||
facts_answer = cluster_answer(
|
||||
cleaned,
|
||||
inventory=inventory,
|
||||
snapshot=snapshot,
|
||||
workloads=workloads,
|
||||
history_lines=history_lines,
|
||||
)
|
||||
if not answer:
|
||||
answer = fallback
|
||||
open_ended = _is_subjective_query(cleaned) or _knowledge_intent(cleaned)
|
||||
if open_ended:
|
||||
llm_context = _append_history_context(context, history_lines)
|
||||
answer = ollama_reply(
|
||||
("http", "internal"),
|
||||
cleaned,
|
||||
context=llm_context,
|
||||
fallback=facts_answer or fallback,
|
||||
use_history=False,
|
||||
)
|
||||
else:
|
||||
answer = facts_answer or fallback
|
||||
else:
|
||||
llm_prompt = cleaned
|
||||
answer = ollama_reply(
|
||||
@ -2761,11 +2769,13 @@ def _ollama_call(hist_key, prompt: str, *, context: str, use_history: bool = Tru
|
||||
"When a cluster snapshot is provided, never answer about unrelated meanings of 'Atlas' (maps, mythology, Apache Atlas, etc). "
|
||||
"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. "
|
||||
"For subjective prompts (interesting, favorite, unconventional), pick one or two observations from the context, explain why they stand out in 1-2 sentences, and avoid repeating the same observation as the last response if you can. "
|
||||
"Prefer exact repo paths and Kubernetes resource names when relevant. "
|
||||
"Never include or request secret values. "
|
||||
"Do not suggest commands unless explicitly asked. "
|
||||
"Respond in plain sentences; do not return JSON or code fences unless explicitly asked. "
|
||||
"Translate metrics into natural language instead of echoing raw label/value pairs. "
|
||||
"Avoid bare lists unless the user asked for a list; weave numbers into sentences. "
|
||||
"Do not answer by only listing runbooks; if the question is about Atlas/Othrys, summarize the cluster first and mention docs only if useful. "
|
||||
"If the question is not about Atlas/Othrys and no cluster context is provided, answer using general knowledge and say when you are unsure. "
|
||||
"If the answer is not grounded in the provided context or tool data, say you do not know. "
|
||||
@ -2974,15 +2984,27 @@ def sync_loop(token: str, room_id: str):
|
||||
fallback = "I don't have enough data to answer that."
|
||||
|
||||
if cluster_query:
|
||||
reply = cluster_answer(
|
||||
facts_answer = cluster_answer(
|
||||
cleaned_body,
|
||||
inventory=inventory,
|
||||
snapshot=snapshot,
|
||||
workloads=workloads,
|
||||
history_lines=history[hist_key],
|
||||
)
|
||||
if not reply:
|
||||
reply = fallback
|
||||
open_ended = _is_subjective_query(cleaned_body) or _knowledge_intent(cleaned_body)
|
||||
if open_ended:
|
||||
llm_context = _append_history_context(context, history[hist_key])
|
||||
reply = ollama_reply_with_thinking(
|
||||
token,
|
||||
rid,
|
||||
hist_key,
|
||||
cleaned_body,
|
||||
context=llm_context,
|
||||
fallback=facts_answer or fallback,
|
||||
use_history=False,
|
||||
)
|
||||
else:
|
||||
reply = facts_answer or fallback
|
||||
else:
|
||||
llm_prompt = cleaned_body
|
||||
reply = ollama_reply_with_thinking(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user