Fix: Issue where the service status is not updated after the local model download is completed

This commit is contained in:
Liujian
2025-02-19 10:57:39 +08:00
parent 9a833023ce
commit 690c2fe2f7
7 changed files with 97 additions and 72 deletions
+12
View File
@@ -210,6 +210,9 @@ func (e *AsyncExecutor) DistributeToModelPipelines(model string, msg PullMessage
type PullCallback func(msg PullMessage) error
func PullModel(model string, id string, fn PullCallback) (*Pipeline, error) {
if client == nil {
return nil, fmt.Errorf("client not initialized")
}
mp, has := taskExecutor.GetModelPipeline(model)
if !has {
mp = newModelPipeline(taskExecutor.ctx, 100)
@@ -279,6 +282,9 @@ func PullModel(model string, id string, fn PullCallback) (*Pipeline, error) {
}
func StopPull(model string) {
if client == nil {
return
}
taskExecutor.CloseModelPipeline(model)
}
@@ -287,6 +293,9 @@ func CancelPipeline(model string, id string) {
}
func RemoveModel(model string) error {
if client == nil {
return fmt.Errorf("client not initialized")
}
taskExecutor.CloseModelPipeline(model)
err := client.Delete(context.Background(), &api.DeleteRequest{Model: model})
if err != nil {
@@ -298,6 +307,9 @@ func RemoveModel(model string) error {
}
func ModelsInstalled() ([]Model, error) {
if client == nil {
return nil, fmt.Errorf("client not initialized")
}
result, err := client.List(context.Background())
if err != nil {
return nil, err
+4 -13
View File
@@ -4,27 +4,18 @@ import (
"net/http"
"net/url"
"github.com/eolinker/eosc/env"
"github.com/ollama/ollama/api"
)
var (
ollamaAddress = "http://127.0.0.1:11434"
EnvOllamaAddress = "OLLAMA_ADDRESS"
client *api.Client
client *api.Client
)
func init() {
address, has := env.GetEnv(EnvOllamaAddress)
if !has {
address = ollamaAddress
}
func ResetOllamaAddress(address string) error {
u, err := url.Parse(address)
if err != nil {
u, err = url.Parse(ollamaAddress)
if err != nil {
panic(err)
}
return err
}
client = api.NewClient(u, http.DefaultClient)
return nil
}
-1
View File
@@ -1,7 +1,6 @@
package ai_provider_local
var (
OllamaBase = "http://apipark-ollama:11434"
OllamaConfig = "{\n \"mirostat\": 0,\n \"mirostat_eta\": 0.1,\n \"mirostat_tau\": 5.0,\n \"num_ctx\": 4096,\n \"repeat_last_n\":64,\n \"repeat_penalty\": 1.1,\n \"temperature\": 0.7,\n \"seed\": 42,\n \"num_predict\": 42,\n \"top_k\": 40,\n \"top_p\": 0.9,\n \"min_p\": 0.5\n}\n"
OllamaSvg = `<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+1 -1
View File
@@ -248,7 +248,7 @@ func (i *imlInitController) OnInit() {
if len(items) == 0 {
err = i.catalogueModule.Create(ctx, &catalogue_dto.CreateCatalogue{
Id: catalogueId,
Name: "Default Catalogue",
Name: "Default Category",
})
if err != nil {
return fmt.Errorf("create default catalogue error: %v", err)
+16 -9
View File
@@ -6,6 +6,8 @@ import (
"fmt"
"sort"
"github.com/APIParkLab/APIPark/service/setting"
ai_provider_local "github.com/APIParkLab/APIPark/ai-provider/local"
model_runtime "github.com/APIParkLab/APIPark/ai-provider/model-runtime"
@@ -37,6 +39,7 @@ type imlBalanceModule struct {
aiAPIService ai_api.IAPIService `autowired:""`
aiKeyService ai_key.IKeyService `autowired:""`
balanceService ai_balance.IBalanceService `autowired:""`
settingService setting.ISettingService `autowired:""`
transaction store.ITransaction `autowired:""`
}
@@ -73,6 +76,11 @@ func (i *imlBalanceModule) Create(ctx context.Context, input *ai_balance_dto.Cre
providerName = "Ollama"
modelName = input.Model
}
v, has := i.settingService.Get(ctx, "system.ai_model.ollama_address")
if !has {
return fmt.Errorf("ollama address not found")
}
return i.transaction.Transaction(ctx, func(ctx context.Context) error {
err = i.balanceService.Create(ctx, &ai_balance.Create{
Id: input.Id,
@@ -90,23 +98,18 @@ func (i *imlBalanceModule) Create(ctx context.Context, input *ai_balance_dto.Cre
if err != nil {
return err
}
return i.syncGateway(ctx, cluster.DefaultClusterID, []*gateway.DynamicRelease{newRelease(item)}, true)
return i.syncGateway(ctx, cluster.DefaultClusterID, []*gateway.DynamicRelease{newRelease(item, v)}, true)
})
}
//var (
// ollamaConfig = "{\n \"mirostat\": 0,\n \"mirostat_eta\": 0.1,\n \"mirostat_tau\": 5.0,\n \"num_ctx\": 4096,\n \"repeat_last_n\":64,\n \"repeat_penalty\": 1.1,\n \"temperature\": 0.7,\n \"seed\": 42,\n \"num_predict\": 42,\n \"top_k\": 40,\n \"top_p\": 0.9,\n \"min_p\": 0.5\n}\n"
// ollamaBase = "http://apipark-ollama:11434"
//)
func newRelease(item *ai_balance.Balance) *gateway.DynamicRelease {
func newRelease(item *ai_balance.Balance, base string) *gateway.DynamicRelease {
cfg := make(map[string]interface{})
cfg["provider"] = item.Id
cfg["model"] = item.Model
cfg["model_config"] = ai_provider_local.OllamaConfig
cfg["base"] = ai_provider_local.OllamaBase
cfg["base"] = base
return &gateway.DynamicRelease{
BasicItem: &gateway.BasicItem{
ID: item.Id,
@@ -133,9 +136,13 @@ func (i *imlBalanceModule) Sort(ctx context.Context, input *ai_balance_dto.Sort)
if err != nil {
return err
}
v, has := i.settingService.Get(ctx, "system.ai_model.ollama_address")
if !has {
return fmt.Errorf("ollama address not found")
}
releases := make([]*gateway.DynamicRelease, 0, len(list))
for _, item := range list {
releases = append(releases, newRelease(item))
releases = append(releases, newRelease(item, v))
}
err = i.syncGateway(ctx, cluster.DefaultClusterID, releases, true)
if err != nil {
+44 -48
View File
@@ -4,12 +4,11 @@ import (
"context"
"errors"
"fmt"
"net/url"
"strings"
"github.com/APIParkLab/APIPark/service/api"
"github.com/APIParkLab/APIPark/service/setting"
"github.com/eolinker/eosc/env"
"github.com/APIParkLab/APIPark/service/api"
"github.com/APIParkLab/APIPark/gateway"
"github.com/eolinker/eosc/log"
@@ -50,26 +49,10 @@ type imlLocalModel struct {
aiAPIService ai_api.IAPIService `autowired:""`
routerService api.IAPIService `autowired:""`
serviceService service.IServiceService `autowired:""`
settingService setting.ISettingService `autowired:""`
transaction store.ITransaction `autowired:""`
}
var (
// ollamaConfig = "{\n \"mirostat\": 0,\n \"mirostat_eta\": 0.1,\n \"mirostat_tau\": 5.0,\n \"num_ctx\": 4096,\n \"repeat_last_n\":64,\n \"repeat_penalty\": 1.1,\n \"temperature\": 0.7,\n \"seed\": 42,\n \"num_predict\": 42,\n \"top_k\": 40,\n \"top_p\": 0.9,\n \"min_p\": 0.5\n}\n"
ollamaBase = "http://apipark-ollama:11434"
)
func init() {
base, has := env.GetEnv("OLLAMA_BASE")
if !has {
return
}
_, err := url.Parse(base)
if err == nil {
ollamaBase = base
}
}
func (i *imlLocalModel) SimpleList(ctx context.Context) ([]*ai_local_dto.SimpleItem, error) {
list, err := i.localModelService.List(ctx)
if err != nil {
@@ -122,7 +105,7 @@ func (i *imlLocalModel) Search(ctx context.Context, keyword string) ([]*ai_local
Name: s.Name,
State: ai_local_dto.FromLocalModelState(s.State),
APICount: count,
CanDelete: count < 1,
CanDelete: count < 1 && s.State != ai_local_dto.LocalModelStateDeploying.Int(),
UpdateTime: auto.TimeLabel(s.UpdateAt),
Provider: "ollama",
}
@@ -194,7 +177,7 @@ func (i *imlLocalModel) pullHook(fn ...func() error) func(msg ai_provider_local.
State: state,
Msg: msg.Msg,
})
info, err = i.localModelStateService.Get(ctx, msg.Model)
} else {
if info.Complete < msg.Completed {
info.Complete = msg.Completed
@@ -210,34 +193,31 @@ func (i *imlLocalModel) pullHook(fn ...func() error) func(msg ai_provider_local.
if err != nil {
return err
}
serviceState := 0
if msg.Status == "error" {
state = 2
}
serviceState := 0
if msg.Status == "error" {
state = 2
}
list, err := i.localModelCacheService.List(ctx, msg.Model, ai_local.CacheTypeService)
if err != nil {
return err
}
for _, l := range list {
serviceInfo, err := i.serviceService.Get(ctx, l.Target)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
continue
}
return err
}
list, err := i.localModelCacheService.List(ctx, msg.Model, ai_local.CacheTypeService)
if serviceInfo.State == serviceState {
continue
}
err = i.serviceService.Save(ctx, l.Target, &service.Edit{State: &serviceState})
if err != nil {
return err
}
for _, l := range list {
_, err := i.serviceService.Get(ctx, l.Target)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
continue
}
return err
}
if info.State == 0 {
continue
}
err = i.serviceService.Save(ctx, l.Target, &service.Edit{State: &serviceState})
if err != nil {
return err
}
}
}
if err != nil {
return err
}
if state == ai_local_dto.DeployStateFinish.Int() {
for _, f := range fn {
@@ -246,12 +226,14 @@ func (i *imlLocalModel) pullHook(fn ...func() error) func(msg ai_provider_local.
return err
}
}
v, _ := i.settingService.Get(ctx, "system.ai_model.ollama_address")
cfg := make(map[string]interface{})
cfg["provider"] = "ollama"
cfg["model"] = msg.Model
cfg["model_config"] = ai_provider_local.OllamaConfig
cfg["priority"] = 0
cfg["base"] = ollamaBase
cfg["base"] = v
return i.syncGateway(ctx, cluster.DefaultClusterID, []*gateway.DynamicRelease{
{
@@ -414,6 +396,16 @@ func (i *imlLocalModel) RemoveModel(ctx context.Context, model string) error {
if count > 0 {
return fmt.Errorf("model %s has api, can not remove", model)
}
info, err := i.localModelService.Get(ctx, model)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
return ai_provider_local.RemoveModel(model)
}
if info.State == ai_local_dto.LocalModelStateDeploying.Int() {
return fmt.Errorf("model %s is deploying, can not remove", model)
}
return i.transaction.Transaction(ctx, func(txCtx context.Context) error {
err = i.localModelService.Delete(ctx, model)
if err != nil {
@@ -528,13 +520,17 @@ func (i *imlLocalModel) getLocalModels(ctx context.Context) ([]*gateway.DynamicR
if err != nil {
return nil, err
}
v, has := i.settingService.Get(ctx, "system.ai_model.ollama_address")
if !has {
return nil, errors.New("ollama_address not set")
}
releases := make([]*gateway.DynamicRelease, 0, len(list))
for _, l := range list {
cfg := make(map[string]interface{})
cfg["provider"] = "ollama"
cfg["model"] = l.Id
cfg["model_config"] = ai_provider_local.OllamaSvg
cfg["base"] = ollamaBase
cfg["base"] = v
releases = append(releases, &gateway.DynamicRelease{
BasicItem: &gateway.BasicItem{
ID: l.Id,
+20
View File
@@ -3,6 +3,11 @@ package system
import (
"context"
"github.com/eolinker/go-common/server"
ai_provider_local "github.com/APIParkLab/APIPark/ai-provider/local"
"github.com/eolinker/go-common/register"
"github.com/eolinker/go-common/store"
"github.com/eolinker/go-common/utils"
@@ -43,6 +48,21 @@ func (i *imlSettingModule) Set(ctx context.Context, input *system_dto.InputSetti
return err
}
}
if input.OllamaAddress != nil {
ai_provider_local.ResetOllamaAddress(*input.OllamaAddress)
}
return nil
})
}
func (i *imlSettingModule) OnInit() {
register.Handle(func(v server.Server) {
ctx := context.Background()
address, has := i.settingService.Get(ctx, "system.ai_model.ollama_address")
if has {
ai_provider_local.ResetOllamaAddress(address)
}
})
}