Files
aiagent/backend/app/api/knowledge_dashboard.py
renjianbo beff3fac8d fix: delete agent 500 error + dynamic personality + deployment guide
- Fix delete agent 500: clean up FK records (agent_llm_logs, permissions,
  schedules, executions, team_members) and unbind goals/tasks before delete
- Remove hardcoded personality templates in Android, replace with dynamic
  system prompt generation from name + description
- Set promptSectionsEnabled=false to bypass PromptComposer for personality
- Add Tencent Cloud Linux deployment guide (Docker Compose)
- Accumulated backend service updates, frontend UI fixes, Android app changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-29 01:17:21 +08:00

110 lines
3.5 KiB
Python

"""
知识仪表盘 API — 瓶颈分析、知识条目查询、趋势统计
"""
from __future__ import annotations
import logging
from datetime import datetime, timedelta
from typing import Optional
from fastapi import APIRouter, Depends, Query
from sqlalchemy import func
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.api.auth import get_current_user
from app.models.user import User
from app.models.knowledge_entry import KnowledgeEntry
from app.services.bottleneck_detector import bottleneck_detector
from app.services.optimization_engine import optimization_engine
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/v1/knowledge-dashboard", tags=["knowledge-dashboard"])
@router.get("/bottlenecks")
def get_bottlenecks(
hours: int = Query(168, ge=1, le=2160, description="分析时长(小时)"),
current_user: User = Depends(get_current_user),
):
"""瓶颈分析 — 检测工作流性能瓶颈并生成优化建议。"""
analysis = bottleneck_detector.run_full_analysis(hours=hours)
optimizations = optimization_engine.generate_optimizations(analysis.get("bottlenecks", []))
# Build recommendations dict keyed by node_type for frontend lookup
recommendations_map = {}
for opt in optimizations:
recommendations_map[opt["node_type"]] = {
"node_type": opt["node_type"],
"severity": opt["severity"],
"current_state": opt.get("current_metrics", {}),
"changes": opt.get("changes", []),
}
return {
**analysis,
"recommendations": list(optimizations),
"optimizations": recommendations_map,
}
@router.get("/entries")
def get_knowledge_entries(
days: int = Query(7, ge=1, le=365, description="统计天数"),
limit: int = Query(50, ge=1, le=200, description="返回条数"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""获取知识条目列表,按创建时间倒序。"""
since = datetime.now() - timedelta(days=days)
entries = (
db.query(KnowledgeEntry)
.filter(
KnowledgeEntry.created_at >= since,
KnowledgeEntry.is_active == True,
)
.order_by(KnowledgeEntry.created_at.desc())
.limit(limit)
.all()
)
return [e.to_dict() for e in entries]
@router.get("/trend")
def get_knowledge_trend(
days: int = Query(7, ge=1, le=365, description="统计天数"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""知识条目增长趋势 — 按天统计新增数量。"""
since = datetime.now() - timedelta(days=days)
# GROUP BY date(created_at)
rows = (
db.query(
func.date(KnowledgeEntry.created_at).label("date"),
func.count(KnowledgeEntry.id).label("count"),
)
.filter(
KnowledgeEntry.created_at >= since,
KnowledgeEntry.is_active == True,
)
.group_by(func.date(KnowledgeEntry.created_at))
.order_by(func.date(KnowledgeEntry.created_at).asc())
.all()
)
# Fill in missing dates with 0 count
trend = []
current_date = since.date()
end_date = datetime.now().date()
date_counts = {row.date: row.count for row in rows}
while current_date <= end_date:
trend.append({
"date": current_date.isoformat(),
"count": date_counts.get(current_date, 0),
})
current_date += timedelta(days=1)
return trend