-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathqa.py
More file actions
79 lines (64 loc) · 3.09 KB
/
Copy pathqa.py
File metadata and controls
79 lines (64 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
"""KB Builder Q&A handler — M3.5 (`ask_kb_builder` tool target).
This module exposes :func:`answer_kb_question`, a pure async function called by
the M4.6 Investigator orchestrator when it needs to look up a factual detail
from an equipment knowledge base.
Contract (see issue #21):
- **No DB writes.** The function only reads via :func:`mcp_client.call_tool`
(``get_equipment_kb``).
- **No WebSocket broadcasts.** All ``agent_handoff`` / ``agent_start`` /
``agent_end`` events are emitted by the M4.6 orchestrator wrapper. If this
function also broadcast, the Activity Feed would show duplicates.
- **Always Sonnet.** Uses ``model_for("chat")`` so a demo-day flip to
``ARIA_MODEL=opus`` does not silently 10x the cost of a simple factual lookup.
- **Safe fallback on failure.** Returns a ``{answer, source, confidence}`` dict
on every error path so the Investigator's tool loop can continue with an
``is_error=True`` ``tool_result`` rather than crashing the investigation.
"""
from __future__ import annotations
import logging
from agents.anthropic_client import anthropic, model_for, parse_json_response
from aria_mcp.client import mcp_client
_log = logging.getLogger("aria.kb_builder")
_KB_QUESTION_SYSTEM = (
"You answer factual questions from a colleague agent investigating an "
"equipment failure. Use the knowledge base below. If the information is "
"missing, say 'unknown' — do not guess. Response format: JSON object with "
"keys: answer (str), source (str|null), confidence (0.0-1.0)."
)
async def answer_kb_question(cell_id: int, question: str) -> dict:
"""Answer a factual KB question on behalf of the Investigator.
Args:
cell_id: The production cell whose equipment KB should be consulted.
question: Free-text question from the Investigator agent.
Returns:
``{"answer": str, "source": str | None, "confidence": float}``.
Always returns a dict — never raises — so the Investigator tool loop
can keep reasoning even if the KB is missing or the LLM call fails.
"""
try:
kb_result = await mcp_client.call_tool("get_equipment_kb", {"cell_id": cell_id})
if kb_result.is_error:
return {
"answer": f"KB not available for cell {cell_id}",
"source": None,
"confidence": 0.0,
}
response = await anthropic.messages.create(
model=model_for("chat"), # always Sonnet — see module docstring
max_tokens=1024,
system=_KB_QUESTION_SYSTEM,
messages=[
{
"role": "user",
"content": (f"Equipment KB:\n{kb_result.content}\n\nQuestion: {question}"),
}
],
)
return parse_json_response(response)
except Exception as exc: # noqa: BLE001 — safe fallback for tool-loop continuation
_log.warning("answer_kb_question failed for cell %d: %s", cell_id, exc)
return {
"answer": "KB query failed — information unavailable",
"source": None,
"confidence": 0.0,
}