memoryweave/go/internal/selfoptimize/quality_monitor.go

105 lines
2.4 KiB
Go

// 织忆 MemoryWeave — 质量下降自动动作
// quality_score < 0.3 → 自动降权 → 7天未改善 → deprecated → tombstones
package selfoptimize
import (
"sync"
"time"
)
// QualityDropMonitor 质量下降监控器
type QualityDropMonitor struct {
mu sync.Mutex
// memoryID → 质量下降记录
dropped map[string]*DropRecord
// 阈值
lowThreshold float64 // < 0.3 → 触发
minFeedbacks int // ≥ 5 次反馈 → 有效
deprecationDays int // 7 天未改善 → deprecated
}
type DropRecord struct {
MemoryID string `json:"memory_id"`
Score float64 `json:"score"`
NotifiedAt time.Time `json:"notified_at"`
DaysSinceDrop int `json:"days_since_drop"`
Status string `json:"status"` // notified / deprecating / deprecated
}
var QualityMonitor = &QualityDropMonitor{
dropped: make(map[string]*DropRecord),
lowThreshold: 0.3,
minFeedbacks: 5,
deprecationDays: 7,
}
// Check 检查质量分数
// 返回: 是否需要通知
func (qm *QualityDropMonitor) Check(memoryID string, score float64, feedbackCount int) *DropRecord {
qm.mu.Lock()
defer qm.mu.Unlock()
// 不满足阈值 → 清除记录
if score >= qm.lowThreshold || feedbackCount < qm.minFeedbacks {
delete(qm.dropped, memoryID)
return nil
}
record, exists := qm.dropped[memoryID]
if !exists {
record = &DropRecord{
MemoryID: memoryID,
Score: score,
NotifiedAt: time.Now(),
Status: "notified",
}
qm.dropped[memoryID] = record
return record
}
// 更新分数
record.Score = score
record.DaysSinceDrop = int(time.Since(record.NotifiedAt).Hours() / 24)
// 7 天未改善 → 标记 deprecated
if record.DaysSinceDrop >= qm.deprecationDays {
record.Status = "deprecating"
}
return record
}
// MarkDeprecated 标记为已淘汰
func (qm *QualityDropMonitor) MarkDeprecated(memoryID string) {
qm.mu.Lock()
defer qm.mu.Unlock()
if record, ok := qm.dropped[memoryID]; ok {
record.Status = "deprecated"
}
}
// GetDeprecating 获取待淘汰列表(用于批量淘汰)
func (qm *QualityDropMonitor) GetDeprecating() []*DropRecord {
qm.mu.Lock()
defer qm.mu.Unlock()
var list []*DropRecord
for id, record := range qm.dropped {
if record.Status == "deprecating" {
list = append(list, record)
_ = id
}
}
return list
}
// ActiveAlerts 活跃告警数
func (qm *QualityDropMonitor) ActiveAlerts() int {
qm.mu.Lock()
defer qm.mu.Unlock()
return len(qm.dropped)
}