diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index 03d5bb7..778d9e1 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -350,7 +350,11 @@ func (al *AgentLoop) tryFallbackProviders(ctx context.Context, msg bus.InboundMe lastErr := primaryErr candidates := append([]string(nil), al.providerNames[1:]...) if al.ekg != nil { - candidates = al.ekg.RankProviders(candidates) + errSig := "" + if primaryErr != nil { + errSig = primaryErr.Error() + } + candidates = al.ekg.RankProvidersForError(candidates, errSig) } for _, name := range candidates { p, ok := al.providerPool[name] @@ -361,11 +365,13 @@ func (al *AgentLoop) tryFallbackProviders(ctx context.Context, msg bus.InboundMe if al.ekg != nil { st := "success" lg := "fallback provider success" + errSig := "" if err != nil { st = "error" lg = err.Error() + errSig = err.Error() } - al.ekg.Record(ekg.Event{Session: msg.SessionKey, Channel: msg.Channel, Source: "provider_fallback", Status: st, Provider: name, Model: al.model, Log: lg}) + al.ekg.Record(ekg.Event{Session: msg.SessionKey, Channel: msg.Channel, Source: "provider_fallback", Status: st, Provider: name, Model: al.model, ErrSig: errSig, Log: lg}) } if err == nil { logger.WarnCF("agent", "LLM fallback provider switched", map[string]interface{}{"provider": name}) diff --git a/pkg/ekg/engine.go b/pkg/ekg/engine.go index d7ea5ca..9017167 100644 --- a/pkg/ekg/engine.go +++ b/pkg/ekg/engine.go @@ -175,9 +175,14 @@ var ( ) func (e *Engine) RankProviders(candidates []string) []string { + return e.RankProvidersForError(candidates, "") +} + +func (e *Engine) RankProvidersForError(candidates []string, errSig string) []string { if len(candidates) <= 1 || e == nil { return append([]string(nil), candidates...) } + errSig = NormalizeErrorSignature(errSig) events := e.readRecentEvents() score := map[string]float64{} for _, c := range candidates { @@ -191,13 +196,22 @@ func (e *Engine) RankProviders(candidates []string) []string { if _, ok := score[p]; !ok { continue } + weight := 1.0 + evSig := NormalizeErrorSignature(ev.ErrSig) + if errSig != "" { + if evSig == errSig { + weight = 2.5 + } else if evSig != "" { + weight = 0.4 + } + } switch strings.ToLower(strings.TrimSpace(ev.Status)) { case "success": - score[p] += 1.0 + score[p] += 1.0 * weight case "suppressed": - score[p] += 0.2 + score[p] += 0.2 * weight case "error": - score[p] -= 1.0 + score[p] -= 1.0 * weight } } ordered := append([]string(nil), candidates...)