- DB Migration 081: 新增 account_behavior_hourly / account_risk_scores 表 - 行为采集:Gateway/OpenAI Gateway RecordUsage 注入 fire-and-forget CollectBehaviorAsync - SQL 打分引擎:CTE 加权特征向量 → risk_score [0-1],UPSERT 保留 idle_override - RiskSettings:Redis 缓存 → DB fallback → 默认值(observe 模式) - REST API:/admin/risk/summary|accounts|accounts/:id|settings - 前端:Pinia store + RiskControlView + 6 子组件(donut/radar/line 纯 SVG 图表) - 侧边栏新增 Risk Control 入口(ShieldExclamationIcon) - 反风控优化:移除 Antigravity 后台定时刷新,改为按需刷新避免 idle 封号
122 lines
3.7 KiB
Go
122 lines
3.7 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
RiskLevelLow = "LOW"
|
|
RiskLevelMedium = "MEDIUM"
|
|
RiskLevelHigh = "HIGH"
|
|
)
|
|
|
|
const (
|
|
RiskPhaseOff = "off"
|
|
RiskPhaseObserve = "observe"
|
|
RiskPhaseEnforce = "enforce"
|
|
)
|
|
|
|
const (
|
|
riskSettingsCacheKey = "settings:risk:v1"
|
|
)
|
|
|
|
type RiskSettings struct {
|
|
MediumThreshold float64 `json:"medium_threshold"`
|
|
HighThreshold float64 `json:"high_threshold"`
|
|
Phase string `json:"phase"`
|
|
}
|
|
|
|
func DefaultRiskSettings() *RiskSettings {
|
|
return &RiskSettings{
|
|
MediumThreshold: 0.45,
|
|
HighThreshold: 0.75,
|
|
Phase: RiskPhaseObserve,
|
|
}
|
|
}
|
|
|
|
type RiskBehaviorHourDelta struct {
|
|
APICallCount int64
|
|
StreamCount int64
|
|
TotalInputTokens int64
|
|
TotalOutputTokens int64
|
|
TotalDurationMs int64
|
|
P50DurationMs *int
|
|
}
|
|
|
|
type RiskSummary struct {
|
|
TotalAccounts int64 `json:"total_accounts"`
|
|
LowCount int64 `json:"low_count"`
|
|
MediumCount int64 `json:"medium_count"`
|
|
HighCount int64 `json:"high_count"`
|
|
AverageScore float64 `json:"average_score"`
|
|
LastScoredAt *time.Time `json:"last_scored_at,omitempty"`
|
|
Settings *RiskSettings `json:"settings"`
|
|
}
|
|
|
|
type RiskAccountFilter struct {
|
|
Page int
|
|
PageSize int
|
|
Level string
|
|
Platform string
|
|
}
|
|
|
|
type RiskAccountListItem struct {
|
|
AccountID int64 `json:"account_id"`
|
|
AccountName string `json:"account_name"`
|
|
Platform string `json:"platform"`
|
|
RiskScore float64 `json:"risk_score"`
|
|
RiskLevel string `json:"risk_level"`
|
|
RiskReasons json.RawMessage `json:"risk_reasons"`
|
|
FeatureVector json.RawMessage `json:"feature_vector"`
|
|
IdleOverride bool `json:"idle_override"`
|
|
ScoredAt time.Time `json:"scored_at"`
|
|
LastHourCalls int64 `json:"last_hour_calls"`
|
|
LastHourTokens int64 `json:"last_hour_tokens"`
|
|
}
|
|
|
|
type RiskAccountList struct {
|
|
Items []*RiskAccountListItem `json:"items"`
|
|
Total int64 `json:"total"`
|
|
Page int `json:"page"`
|
|
PageSize int `json:"page_size"`
|
|
}
|
|
|
|
type RiskBehaviorHour struct {
|
|
HourBucket time.Time `json:"hour_bucket"`
|
|
APICallCount int64 `json:"api_call_count"`
|
|
StreamCount int64 `json:"stream_count"`
|
|
TotalInputTokens int64 `json:"total_input_tokens"`
|
|
TotalOutputTokens int64 `json:"total_output_tokens"`
|
|
TotalDurationMs int64 `json:"total_duration_ms"`
|
|
P50DurationMs *int `json:"p50_duration_ms,omitempty"`
|
|
}
|
|
|
|
type RiskAccountDetail struct {
|
|
AccountID int64 `json:"account_id"`
|
|
AccountName string `json:"account_name"`
|
|
Platform string `json:"platform"`
|
|
RiskScore float64 `json:"risk_score"`
|
|
RiskLevel string `json:"risk_level"`
|
|
RiskReasons json.RawMessage `json:"risk_reasons"`
|
|
FeatureVector json.RawMessage `json:"feature_vector"`
|
|
IdleOverride bool `json:"idle_override"`
|
|
ScoredAt time.Time `json:"scored_at"`
|
|
ModelVersion int `json:"model_version"`
|
|
HourlyBehavior []RiskBehaviorHour `json:"hourly_behavior"`
|
|
}
|
|
|
|
type RiskScoreRecord struct {
|
|
ID int64 `json:"id"`
|
|
AccountID int64 `json:"account_id"`
|
|
RiskScore float64 `json:"risk_score"`
|
|
RiskLevel string `json:"risk_level"`
|
|
RiskReasons json.RawMessage `json:"risk_reasons"`
|
|
FeatureVector json.RawMessage `json:"feature_vector"`
|
|
ScoredAt time.Time `json:"scored_at"`
|
|
ModelVersion int `json:"model_version"`
|
|
IdleOverride bool `json:"idle_override"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|