mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 03:20:11 +00:00
Respect patrol model provider in quick analysis
This commit is contained in:
parent
b4e4f6b92d
commit
5f372e257f
3 changed files with 89 additions and 11 deletions
|
|
@ -44,7 +44,7 @@ func TestPatrolService_AskAIAboutAlert(t *testing.T) {
|
|||
ps := NewPatrolService(nil, nil)
|
||||
aiSvc := &Service{
|
||||
provider: mockPatrolProvider{response: "RESOLVE: looks good"},
|
||||
cfg: &config.AIConfig{PatrolModel: "mock:model"},
|
||||
cfg: &config.AIConfig{Enabled: true},
|
||||
}
|
||||
|
||||
alert := AlertInfo{
|
||||
|
|
|
|||
|
|
@ -1232,18 +1232,29 @@ func (s *Service) IsEnabled() bool {
|
|||
// It uses a single-turn, no-tools call for efficiency.
|
||||
func (s *Service) QuickAnalysis(ctx context.Context, prompt string) (string, error) {
|
||||
s.mu.RLock()
|
||||
provider := s.provider
|
||||
defaultProvider := s.provider
|
||||
cfg := s.cfg
|
||||
s.mu.RUnlock()
|
||||
|
||||
if provider == nil {
|
||||
if cfg == nil || !cfg.Enabled {
|
||||
return "", fmt.Errorf("Pulse Assistant is not enabled or configured")
|
||||
}
|
||||
|
||||
// Use a fast model for quick analysis if available
|
||||
model := ""
|
||||
if cfg != nil && cfg.PatrolModel != "" {
|
||||
model = cfg.PatrolModel
|
||||
// Use the configured patrol model and create a provider for that exact model.
|
||||
// This keeps quick patrol decisions aligned with the selected Patrol provider
|
||||
// instead of reusing whichever default provider the service booted with.
|
||||
model := cfg.GetPatrolModel()
|
||||
provider := defaultProvider
|
||||
if model != "" {
|
||||
if modelProvider, err := providers.NewForModel(cfg, model); err == nil {
|
||||
provider = modelProvider
|
||||
} else {
|
||||
log.Debug().Err(err).Str("model", model).Msg("Could not create provider for patrol quick analysis, using default")
|
||||
}
|
||||
}
|
||||
|
||||
if provider == nil {
|
||||
return "", fmt.Errorf("Pulse Assistant is not enabled or configured")
|
||||
}
|
||||
|
||||
messages := []providers.Message{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ package ai
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
|
@ -23,8 +26,8 @@ func TestService_QuickAnalysis(t *testing.T) {
|
|||
// Case 2: Configured
|
||||
mockProv := &mockProvider{
|
||||
chatFunc: func(ctx context.Context, req providers.ChatRequest) (*providers.ChatResponse, error) {
|
||||
if req.Model != "fast-model" {
|
||||
return nil, nil // Should use patrol model
|
||||
if req.Model != "" {
|
||||
t.Fatalf("expected default-provider fallback with empty model override, got %q", req.Model)
|
||||
}
|
||||
return &providers.ChatResponse{
|
||||
Content: "Analysis Result",
|
||||
|
|
@ -33,8 +36,7 @@ func TestService_QuickAnalysis(t *testing.T) {
|
|||
}
|
||||
svc.provider = mockProv
|
||||
svc.cfg = &config.AIConfig{
|
||||
Enabled: true,
|
||||
PatrolModel: "fast-model",
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
res, err := svc.QuickAnalysis(context.Background(), "Analysis prompt")
|
||||
|
|
@ -55,6 +57,71 @@ func TestService_QuickAnalysis(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestService_QuickAnalysis_UsesPatrolModelProviderInsteadOfDefaultProvider(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
openAI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/v1/chat/completions" {
|
||||
t.Fatalf("unexpected path: %s", r.URL.Path)
|
||||
}
|
||||
|
||||
var req map[string]interface{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
if got, _ := req["model"].(string); got != "gpt-4o-mini" {
|
||||
t.Fatalf("model = %q, want gpt-4o-mini", got)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"id": "chatcmpl-test",
|
||||
"object": "chat.completion",
|
||||
"created": 1,
|
||||
"model": "gpt-4o-mini",
|
||||
"choices": []map[string]interface{}{
|
||||
{
|
||||
"index": 0,
|
||||
"message": map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": "analysis from patrol model",
|
||||
},
|
||||
"finish_reason": "stop",
|
||||
},
|
||||
},
|
||||
"usage": map[string]interface{}{
|
||||
"prompt_tokens": 11,
|
||||
"completion_tokens": 7,
|
||||
"total_tokens": 18,
|
||||
},
|
||||
})
|
||||
}))
|
||||
defer openAI.Close()
|
||||
|
||||
svc := NewService(nil, nil)
|
||||
svc.provider = &mockProvider{
|
||||
chatFunc: func(ctx context.Context, req providers.ChatRequest) (*providers.ChatResponse, error) {
|
||||
t.Fatal("expected QuickAnalysis to avoid the stale default provider")
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
svc.cfg = &config.AIConfig{
|
||||
Enabled: true,
|
||||
Model: "gemini:gemini-2.5-pro",
|
||||
PatrolModel: "openai:gpt-4o-mini",
|
||||
OpenAIAPIKey: "test-key",
|
||||
OpenAIBaseURL: openAI.URL,
|
||||
}
|
||||
|
||||
res, err := svc.QuickAnalysis(context.Background(), "Analysis prompt")
|
||||
if err != nil {
|
||||
t.Fatalf("QuickAnalysis failed: %v", err)
|
||||
}
|
||||
if res != "analysis from patrol model" {
|
||||
t.Fatalf("unexpected result: %s", res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_AnalyzeForDiscovery(t *testing.T) {
|
||||
svc := NewService(nil, nil)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue