feat: add router package with heuristic strategy
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"gophergate/internal/db"
|
||||
)
|
||||
|
||||
// Decision holds the result of a routing decision.
|
||||
type Decision struct {
|
||||
SelectedModel string `json:"selected_model"`
|
||||
Strategy string `json:"strategy"` // "heuristic" or "classifier"
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
// ClassifierFunc is the callback for classifier-based routing.
|
||||
type ClassifierFunc func(ctx context.Context, selectorModel, systemPrompt, userMessage string) (string, error)
|
||||
|
||||
// Router resolves model groups to concrete models.
|
||||
type Router struct {
|
||||
groups map[string]db.ModelGroup
|
||||
classify ClassifierFunc
|
||||
}
|
||||
|
||||
// New creates a Router. classify may be nil if no classifier groups exist.
|
||||
func New(groups []db.ModelGroup, classify ClassifierFunc) *Router {
|
||||
r := &Router{
|
||||
groups: make(map[string]db.ModelGroup),
|
||||
classify: classify,
|
||||
}
|
||||
for _, g := range groups {
|
||||
r.groups[g.ID] = g
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// IsGroup returns true if the model name is a group ID.
|
||||
func (r *Router) IsGroup(modelID string) bool {
|
||||
_, ok := r.groups[modelID]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Route resolves a group to a concrete model.
|
||||
func (r *Router) Route(ctx context.Context, groupID string, userMessage string) (*Decision, error) {
|
||||
group, ok := r.groups[groupID]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown model group: %s", groupID)
|
||||
}
|
||||
|
||||
var targets []string
|
||||
if err := json.Unmarshal([]byte(group.Targets), &targets); err != nil || len(targets) == 0 {
|
||||
return nil, fmt.Errorf("invalid or empty targets for group %s", groupID)
|
||||
}
|
||||
|
||||
switch group.Strategy {
|
||||
case "heuristic":
|
||||
return routeHeuristic(group, targets, userMessage)
|
||||
case "classifier":
|
||||
if r.classify == nil {
|
||||
return routeHeuristic(group, targets, userMessage)
|
||||
}
|
||||
return routeClassifier(ctx, r.classify, group, targets, userMessage)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown strategy: %s", group.Strategy)
|
||||
}
|
||||
}
|
||||
|
||||
// Reload replaces the group definitions without recreating the router.
|
||||
func (r *Router) Reload(groups []db.ModelGroup) {
|
||||
r.groups = make(map[string]db.ModelGroup)
|
||||
for _, g := range groups {
|
||||
r.groups[g.ID] = g
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user