feat(analyst): Add sample and escalate functionality to analyst API

- Introduced new endpoints `/api/analyst/query/{trace_id}/sample` and `/api/analyst/escalate` for sampling query results and escalating issues to human analysts, respectively.
- Enhanced `AnalystAgent` to support sampling of SQL results based on trace ID and to handle escalation requests, improving user experience in error scenarios.
- Updated `analyst_schemas.py` to include `EscalateRequest` for structured escalation requests.
- Added corresponding frontend API calls and UI components to facilitate user interactions with the new features.
- Implemented unit tests to ensure the reliability of the new functionalities.

This update significantly enhances the analytical capabilities of the application, allowing users to retrieve detailed query samples and escalate issues effectively.
This commit is contained in:
2026-09-11 15:18:56 +08:00
parent 0fb7d34d7a
commit 8556da489a
27 changed files with 656 additions and 42 deletions
+40
View File
@@ -0,0 +1,40 @@
"""C-04 演示:扫描已配置阈值的客户,命中则 Redis pub + 控制台输出。
用法:python scripts/demo/push_threshold_alerts.py
需 MySQL 演示库 + Redis 6380。
"""
from __future__ import annotations
import json
import os
import sys
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.insert(0, ROOT)
from app.repository.core_ro import CoreReadOnlyRepository
from app.repository.threshold_repository import ThresholdRepository
from app.service.threshold_service import THRESHOLD_PUSH_CHANNEL, run_threshold_check
def main() -> None:
core = CoreReadOnlyRepository()
repo = ThresholdRepository()
customer_ids = repo.list_customer_ids_with_threshold()
if not customer_ids:
print("No customers with threshold config.")
return
hits = 0
for cid in customer_ids:
rows = core.list_holdings(cid, limit=500)
out = run_threshold_check(cid, rows, trace_id="demo-push", push=True)
if out.get("alert"):
hits += 1
print(json.dumps({"customer_id": cid, **out}, ensure_ascii=False))
print(f"channel={THRESHOLD_PUSH_CHANNEL} alerts={hits}/{len(customer_ids)}")
if __name__ == "__main__":
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
main()
+1
View File
@@ -46,6 +46,7 @@ def call(question: str, idx: int, token: str) -> dict:
"question": question,
"session_id": f"battery-{idx}",
"trace_id": f"trace-{idx}",
"interpret": False,
}).encode("utf-8")
req = urllib.request.Request(
URL,
+12
View File
@@ -0,0 +1,12 @@
# 口径字典 + 问数模板种子(本机 MySQL jinrong_agent)
$ErrorActionPreference = "Stop"
$Root = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$AgentDir = Join-Path $Root "scripts\agent"
Write-Host "Seeding analyst metric dict..."
Get-Content (Join-Path $AgentDir "seed-analyst-metric-dict.sql") -Raw | mysql -u root jinrong_agent
Write-Host "Seeding analyst query templates..."
Get-Content (Join-Path $AgentDir "seed-analyst-query-templates.sql") -Raw | mysql -u root jinrong_agent
Write-Host "Done."