gwdoc/tools/agent_usage_statistics.py

238 lines
7.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
智能体使用统计工具
记录和统计智能体的调用次数PostgreSQL数据库存储
"""
from datetime import datetime
from typing import Dict, Any
from config import POSTGRES_CONNECTION_STRING
ROUTE_FLAG_DISPLAY_NAMES = {
"问题排查": "问题排查",
"操作使用": "操作使用",
"百科问答": "百科问答"
}
ROUTE_FLAG_ICONS = {
"问题排查": "detection",
"操作使用": "repair",
"百科问答": "doc"
}
ROUTE_FLAG_COLORS = {
"问题排查": "#FFB800",
"操作使用": "#00C2FF",
"百科问答": "#9153FF"
}
async def init_agent_usage_table():
"""
初始化 agent_usage_records 表
"""
try:
from psycopg_pool import AsyncConnectionPool
except ImportError:
print("[agent_usage_statistics] psycopg_pool 未安装,无法初始化表")
return
async with AsyncConnectionPool(
POSTGRES_CONNECTION_STRING,
kwargs={"autocommit": True}
) as pool:
async with pool.connection() as conn:
async with conn.cursor() as cur:
await cur.execute("""
CREATE TABLE IF NOT EXISTS agent_usage_records (
id SERIAL PRIMARY KEY,
chat_id TEXT NOT NULL DEFAULT '',
route_flag TEXT NOT NULL DEFAULT '',
message_id TEXT NOT NULL DEFAULT '',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
UNIQUE(chat_id, route_flag)
)
""")
await cur.execute("""
CREATE INDEX IF NOT EXISTS agent_usage_records_route_flag_idx ON agent_usage_records(route_flag)
""")
await cur.execute("""
CREATE INDEX IF NOT EXISTS agent_usage_records_created_at_idx ON agent_usage_records(created_at)
""")
print("[agent_usage_statistics] agent_usage_records 表初始化完成")
async def record_agent_usage(chat_id: str, route_flag: str, message_id: str = "") -> bool:
"""
记录智能体使用情况到数据库
Args:
chat_id: 会话ID
route_flag: 路由标志(智能体类型)
message_id: 消息ID
Returns:
是否记录成功
"""
if not chat_id or not route_flag:
return False
try:
from psycopg_pool import AsyncConnectionPool
except ImportError:
print("[agent_usage_statistics] psycopg_pool 未安装,无法记录")
return False
try:
async with AsyncConnectionPool(
POSTGRES_CONNECTION_STRING,
kwargs={"autocommit": True}
) as pool:
async with pool.connection() as conn:
async with conn.cursor() as cur:
await cur.execute(
"""
INSERT INTO agent_usage_records (chat_id, route_flag, message_id, created_at)
VALUES (%s, %s, %s, %s)
ON CONFLICT (chat_id, route_flag) DO UPDATE SET
message_id = EXCLUDED.message_id,
created_at = EXCLUDED.created_at
""",
(chat_id, route_flag, message_id or "", datetime.now())
)
return True
except Exception as e:
print(f"[agent_usage_statistics] 记录智能体使用失败: {e}")
return False
def _format_count(count: int) -> str:
if count >= 10000:
return f"{count / 10000:.1f}"
else:
return f"{count:,}"
async def get_agent_usage_statistics() -> Dict[str, Any]:
"""
从数据库查询智能体使用统计
统计逻辑:
- 同一 chat_id + route_flag 只保留一条记录
- 统计各类型的总使用次数
- 统计近6个月的月度使用次数
Returns:
统计结果字典
"""
try:
from psycopg_pool import AsyncConnectionPool
except ImportError:
print("[agent_usage_statistics] psycopg_pool 未安装,无法查询")
return {"success": False, "data": None}
required_routes = ["操作使用", "问题排查", "百科问答"]
now = datetime.now()
last_6_months = []
for i in range(5, -1, -1):
year = now.year
month = now.month - i
while month <= 0:
month += 12
year -= 1
last_6_months.append({
"year": year,
"month": month,
"key": f"{year}-{month:02d}",
"label": f"{month}"
})
try:
async with AsyncConnectionPool(
POSTGRES_CONNECTION_STRING,
kwargs={"autocommit": True}
) as pool:
async with pool.connection() as conn:
async with conn.cursor() as cur:
# 查询各类型总使用次数
route_counts = {}
for route_flag in required_routes:
await cur.execute(
"""
SELECT COUNT(*) FROM agent_usage_records
WHERE route_flag = %s
""",
(route_flag,)
)
row = await cur.fetchone()
route_counts[route_flag] = row[0] if row else 0
# 查询近6个月各类型月度使用次数
monthly_counts = {route: {m["key"]: 0 for m in last_6_months} for route in required_routes}
for route_flag in required_routes:
for m in last_6_months:
month_start = datetime(m["year"], m["month"], 1)
if m["month"] == 12:
month_end = datetime(m["year"] + 1, 1, 1)
else:
month_end = datetime(m["year"], m["month"] + 1, 1)
await cur.execute(
"""
SELECT COUNT(*) FROM agent_usage_records
WHERE route_flag = %s AND created_at >= %s AND created_at < %s
""",
(route_flag, month_start, month_end)
)
row = await cur.fetchone()
monthly_counts[route_flag][m["key"]] = row[0] if row else 0
except Exception as e:
print(f"[agent_usage_statistics] 查询统计数据失败: {e}")
import traceback
traceback.print_exc()
return {"success": False, "data": None}
total = sum(route_counts.get(route, 0) for route in required_routes)
types_data = []
monthly_stats = []
for route_flag in required_routes:
count = route_counts.get(route_flag, 0)
display_name = ROUTE_FLAG_DISPLAY_NAMES.get(route_flag, route_flag)
icon = ROUTE_FLAG_ICONS.get(route_flag, "info")
color = ROUTE_FLAG_COLORS.get(route_flag, "#8C8C8C")
types_data.append({
"name": display_name,
"count": _format_count(count),
"icon": icon,
"color": color
})
monthly_data = []
for m in last_6_months:
monthly_data.append({
"month": m["label"],
"count": monthly_counts[route_flag][m["key"]]
})
monthly_stats.append({
"name": display_name,
"color": color,
"monthlyCounts": monthly_data
})
return {
"success": True,
"data": {
"total": _format_count(total),
"types": types_data,
"monthlyStats": monthly_stats,
"months": [m["label"] for m in last_6_months]
}
}