memoryweave/go/internal/selfoptimize/executor.go

177 lines
5.1 KiB
Go

// 织忆 MemoryWeave — 触发器执行器
package selfoptimize
import (
"log"
"sync"
"time"
)
// ─── 触发器执行器 ──────────────────────────────────────
// TriggerExecutor 8 类触发器自动执行循环
type TriggerExecutor struct {
mu sync.RWMutex
triggers []*TriggerDef
checkInterval time.Duration
eventBus TriggerEventBus
}
// TriggerDef 触发器定义
type TriggerDef struct {
ID string `json:"id"`
Type TriggerExType `json:"type"`
Condition interface{} `json:"condition"`
Action string `json:"action"` // 触发的流水线任务类型
LastFired time.Time `json:"last_fired"`
Cooldown time.Duration `json:"cooldown"` // 冷却时间
Enabled bool `json:"enabled"`
FireCount int `json:"fire_count"`
}
type TriggerExType string
const (
TCommitCount TriggerExType = "commit_count" // 新增 N 条
TTimeSince TriggerExType = "time_since" // 距上次 N 小时
TRecallMiss TriggerExType = "recall_miss" // 连续 N 次 miss
TQualityDrop TriggerExType = "quality_drop" // quality < threshold
TGapDetected TriggerExType = "gap_detected" // 新缺口
TConflict TriggerExType = "conflict_pending" // 待解决冲突
TVValueLow TriggerExType = "v_value_low" // V 值过低
TDecayCritical TriggerExType = "decay_critical" // 衰减临界
)
type TriggerEventBus interface {
OnTrigger(trigger *TriggerDef)
}
// 全局触发器状态
var Executor = &TriggerExecutor{
triggers: makeTriggers(),
checkInterval: 5 * time.Minute,
}
func makeTriggers() []*TriggerDef {
return []*TriggerDef{
{ID: "t1", Type: TCommitCount, Condition: 50, Action: "consolidate", Cooldown: 24 * time.Hour, Enabled: true},
{ID: "t2", Type: TTimeSince, Condition: 48.0, Action: "consolidate", Cooldown: 24 * time.Hour, Enabled: true},
{ID: "t3", Type: TRecallMiss, Condition: 3, Action: "gap_classify", Cooldown: 30 * time.Minute, Enabled: true},
{ID: "t4", Type: TQualityDrop, Condition: 0.3, Action: "deprecate_review", Cooldown: 1 * time.Hour, Enabled: true},
{ID: "t5", Type: TGapDetected, Condition: true, Action: "gap_fill", Cooldown: 5 * time.Minute, Enabled: true},
{ID: "t6", Type: TConflict, Condition: 3, Action: "conflict_muchen", Cooldown: 10 * time.Minute, Enabled: true},
{ID: "t7", Type: TVValueLow, Condition: 0.2, Action: "mem_review", Cooldown: 12 * time.Hour, Enabled: true},
{ID: "t8", Type: TDecayCritical, Condition: 0.1, Action: "archive_or_boost", Cooldown: 6 * time.Hour, Enabled: true},
}
}
// Start 启动触发器检查循环
func (te *TriggerExecutor) Start(flow *Pipeline) {
if te.eventBus == nil {
te.eventBus = &defaultEventBus{flow: flow}
}
go te.loop()
log.Println("[executor] 触发器执行器启动 (8 triggers)")
}
func (te *TriggerExecutor) loop() {
ticker := time.NewTicker(te.checkInterval)
defer ticker.Stop()
for range ticker.C {
te.checkAll()
}
}
func (te *TriggerExecutor) checkAll() {
te.mu.RLock()
triggers := make([]*TriggerDef, len(te.triggers))
copy(triggers, te.triggers)
te.mu.RUnlock()
metrics := Dash.Metrics()
for _, t := range triggers {
if !t.Enabled {
continue
}
if time.Since(t.LastFired) < t.Cooldown {
continue
}
if te.evaluate(t, metrics) {
t.LastFired = time.Now()
t.FireCount++
te.eventBus.OnTrigger(t)
log.Printf("[executor] trigger %s fired (count=%d)", t.ID, t.FireCount)
}
}
}
func (te *TriggerExecutor) evaluate(t *TriggerDef, metrics map[string]float64) bool {
switch t.Type {
case TCommitCount:
// 需要 commit 计数(从 LanceDB stats 获取)
return false // 待集成
case TTimeSince:
hours := time.Since(t.LastFired).Hours()
threshold, _ := t.Condition.(float64)
return hours >= threshold
case TRecallMiss:
// 检查最近的 miss 计数
rate, ok := metrics["recall_hit_rate"]
return ok && rate > 0 && t.LastFired.IsZero()
case TQualityDrop:
threshold, _ := t.Condition.(float64)
return metrics["recall_usefulness_rate"] < threshold
case TGapDetected:
return metrics["gap_closure_rate"] < 0.5
case TConflict:
return metrics["auto_resolve_rate"] < 0.5
case TVValueLow:
threshold, _ := t.Condition.(float64)
return metrics["recall_usefulness_rate"] < threshold
case TDecayCritical:
return metrics["deprecated_per_day"] > 5
}
return false
}
// Fire 手动触发
func (te *TriggerExecutor) Fire(triggerID string) bool {
te.mu.RLock()
defer te.mu.RUnlock()
for _, t := range te.triggers {
if t.ID == triggerID {
t.LastFired = time.Now()
t.FireCount++
te.eventBus.OnTrigger(t)
return true
}
}
return false
}
// List 返回所有触发器状态
func (te *TriggerExecutor) List() []*TriggerDef {
te.mu.RLock()
defer te.mu.RUnlock()
result := make([]*TriggerDef, len(te.triggers))
copy(result, te.triggers)
return result
}
// defaultEventBus 默认实现:触发 → 入队到流水线
type defaultEventBus struct {
flow *Pipeline
}
func (eb *defaultEventBus) OnTrigger(t *TriggerDef) {
if eb.flow != nil {
eb.flow.Enqueue(t.Action, map[string]string{
"trigger_id": t.ID,
"action": t.Action,
})
}
}