fix: 实现 Agent 修复验证闭环
This commit is contained in:
@@ -13,7 +13,7 @@ class DiagnosticAgentTest(unittest.TestCase):
|
||||
def test_executes_read_only_tool_and_returns_final_answer(self):
|
||||
responses = iter([
|
||||
'{"action":"command","command":"kubectl get pods -A","reason":"查看异常 Pod"}',
|
||||
'{"action":"final","analysis":"发现一个异常 Pod"}',
|
||||
'{"action":"final","analysis":"发现一个异常 Pod","verified":true,"remaining_issues":0}',
|
||||
])
|
||||
|
||||
async def fake_completion(messages):
|
||||
@@ -90,7 +90,7 @@ class DiagnosticAgentTest(unittest.TestCase):
|
||||
|
||||
def test_ai_mode_forces_initial_read_only_probe_before_model_planning(self):
|
||||
responses = iter([
|
||||
'{"action":"final","analysis":"根据采集结果完成分析"}',
|
||||
'{"action":"final","analysis":"根据采集结果完成分析","verified":true,"remaining_issues":0}',
|
||||
])
|
||||
|
||||
async def fake_completion(messages):
|
||||
@@ -131,7 +131,7 @@ class DiagnosticAgentTest(unittest.TestCase):
|
||||
)
|
||||
for index in range(command_count)
|
||||
],
|
||||
'{"action":"final","analysis":"已完成根因分析"}',
|
||||
'{"action":"final","analysis":"已完成根因分析","verified":true,"remaining_issues":0}',
|
||||
])
|
||||
executed = []
|
||||
|
||||
@@ -168,6 +168,44 @@ class DiagnosticAgentTest(unittest.TestCase):
|
||||
self.assertIn("安全上限", events[-1]["message"])
|
||||
self.assertNotIn("人工排查", events[-1]["message"])
|
||||
|
||||
def test_agent_rejects_final_until_verification_reports_no_remaining_issues(self):
|
||||
responses = iter([
|
||||
'{"action":"final","analysis":"已经修复"}',
|
||||
'{"action":"command","command":"kubectl get pods -A","reason":"执行全量复检"}',
|
||||
'{"action":"final","analysis":"所有工作负载恢复正常","verified":true,"remaining_issues":0}',
|
||||
])
|
||||
executed = []
|
||||
|
||||
async def fake_completion(messages):
|
||||
return next(responses)
|
||||
|
||||
async def fake_execute(command):
|
||||
executed.append(command)
|
||||
stdout = "node-a Ready" if command == "kubectl get nodes -o wide" else "all pods Running"
|
||||
return {"command": command, "mode": "read", "returncode": 0, "stdout": stdout, "stderr": ""}
|
||||
|
||||
async def run():
|
||||
with patch("backend.ai_agent._complete_chat", fake_completion), patch("backend.ai_agent.execute_kubectl", fake_execute):
|
||||
return await collect_events(run_diagnostic_agent("report", execution_mode="ai", max_steps=5))
|
||||
|
||||
events = asyncio.run(run())
|
||||
self.assertEqual(executed, ["kubectl get nodes -o wide", "kubectl get pods -A"])
|
||||
self.assertEqual(events[-1]["type"], "final")
|
||||
self.assertTrue(events[-1]["verified"])
|
||||
self.assertEqual(events[-1]["remaining_issues"], 0)
|
||||
|
||||
def test_parse_final_requires_explicit_verification_fields(self):
|
||||
from backend.ai_agent import _parse_agent_action
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
_parse_agent_action('{"action":"final","analysis":"看起来正常"}')
|
||||
|
||||
action = _parse_agent_action(
|
||||
'{"action":"final","analysis":"全部正常","verified":true,"remaining_issues":0}'
|
||||
)
|
||||
self.assertTrue(action["verified"])
|
||||
self.assertEqual(action["remaining_issues"], 0)
|
||||
|
||||
def test_stops_when_model_returns_invalid_action(self):
|
||||
async def fake_completion(messages):
|
||||
return "not-json"
|
||||
|
||||
Reference in New Issue
Block a user