mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-04 10:13:53 +08:00
Fix: Issue where the service status is not updated after the local model download is completed
This commit is contained in:
@@ -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,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,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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user