fix: classifier selector model now routes to correct provider
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled

Extracted selectProvider() method from handleChatCompletions' inline
logic. The classifier callback now calls selectProvider(selectorModel)
instead of hardcoding openaiProvider.

This fixes the 'circuit breaker is open' error when dispatcher tries
to use deepseek-v4-flash as its selector model.
This commit is contained in:
2026-05-07 13:37:19 -04:00
parent 3c0b59622e
commit 0ae30036f0
+36 -3
View File
@@ -186,8 +186,11 @@ func (s *Server) refreshRouter() {
} }
var classifyFn router.ClassifierFunc var classifyFn router.ClassifierFunc
if openaiProvider, ok := s.providers["openai"]; ok {
classifyFn = func(ctx context.Context, selectorModel, systemPrompt, userMessage string) (string, error) { classifyFn = func(ctx context.Context, selectorModel, systemPrompt, userMessage string) (string, error) {
provider, _, err := s.selectProvider(selectorModel)
if err != nil {
return "", err
}
req := &models.UnifiedRequest{ req := &models.UnifiedRequest{
Model: selectorModel, Model: selectorModel,
Messages: []models.UnifiedMessage{ Messages: []models.UnifiedMessage{
@@ -197,7 +200,7 @@ func (s *Server) refreshRouter() {
MaxTokens: uint32Ptr(5), MaxTokens: uint32Ptr(5),
Stream: false, Stream: false,
} }
resp, err := openaiProvider.ChatCompletion(ctx, req) resp, err := provider.ChatCompletion(ctx, req)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -210,7 +213,6 @@ func (s *Server) refreshRouter() {
} }
return content, nil return content, nil
} }
}
if s.modelRouter == nil { if s.modelRouter == nil {
s.modelRouter = router.New(groups, classifyFn) s.modelRouter = router.New(groups, classifyFn)
@@ -492,6 +494,37 @@ func (s *Server) handleListModels(c *gin.Context) {
}) })
} }
func (s *Server) selectProvider(modelID string) (providers.Provider, string, error) {
providerName := "openai" // default
modelLower := strings.ToLower(modelID)
if strings.HasPrefix(modelLower, "gemini/") || strings.Contains(modelLower, "gemini") || strings.HasPrefix(modelLower, "google/") {
providerName = "gemini"
} else if strings.HasPrefix(modelLower, "deepseek/") || (strings.Contains(modelLower, "deepseek") && !strings.Contains(modelLower, "ollama")) {
providerName = "deepseek"
} else if strings.HasPrefix(modelLower, "moonshot/") || strings.Contains(modelLower, "kimi") || strings.Contains(modelLower, "moonshot") {
providerName = "moonshot"
} else if strings.HasPrefix(modelLower, "grok/") || strings.Contains(modelLower, "grok") {
providerName = "grok"
} else if strings.HasPrefix(modelLower, "ollama/") ||
strings.Contains(modelLower, "glm-") ||
strings.Contains(modelLower, "qwen") ||
strings.Contains(modelLower, "gemma") ||
strings.Contains(modelLower, "llama") ||
strings.Contains(modelLower, "mistral") ||
strings.Contains(modelLower, "phi") ||
strings.Contains(modelLower, "yi") ||
strings.Contains(modelLower, "codellama") ||
strings.Contains(modelLower, "command-r") {
providerName = "ollama"
}
p, ok := s.providers[providerName]
if !ok {
return nil, "", fmt.Errorf("Provider %s not enabled or supported", providerName)
}
return p, providerName, nil
}
func (s *Server) handleChatCompletions(c *gin.Context) { func (s *Server) handleChatCompletions(c *gin.Context) {
startTime := time.Now() startTime := time.Now()
var req models.ChatCompletionRequest var req models.ChatCompletionRequest