diff --git a/controller/ai/controller.go b/controller/ai/controller.go index c2372536..bccbc4c0 100644 --- a/controller/ai/controller.go +++ b/controller/ai/controller.go @@ -12,7 +12,7 @@ type IProviderController interface { ConfiguredProviders(ctx *gin.Context, keyword string) ([]*ai_dto.ConfiguredProviderItem, error) UnConfiguredProviders(ctx *gin.Context) ([]*ai_dto.ProviderItem, error) SimpleProviders(ctx *gin.Context) ([]*ai_dto.SimpleProviderItem, error) - SimpleConfiguredProviders(ctx *gin.Context) ([]*ai_dto.SimpleProviderItem, *ai_dto.BackupProvider, error) + SimpleConfiguredProviders(ctx *gin.Context, all string) ([]*ai_dto.SimpleProviderItem, *ai_dto.BackupProvider, error) Provider(ctx *gin.Context, id string) (*ai_dto.Provider, error) SimpleProvider(ctx *gin.Context, id string) (*ai_dto.SimpleProvider, error) LLMs(ctx *gin.Context, driver string) ([]*ai_dto.LLMItem, *ai_dto.ProviderItem, error) diff --git a/controller/ai/iml.go b/controller/ai/iml.go index 033e6301..0febda5c 100644 --- a/controller/ai/iml.go +++ b/controller/ai/iml.go @@ -33,8 +33,11 @@ func (i *imlProviderController) SimpleProviders(ctx *gin.Context) ([]*ai_dto.Sim return i.module.SimpleProviders(ctx) } -func (i *imlProviderController) SimpleConfiguredProviders(ctx *gin.Context) ([]*ai_dto.SimpleProviderItem, *ai_dto.BackupProvider, error) { - return i.module.SimpleConfiguredProviders(ctx) +func (i *imlProviderController) SimpleConfiguredProviders(ctx *gin.Context, all string) ([]*ai_dto.SimpleProviderItem, *ai_dto.BackupProvider, error) { + if all == "true" { + return i.module.SimpleConfiguredProviders(ctx, true) + } + return i.module.SimpleConfiguredProviders(ctx, false) } func (i *imlProviderController) Provider(ctx *gin.Context, id string) (*ai_dto.Provider, error) { diff --git a/module/ai/dto/output.go b/module/ai/dto/output.go index 21a929ed..27d07eae 100644 --- a/module/ai/dto/output.go +++ b/module/ai/dto/output.go @@ -58,13 +58,14 @@ type SimpleProviderItem struct { DefaultConfig string `json:"default_config"` Status ProviderStatus `json:"status"` Model *BasicInfo `json:"model,omitempty"` - Priority int `json:"-"` + Type string `json:"type"` } type BackupProvider struct { Id string `json:"id"` Name string `json:"name"` Model *BasicInfo `json:"model,omitempty"` + Type string `json:"type"` } type LLMItem struct { diff --git a/module/ai/iml.go b/module/ai/iml.go index 801672b7..f68539f8 100644 --- a/module/ai/iml.go +++ b/module/ai/iml.go @@ -219,6 +219,7 @@ func (i *imlProviderModule) SimpleProviders(ctx context.Context) ([]*ai_dto.Simp providerMap := utils.SliceToMap(list, func(e *ai.Provider) string { return e.Id }) + items := make([]*ai_dto.SimpleProviderItem, 0, len(providers)) for _, v := range providers { item := &ai_dto.SimpleProviderItem{ @@ -231,31 +232,47 @@ func (i *imlProviderModule) SimpleProviders(ctx context.Context) ([]*ai_dto.Simp if info, has := providerMap[v.ID()]; has { item.Configured = true item.Status = ai_dto.ToProviderStatus(info.Status) - item.Priority = info.Priority } items = append(items, item) } - sort.Slice(items, func(i, j int) bool { - if items[i].Priority != items[j].Priority { - if items[i].Priority == 0 { - return false - } - if items[j].Priority == 0 { - return true - } - return items[i].Priority < items[j].Priority - } - return items[i].Name < items[j].Name - }) + + //sort.Slice(items, func(i, j int) bool { + // if items[i].Priority != items[j].Priority { + // if items[i].Priority == 0 { + // return false + // } + // if items[j].Priority == 0 { + // return true + // } + // return items[i].Priority < items[j].Priority + // } + // return items[i].Name < items[j].Name + //}) return items, nil } -func (i *imlProviderModule) SimpleConfiguredProviders(ctx context.Context) ([]*ai_dto.SimpleProviderItem, *ai_dto.BackupProvider, error) { +func (i *imlProviderModule) SimpleConfiguredProviders(ctx context.Context, all bool) ([]*ai_dto.SimpleProviderItem, *ai_dto.BackupProvider, error) { list, err := i.providerService.List(ctx) if err != nil { return nil, nil, err } + items := make([]*ai_dto.SimpleProviderItem, 0, len(list)) + + healthProvider := make(map[string]struct{}) + if all { + healthProvider["ollama"] = struct{}{} + items = append(items, &ai_dto.SimpleProviderItem{ + Id: "ollama", + Name: "Ollama", + Logo: ollamaSvg, + Configured: true, + DefaultConfig: "", + Status: ai_dto.ProviderEnabled, + Type: "local", + }) + } + var backup *ai_dto.BackupProvider for _, l := range list { p, has := model_runtime.GetProvider(l.Id) @@ -275,34 +292,32 @@ func (i *imlProviderModule) SimpleConfiguredProviders(ctx context.Context) ([]*a Logo: p.Logo(), DefaultConfig: p.DefaultConfig(), Status: ai_dto.ToProviderStatus(l.Status), - Priority: l.Priority, Configured: true, Model: &ai_dto.BasicInfo{ Id: model.ID(), Name: model.ID(), }, } - + if item.Status == ai_dto.ProviderEnabled { + healthProvider[l.Id] = struct{}{} + } items = append(items, item) } - sort.Slice(items, func(i, j int) bool { - if items[i].Priority != items[j].Priority { - if items[i].Priority == 0 { - return false - } - if items[j].Priority == 0 { - return true - } - return items[i].Priority < items[j].Priority - } - return items[i].Name < items[j].Name - }) - for _, item := range items { - if item.Status == ai_dto.ProviderEnabled { + + aiBalanceItems, err := i.aiBalanceService.Search(ctx, "", nil, "priority asc") + if err != nil { + return nil, nil, err + } + for _, item := range aiBalanceItems { + if _, has := healthProvider[item.Provider]; has { backup = &ai_dto.BackupProvider{ - Id: item.Id, - Name: item.Name, - Model: item.Model, + Id: item.Provider, + Name: item.Provider, + Model: &ai_dto.BasicInfo{ + Id: item.Model, + Name: item.Model, + }, + Type: "local", } break } diff --git a/module/ai/module.go b/module/ai/module.go index 40d1e1a9..650de0ff 100644 --- a/module/ai/module.go +++ b/module/ai/module.go @@ -13,7 +13,7 @@ type IProviderModule interface { ConfiguredProviders(ctx context.Context, keyword string) ([]*ai_dto.ConfiguredProviderItem, error) UnConfiguredProviders(ctx context.Context) ([]*ai_dto.ProviderItem, error) SimpleProviders(ctx context.Context) ([]*ai_dto.SimpleProviderItem, error) - SimpleConfiguredProviders(ctx context.Context) ([]*ai_dto.SimpleProviderItem, *ai_dto.BackupProvider, error) + SimpleConfiguredProviders(ctx context.Context, all bool) ([]*ai_dto.SimpleProviderItem, *ai_dto.BackupProvider, error) Provider(ctx context.Context, id string) (*ai_dto.Provider, error) SimpleProvider(ctx context.Context, id string) (*ai_dto.SimpleProvider, error) LLMs(ctx context.Context, driver string) ([]*ai_dto.LLMItem, *ai_dto.ProviderItem, error) diff --git a/module/ai/svg.go b/module/ai/svg.go new file mode 100644 index 00000000..92b50ec8 --- /dev/null +++ b/module/ai/svg.go @@ -0,0 +1,101 @@ +package ai + +var ( + ollamaSvg = ` + + + + + + + + + + + +` +) diff --git a/plugins/core/ai.go b/plugins/core/ai.go index dfc0cb69..a1ef62f7 100644 --- a/plugins/core/ai.go +++ b/plugins/core/ai.go @@ -13,7 +13,7 @@ func (p *plugin) aiAPIs() []pm3.Api { pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/providers/unconfigured", []string{"context"}, []string{"providers"}, p.aiProviderController.UnConfiguredProviders, access.SystemSettingsAiProviderView), pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/providers/configured", []string{"context", "query:keyword"}, []string{"providers"}, p.aiProviderController.ConfiguredProviders, access.SystemSettingsAiProviderView), pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/ai/providers", []string{"context"}, []string{"providers"}, p.aiProviderController.SimpleProviders), - pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/ai/providers/configured", []string{"context"}, []string{"providers", "backup"}, p.aiProviderController.SimpleConfiguredProviders), + pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/ai/providers/configured", []string{"context", "query:all"}, []string{"providers", "backup"}, p.aiProviderController.SimpleConfiguredProviders), pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/provider/config", []string{"context", "query:provider"}, []string{"provider"}, p.aiProviderController.Provider, access.SystemSettingsAiProviderView), pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/ai/provider", []string{"context", "query:provider"}, []string{"provider"}, p.aiProviderController.SimpleProvider), pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/provider/llms", []string{"context", "query:provider"}, []string{"llms", "provider"}, p.aiProviderController.LLMs),