Files
DEMO-AGENT/tests/test_audit.py

357 lines
11 KiB
Python

from django.urls import reverse
from agent_core.results import AgentResult
from apps.audit.models import AgentAuditLog, DemoBusinessRecord, NotificationRecord
from apps.audit.services import create_audit_log, create_notification_record
from apps.chat.models import Conversation
from agent_core.tools.builtin_tools import query_demo_records
def test_create_audit_log_records_success_result(db):
result = AgentResult(answer="回答", structured_output={"x": 1}, status="success")
log = create_audit_log("knowledge_qa", "知识库问答助手", "问题", result)
assert AgentAuditLog.objects.count() == 1
assert log.final_answer == "回答"
assert log.structured_output == {"x": 1}
assert log.status == "success"
def test_audit_list_page_shows_log(client, db):
result = AgentResult(answer="回答", status="success")
create_audit_log("knowledge_qa", "知识库问答助手", "问题", result)
response = client.get(reverse("audit:list"))
assert response.status_code == 200
assert "知识库问答助手" in response.content.decode("utf-8")
def test_audit_list_can_filter_by_scenario(client, db):
create_audit_log(
"knowledge_qa",
"知识库问答助手",
"制度问题",
AgentResult(answer="回答一", status="success"),
)
create_audit_log(
"quality_analysis",
"质量异常分析助手",
"质量问题",
AgentResult(answer="回答二", status="success"),
)
response = client.get(reverse("audit:list"), {"scenario_id": "knowledge_qa"})
content = response.content.decode("utf-8")
assert response.status_code == 200
assert "知识库问答助手" in content
assert "质量异常分析助手" not in content
def test_audit_list_page_shows_user_input_summary(client, db):
create_audit_log(
"knowledge_qa",
"知识库问答助手",
"这是一个比较长的用户输入,用于确认列表页会展示输入摘要。",
AgentResult(answer="回答", status="success"),
)
response = client.get(reverse("audit:list"))
assert "这是一个比较长的用户输入" in response.content.decode("utf-8")
def test_audit_detail_page_shows_raw_output(client, db):
result = AgentResult(
answer="结构化回答",
raw_output='{"answer":"结构化回答","confidence":"high"}',
status="success",
)
log = create_audit_log("knowledge_qa", "知识库问答助手", "问题", result)
response = client.get(reverse("audit:detail", args=[log.id]))
content = response.content.decode("utf-8")
assert response.status_code == 200
assert "原始输出" in content
assert "confidence" in content
assert "high" in content
def test_create_audit_log_masks_api_keys_from_error_message(db):
result = AgentResult(
answer="",
status="failed",
error="LLM_API_KEY=sk-secret-value 调用失败",
)
log = create_audit_log("knowledge_qa", "知识库问答助手", "问题", result)
assert "sk-secret-value" not in log.error_message
assert "sk-***" in log.error_message
def test_create_audit_log_masks_embedding_api_keys_from_error_message(db):
result = AgentResult(
answer="",
status="failed",
error="EMBEDDING_API_KEY=embed-secret 调用失败",
)
log = create_audit_log("knowledge_qa", "知识库问答助手", "问题", result)
assert "embed-secret" not in log.error_message
assert "EMBEDDING_API_KEY=***" in log.error_message
def test_query_demo_records_reads_demo_business_record_table(db):
DemoBusinessRecord.objects.create(
scenario_id="quality_analysis",
record_type="defect",
title="A线缺陷",
payload={"rate": 0.12},
)
result = query_demo_records(user_input="quality_analysis defect")
assert result["records"][0]["title"] == "A线缺陷"
assert result["records"][0]["payload"] == {"rate": 0.12}
def test_audit_log_records_batch_conversation_and_product_context(db):
result = AgentResult(answer="回答", status="success")
log = create_audit_log(
"document_review",
"注册审核智能体",
"开始审核",
result,
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="新型冠状病毒 2019-nCoV 核酸检测试剂盒",
)
assert log.batch_id == "SUB-20260604-001"
assert log.conversation_id == "conv-001"
assert log.product_name == "新型冠状病毒 2019-nCoV 核酸检测试剂盒"
def test_create_notification_record_persists_task_completed_and_task_failed(db):
completed = create_notification_record(
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
trigger_source="risk_report",
notify_reason="task_completed",
owner_role="注册资料负责人",
feishu_user_id="ou_demo_1",
message_status="sent",
web_detail_url="https://example.com/detail/1",
receipt={"message_id": "msg-1"},
)
failed = create_notification_record(
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
trigger_source="risk_report",
notify_reason="task_failed",
owner_role="注册资料负责人",
feishu_user_id="ou_demo_1",
message_status="failed",
web_detail_url="https://example.com/detail/1",
receipt={"message_id": "msg-2"},
)
assert NotificationRecord.objects.count() == 2
assert completed.notify_reason == "task_completed"
assert failed.notify_reason == "task_failed"
def test_audit_list_supports_batch_and_product_filters(client, db):
create_audit_log(
"document_review",
"注册审核智能体",
"问题一",
AgentResult(answer="回答一", status="success"),
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
)
create_audit_log(
"document_review",
"注册审核智能体",
"问题二",
AgentResult(answer="回答二", status="success"),
batch_id="SUB-20260604-002",
conversation_id="conv-002",
product_name="产品B",
)
response = client.get(reverse("audit:list"), {"keyword": "产品A"})
content = response.content.decode("utf-8")
assert response.status_code == 200
assert "产品A" in content
assert "产品B" not in content
def test_audit_list_shows_risk_and_notification_status(client, db):
create_audit_log(
"document_review",
"注册审核智能体",
"问题一",
AgentResult(
answer="回答一",
status="success",
structured_output={"highest_risk_level": "high"},
),
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
)
create_notification_record(
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
trigger_source="risk_report",
notify_reason="task_completed",
owner_role="注册资料负责人",
feishu_user_id="ou_demo_1",
message_status="sent",
web_detail_url="https://example.com/detail/1",
receipt={"message_id": "msg-1"},
)
response = client.get(reverse("audit:list"))
content = response.content.decode("utf-8")
assert response.status_code == 200
assert "风险状态" in content
assert "high" in content
assert "通知状态" in content
assert "sent" in content
assert "通知原因" in content
assert "task_completed" in content
def test_audit_list_can_filter_by_notification_status(client, db):
create_audit_log(
"document_review",
"注册审核智能体",
"问题一",
AgentResult(answer="回答一", status="success"),
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
)
create_audit_log(
"document_review",
"注册审核智能体",
"问题二",
AgentResult(answer="回答二", status="failed"),
batch_id="SUB-20260604-002",
conversation_id="conv-002",
product_name="产品B",
)
create_notification_record(
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
trigger_source="risk_report",
notify_reason="task_completed",
owner_role="注册资料负责人",
feishu_user_id="ou_demo_1",
message_status="sent",
web_detail_url="https://example.com/detail/1",
receipt={"message_id": "msg-1"},
)
create_notification_record(
batch_id="SUB-20260604-002",
conversation_id="conv-002",
product_name="产品B",
trigger_source="risk_report",
notify_reason="task_failed",
owner_role="注册资料负责人",
feishu_user_id="ou_demo_2",
message_status="failed",
web_detail_url="https://example.com/detail/2",
receipt={"message_id": "msg-2"},
)
response = client.get(reverse("audit:list"), {"notify_status": "failed"})
content = response.content.decode("utf-8")
assert response.status_code == 200
assert "产品B" in content
assert "产品A" not in content
def test_audit_list_can_filter_by_risk_status(client, db):
create_audit_log(
"document_review",
"注册审核智能体",
"问题一",
AgentResult(
answer="回答一",
status="success",
structured_output={"highest_risk_level": "high"},
),
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
)
create_audit_log(
"document_review",
"注册审核智能体",
"问题二",
AgentResult(
answer="回答二",
status="success",
structured_output={"highest_risk_level": "low"},
),
batch_id="SUB-20260604-002",
conversation_id="conv-002",
product_name="产品B",
)
response = client.get(reverse("audit:list"), {"risk_status": "high"})
content = response.content.decode("utf-8")
assert response.status_code == 200
assert "产品A" in content
assert "产品B" not in content
def test_audit_detail_page_shows_conversation_node_results(client, db):
Conversation.objects.create(
conversation_id="conv-001",
title="产品A",
product_name="产品A",
batch_id="SUB-20260604-001",
task_status="failed",
node_results=[
{"label": "资料包导入", "status": "已完成"},
{"label": "风险预警", "status": "已阻断"},
{"label": "飞书通知", "status": "失败"},
],
)
log = create_audit_log(
"document_review",
"注册审核智能体",
"问题一",
AgentResult(answer="回答一", status="failed"),
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
)
response = client.get(reverse("audit:detail", args=[log.id]))
content = response.content.decode("utf-8")
assert response.status_code == 200
assert "会话节点结果" in content
assert "风险预警 / 已阻断" in content
assert "飞书通知 / 失败" in content