150 lines
5.7 KiB
Python
150 lines
5.7 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from datetime import UTC, datetime, timedelta
|
||
|
|
|
||
|
|
from sqlalchemy import create_engine
|
||
|
|
from sqlalchemy.orm import Session, sessionmaker
|
||
|
|
from sqlalchemy.pool import StaticPool
|
||
|
|
|
||
|
|
from app.db.base import Base
|
||
|
|
from app.models.agent_feedback import AgentOperationFeedback
|
||
|
|
from app.models.agent_run import AgentRun, AgentToolCall
|
||
|
|
from app.models.user_session_metric import UserSessionMetric
|
||
|
|
from app.services.system_dashboard import SystemDashboardService
|
||
|
|
|
||
|
|
|
||
|
|
def build_session() -> Session:
|
||
|
|
engine = create_engine(
|
||
|
|
"sqlite+pysqlite:///:memory:",
|
||
|
|
connect_args={"check_same_thread": False},
|
||
|
|
poolclass=StaticPool,
|
||
|
|
)
|
||
|
|
Base.metadata.create_all(bind=engine)
|
||
|
|
session_factory = sessionmaker(bind=engine, autoflush=False, autocommit=False)
|
||
|
|
return session_factory()
|
||
|
|
|
||
|
|
|
||
|
|
def test_system_dashboard_service_aggregates_real_runtime_metrics() -> None:
|
||
|
|
now = datetime.now(UTC)
|
||
|
|
|
||
|
|
with build_session() as db:
|
||
|
|
db.add(
|
||
|
|
AgentRun(
|
||
|
|
run_id="run-dashboard-001",
|
||
|
|
agent="orchestrator",
|
||
|
|
source="user_message",
|
||
|
|
user_id="chen.yuqing@example.com",
|
||
|
|
status="succeeded",
|
||
|
|
started_at=now - timedelta(hours=3),
|
||
|
|
finished_at=now - timedelta(hours=3, minutes=-1),
|
||
|
|
tool_calls=[
|
||
|
|
AgentToolCall(
|
||
|
|
run_id="run-dashboard-001",
|
||
|
|
tool_type="llm",
|
||
|
|
tool_name="expense_claim.review",
|
||
|
|
request_json={"prompt_tokens": 120},
|
||
|
|
response_json={"completion_tokens": 80},
|
||
|
|
status="succeeded",
|
||
|
|
duration_ms=1800,
|
||
|
|
created_at=now - timedelta(hours=3),
|
||
|
|
),
|
||
|
|
AgentToolCall(
|
||
|
|
run_id="run-dashboard-001",
|
||
|
|
tool_type="ocr",
|
||
|
|
tool_name="invoice.ocr",
|
||
|
|
request_json={"image_count": 1},
|
||
|
|
response_json={"message": "识别失败"},
|
||
|
|
status="failed",
|
||
|
|
duration_ms=2600,
|
||
|
|
error_message="low confidence",
|
||
|
|
created_at=now - timedelta(hours=2),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
)
|
||
|
|
db.add(
|
||
|
|
AgentRun(
|
||
|
|
run_id="run-dashboard-002",
|
||
|
|
agent="hermes",
|
||
|
|
source="schedule",
|
||
|
|
user_id="gu.chengyu@example.com",
|
||
|
|
status="failed",
|
||
|
|
started_at=now - timedelta(hours=1),
|
||
|
|
finished_at=now,
|
||
|
|
tool_calls=[
|
||
|
|
AgentToolCall(
|
||
|
|
run_id="run-dashboard-002",
|
||
|
|
tool_type="knowledge",
|
||
|
|
tool_name="policy.rag",
|
||
|
|
request_json={"total_tokens": 90},
|
||
|
|
response_json={},
|
||
|
|
status="succeeded",
|
||
|
|
duration_ms=900,
|
||
|
|
created_at=now - timedelta(hours=1),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
)
|
||
|
|
db.add_all(
|
||
|
|
[
|
||
|
|
UserSessionMetric(
|
||
|
|
session_id="session-dashboard-001",
|
||
|
|
username="chen.yuqing@example.com",
|
||
|
|
display_name="陈雨晴",
|
||
|
|
email="chen.yuqing@example.com",
|
||
|
|
login_at=now - timedelta(hours=4),
|
||
|
|
logout_at=now - timedelta(hours=3),
|
||
|
|
duration_ms=60 * 60 * 1000,
|
||
|
|
activity_event_count=16,
|
||
|
|
status="closed",
|
||
|
|
),
|
||
|
|
UserSessionMetric(
|
||
|
|
session_id="session-dashboard-002",
|
||
|
|
username="gu.chengyu@example.com",
|
||
|
|
display_name="顾成宇",
|
||
|
|
email="gu.chengyu@example.com",
|
||
|
|
login_at=now - timedelta(minutes=25),
|
||
|
|
last_activity_at=now - timedelta(minutes=5),
|
||
|
|
activity_event_count=9,
|
||
|
|
status="active",
|
||
|
|
),
|
||
|
|
]
|
||
|
|
)
|
||
|
|
db.add_all(
|
||
|
|
[
|
||
|
|
AgentOperationFeedback(
|
||
|
|
run_id="run-dashboard-001",
|
||
|
|
user_id="chen.yuqing@example.com",
|
||
|
|
agent="orchestrator",
|
||
|
|
rating=5,
|
||
|
|
created_at=now - timedelta(hours=2),
|
||
|
|
),
|
||
|
|
AgentOperationFeedback(
|
||
|
|
run_id="run-dashboard-002",
|
||
|
|
user_id="gu.chengyu@example.com",
|
||
|
|
agent="hermes",
|
||
|
|
rating=2,
|
||
|
|
created_at=now - timedelta(hours=1),
|
||
|
|
),
|
||
|
|
]
|
||
|
|
)
|
||
|
|
db.commit()
|
||
|
|
|
||
|
|
dashboard = SystemDashboardService(db).build_dashboard(days=7)
|
||
|
|
|
||
|
|
assert dashboard.has_real_data is True
|
||
|
|
assert dashboard.totals["toolCalls"] == 3
|
||
|
|
assert dashboard.totals["modelTokens"] >= 290
|
||
|
|
assert dashboard.totals["onlineUsers"] == 1
|
||
|
|
assert dashboard.totals["executionSuccessRate"] == 50.0
|
||
|
|
assert dashboard.totals["positiveFeedback"] == 1
|
||
|
|
assert dashboard.totals["negativeFeedback"] == 1
|
||
|
|
assert dashboard.user_token_usage[0]["tokens"] >= 200
|
||
|
|
assert "陈雨晴" in {item["name"] for item in dashboard.user_token_usage}
|
||
|
|
assert dashboard.accuracy_comparison["correct"][
|
||
|
|
dashboard.accuracy_comparison["categories"].index("报销预审")
|
||
|
|
] == 1
|
||
|
|
assert dashboard.accuracy_comparison["wrong"][
|
||
|
|
dashboard.accuracy_comparison["categories"].index("异常诊断")
|
||
|
|
] == 1
|