132 lines
4.3 KiB
Python
132 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
from .shared import *
|
|
|
|
class ModelCapabilityGapQueriesMixin:
|
|
async def list_capability_gaps(
|
|
self,
|
|
tenant_id: int,
|
|
status: Optional[str] = None,
|
|
severity: Optional[str] = None,
|
|
limit: int = 100,
|
|
) -> Dict[str, Any]:
|
|
"""列出能力差距记录"""
|
|
query = select(ModelCapabilityGap).where(
|
|
ModelCapabilityGap.tenant_id == tenant_id
|
|
)
|
|
|
|
if status:
|
|
query = query.where(ModelCapabilityGap.status == status)
|
|
if severity:
|
|
query = query.where(ModelCapabilityGap.severity == severity)
|
|
|
|
query = query.order_by(desc(ModelCapabilityGap.created_at)).limit(limit)
|
|
|
|
result = await self.db.execute(query)
|
|
gaps = result.scalars().all()
|
|
|
|
return {
|
|
"gaps": [
|
|
{
|
|
"id": g.id,
|
|
"gap_type": g.gap_type,
|
|
"severity": g.severity,
|
|
"description": g.description,
|
|
"ai_analysis": g.ai_analysis,
|
|
"status": g.status,
|
|
"created_at": g.created_at.isoformat() if g.created_at else None,
|
|
"resolved_at": g.resolved_at.isoformat() if g.resolved_at else None,
|
|
}
|
|
for g in gaps
|
|
],
|
|
"total": len(gaps),
|
|
}
|
|
|
|
async def acknowledge_gap(
|
|
self, gap_id: int, tenant_id: int
|
|
) -> Dict[str, Any]:
|
|
"""确认能力差距"""
|
|
result = await self.db.execute(
|
|
select(ModelCapabilityGap).where(
|
|
and_(
|
|
ModelCapabilityGap.id == gap_id,
|
|
ModelCapabilityGap.tenant_id == tenant_id,
|
|
)
|
|
)
|
|
)
|
|
gap = result.scalar_one_or_none()
|
|
|
|
if not gap:
|
|
raise ValueError(f"能力差距 {gap_id} 不存在")
|
|
|
|
gap.status = "acknowledged"
|
|
await self.db.commit()
|
|
|
|
return {"id": gap.id, "status": gap.status}
|
|
|
|
async def resolve_gap(
|
|
self, gap_id: int, tenant_id: int, resolution_notes: Optional[str] = None
|
|
) -> Dict[str, Any]:
|
|
"""解决能力差距"""
|
|
result = await self.db.execute(
|
|
select(ModelCapabilityGap).where(
|
|
and_(
|
|
ModelCapabilityGap.id == gap_id,
|
|
ModelCapabilityGap.tenant_id == tenant_id,
|
|
)
|
|
)
|
|
)
|
|
gap = result.scalar_one_or_none()
|
|
|
|
if not gap:
|
|
raise ValueError(f"能力差距 {gap_id} 不存在")
|
|
|
|
gap.status = "resolved"
|
|
gap.resolved_at = now_cn_naive()
|
|
gap.resolution_notes = resolution_notes
|
|
await self.db.commit()
|
|
|
|
return {"id": gap.id, "status": gap.status}
|
|
|
|
async def get_cost_tracking(
|
|
self, truth_node_id: int, period: str = "weekly", tenant_id: int = 1
|
|
) -> Dict[str, Any]:
|
|
"""获取成本跟踪记录"""
|
|
result = await self.db.execute(
|
|
select(CostTracking).where(
|
|
and_(
|
|
CostTracking.truth_node_id == truth_node_id,
|
|
CostTracking.period == period,
|
|
CostTracking.tenant_id == tenant_id,
|
|
)
|
|
).order_by(desc(CostTracking.created_at))
|
|
)
|
|
tracking = result.scalar_one_or_none()
|
|
|
|
if not tracking:
|
|
return {
|
|
"truth_node_id": truth_node_id,
|
|
"period": period,
|
|
"estimated_tokens": 0,
|
|
"actual_tokens": 0,
|
|
"estimated_cost_usd": 0.0,
|
|
"actual_cost_usd": 0.0,
|
|
"roi_score": None,
|
|
"roi_analysis": {},
|
|
"optimization_suggestions": {},
|
|
}
|
|
|
|
return {
|
|
"id": tracking.id,
|
|
"truth_node_id": tracking.truth_node_id,
|
|
"period": tracking.period,
|
|
"estimated_tokens": tracking.estimated_tokens,
|
|
"actual_tokens": tracking.actual_tokens,
|
|
"estimated_cost_usd": float(tracking.estimated_cost_usd),
|
|
"actual_cost_usd": float(tracking.actual_cost_usd),
|
|
"roi_score": tracking.roi_score,
|
|
"roi_analysis": tracking.roi_analysis,
|
|
"optimization_suggestions": tracking.optimization_suggestions,
|
|
}
|
|
|