diff --git a/controller/ai-local/iml.go b/controller/ai-local/iml.go index 493c36c9..e310ecb9 100644 --- a/controller/ai-local/iml.go +++ b/controller/ai-local/iml.go @@ -220,6 +220,7 @@ func (i *imlLocalModelController) initAILocalService(ctx context.Context, model Prefix: prefix, Description: "Auto generated service for AI model " + model, ServiceType: "public", + State: "deploying", Catalogue: catalogueInfo.Id, ApprovalType: "auto", Kind: "ai", diff --git a/module/ai-api/dto/output.go b/module/ai-api/dto/output.go index a00c6690..521d8979 100644 --- a/module/ai-api/dto/output.go +++ b/module/ai-api/dto/output.go @@ -4,6 +4,39 @@ import ( "github.com/eolinker/go-common/auto" ) +type ModelType string + +const ( + ModelTypeOnline ModelType = "online" + ModelTypeLocal ModelType = "local" +) + +func (m ModelType) String() string { + return string(m) +} + +func (m ModelType) Int() int { + switch m { + case ModelTypeOnline: + return 0 + case ModelTypeLocal: + return 1 + default: + return -1 + } +} + +func FromModelType(m int) ModelType { + switch m { + case 0: + return ModelTypeOnline + case 1: + return ModelTypeLocal + default: + return "" + } +} + type API struct { Id string `json:"id"` Name string `json:"name"` @@ -19,6 +52,7 @@ type API struct { type APIItem struct { Id string `json:"id"` Name string `json:"name"` + ModelType ModelType `json:"model_type"` RequestPath string `json:"request_path"` Description string `json:"description"` Disable bool `json:"disabled"` diff --git a/module/ai-api/iml.go b/module/ai-api/iml.go index 12994aa2..548a88df 100644 --- a/module/ai-api/iml.go +++ b/module/ai-api/iml.go @@ -107,6 +107,7 @@ func (i *imlAPIModule) Create(ctx context.Context, serviceId string, input *ai_a if err != nil { return err } + return i.aiAPIService.Create(ctx, &ai_api.Create{ ID: input.Id, Name: input.Name, @@ -118,6 +119,7 @@ func (i *imlAPIModule) Create(ctx context.Context, serviceId string, input *ai_a Retry: input.Retry, Model: input.AiModel.Id, Provider: input.AiModel.Provider, + Type: ai_api_dto.ModelType(input.AiModel.Type).Int(), AdditionalConfig: map[string]interface{}{ "ai_prompt": input.AiPrompt, "ai_model": input.AiModel, @@ -163,6 +165,7 @@ func (i *imlAPIModule) Edit(ctx context.Context, serviceId string, apiId string, if input.AiModel != nil { apiInfo.AdditionalConfig["ai_model"] = input.AiModel } + typ := ai_api_dto.ModelType(input.AiModel.Type).Int() return i.aiAPIService.Save(ctx, apiId, &ai_api.Edit{ Name: input.Name, Path: input.Path, @@ -171,6 +174,7 @@ func (i *imlAPIModule) Edit(ctx context.Context, serviceId string, apiId string, Retry: input.Retry, Model: modelId, Provider: providerId, + Type: &typ, AdditionalConfig: &apiInfo.AdditionalConfig, Disable: input.Disable, }) diff --git a/module/ai-local/dto/output.go b/module/ai-local/dto/output.go index 3486907f..58c224b3 100644 --- a/module/ai-local/dto/output.go +++ b/module/ai-local/dto/output.go @@ -59,8 +59,9 @@ func FromLocalModelState(state int) LocalModelState { } type SimpleItem struct { - Id string `json:"id"` - Name string `json:"name"` + Id string `json:"id"` + Name string `json:"name"` + DefaultConfig string `json:"default_config"` } type LocalModelItem struct { diff --git a/module/ai-local/iml.go b/module/ai-local/iml.go index e153dea4..1aaa80e3 100644 --- a/module/ai-local/iml.go +++ b/module/ai-local/iml.go @@ -6,6 +6,8 @@ import ( "fmt" "strings" + "github.com/APIParkLab/APIPark/service/service" + "github.com/eolinker/go-common/auto" ai_api "github.com/APIParkLab/APIPark/service/ai-api" @@ -34,9 +36,14 @@ type imlLocalModel struct { localModelPackageService ai_local.ILocalModelPackageService `autowired:""` localModelStateService ai_local.ILocalModelInstallStateService `autowired:""` aiAPIService ai_api.IAPIService `autowired:""` + serviceService service.IServiceService `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" +) + func (i *imlLocalModel) SimpleList(ctx context.Context) ([]*ai_local_dto.SimpleItem, error) { list, err := i.localModelService.List(ctx) if err != nil { @@ -44,8 +51,9 @@ func (i *imlLocalModel) SimpleList(ctx context.Context) ([]*ai_local_dto.SimpleI } return utils.SliceToSlice(list, func(s *ai_local.LocalModel) *ai_local_dto.SimpleItem { return &ai_local_dto.SimpleItem{ - Id: s.Id, - Name: s.Name, + Id: s.Id, + Name: s.Name, + DefaultConfig: ollamaConfig, } }, func(l *ai_local.LocalModel) bool { if l.State != ai_local_dto.LocalModelStateNormal.Int() && l.State != ai_local_dto.LocalModelStateDisable.Int() { @@ -203,10 +211,19 @@ func (i *imlLocalModel) Deploy(ctx context.Context, model string, session string } func (i *imlLocalModel) CancelDeploy(ctx context.Context, model string) error { - ai_provider_local.StopPull(model) - - // 删除模型 - return i.localModelService.Delete(ctx, model) + return i.transaction.Transaction(ctx, func(txCtx context.Context) error { + err := i.serviceService.ForceDelete(ctx, model) + if err != nil { + return err + } + // 删除模型 + err = i.localModelService.Delete(ctx, model) + if err != nil { + return err + } + ai_provider_local.StopPull(model) + return nil + }) } func (i *imlLocalModel) RemoveModel(ctx context.Context, model string) error { diff --git a/module/service/dto/output.go b/module/service/dto/output.go index f9e9968d..a4031979 100644 --- a/module/service/dto/output.go +++ b/module/service/dto/output.go @@ -5,6 +5,44 @@ import ( "github.com/eolinker/go-common/auto" ) +type ServiceState string + +const ( + ServiceStateNormal ServiceState = "normal" + ServiceStateDeploying ServiceState = "deploying" + ServiceStateDeployError ServiceState = "error" +) + +func (s ServiceState) String() string { + return string(s) +} + +func (s ServiceState) Int() int { + switch s { + case ServiceStateNormal: + return 0 + case ServiceStateDeploying: + return 1 + case ServiceStateDeployError: + return 2 + default: + return -1 + } +} + +func FromServiceState(s int) ServiceState { + switch s { + case 0: + return ServiceStateNormal + case 1: + return ServiceStateDeploying + case 2: + return ServiceStateDeployError + default: + return "" + } +} + type ServiceItem struct { Id string `json:"id"` Name string `json:"name"` @@ -15,6 +53,7 @@ type ServiceItem struct { CreateTime auto.TimeLabel `json:"create_time"` UpdateTime auto.TimeLabel `json:"update_time"` Provider *auto.Label `json:"provider,omitempty" aolabel:"ai_provider"` + State string `json:"state"` CanDelete bool `json:"can_delete"` } @@ -96,6 +135,13 @@ func ToService(model *service.Service) *Service { AsApp: model.AsApp, ServiceKind: model.Kind.String(), } + state := FromServiceState(model.State) + if state == ServiceStateNormal { + s.State = model.ServiceType.String() + } else { + s.State = state.String() + } + switch model.Kind { case service.AIService: provider := auto.UUID(model.AdditionalConfig["provider"]) diff --git a/module/service/iml.go b/module/service/iml.go index 8edf26d3..25a51694 100644 --- a/module/service/iml.go +++ b/module/service/iml.go @@ -273,6 +273,13 @@ func toServiceItem(model *service.Service) *service_dto.ServiceItem { Team: auto.UUID(model.Team), ServiceKind: model.Kind.String(), } + state := service_dto.FromServiceState(model.State) + if state == service_dto.ServiceStateNormal { + item.State = model.ServiceType.String() + } else { + item.State = state.String() + } + switch model.Kind { case service.RestService: return item @@ -299,6 +306,7 @@ func (i *imlServiceModule) Create(ctx context.Context, teamID string, input *ser Catalogue: input.Catalogue, Prefix: input.Prefix, Logo: input.Logo, + State: service_dto.ServiceState(input.State).Int(), ApprovalType: service.ApprovalType(input.ApprovalType), AdditionalConfig: make(map[string]string), Kind: service.Kind(input.Kind), @@ -375,8 +383,7 @@ func (i *imlServiceModule) Edit(ctx context.Context, id string, input *service_d if input.ApprovalType != nil { approvalType = service.ApprovalType(*input.ApprovalType) } - - err = i.serviceService.Save(ctx, id, &service.Edit{ + editCfg := &service.Edit{ Name: input.Name, Description: input.Description, Logo: input.Logo, @@ -384,7 +391,13 @@ func (i *imlServiceModule) Edit(ctx context.Context, id string, input *service_d Catalogue: input.Catalogue, AdditionalConfig: &info.AdditionalConfig, ApprovalType: &approvalType, - }) + } + if input.State != nil { + state := service_dto.ServiceState(*input.State).Int() + editCfg.State = &state + } + + err = i.serviceService.Save(ctx, id, editCfg) if err != nil { return err } diff --git a/service/service/iml.go b/service/service/iml.go index 719e55e7..47f015fd 100644 --- a/service/service/iml.go +++ b/service/service/iml.go @@ -20,12 +20,18 @@ var ( type imlServiceService struct { store service.IServiceStore `autowired:""` + universally.IServiceGet[Service] universally.IServiceDelete universally.IServiceCreate[Create] universally.IServiceEdit[Edit] } +func (i *imlServiceService) ForceDelete(ctx context.Context, id string) error { + _, err := i.store.DeleteWhere(ctx, map[string]interface{}{"uuid": id}) + return err +} + func (i *imlServiceService) ServiceList(ctx context.Context, serviceIds ...string) ([]*Service, error) { w := make(map[string]interface{}) if len(serviceIds) > 0 { @@ -168,6 +174,7 @@ func createEntityHandler(i *Create) *service.Service { ApprovalType: i.ApprovalType.Int(), Kind: i.Kind.Int(), AdditionalConfig: string(cfg), + State: i.State, Catalogue: i.Catalogue, AsServer: i.AsServer, AsApp: i.AsApp, @@ -199,4 +206,8 @@ func updateHandler(e *service.Service, i *Edit) { if i.ApprovalType != nil { e.ApprovalType = (*i.ApprovalType).Int() } + if i.State != nil { + e.State = *i.State + } + e.UpdateAt = time.Now() } diff --git a/service/service/model.go b/service/service/model.go index 03e19fab..bd8a1b3b 100644 --- a/service/service/model.go +++ b/service/service/model.go @@ -119,6 +119,7 @@ type Service struct { Kind Kind Catalogue string AdditionalConfig map[string]string + State int AsServer bool AsApp bool ApprovalType ApprovalType @@ -144,6 +145,7 @@ func FromEntity(e *service.Service) *Service { ApprovalType: ToApprovalType(e.ApprovalType), AsServer: e.AsServer, AsApp: e.AsApp, + State: e.State, CreateTime: e.CreateAt, UpdateTime: e.UpdateAt, AdditionalConfig: additionalConfig, @@ -162,6 +164,7 @@ type Create struct { Catalogue string AdditionalConfig map[string]string ApprovalType ApprovalType + State int AsServer bool AsApp bool } @@ -174,6 +177,7 @@ type Edit struct { Catalogue *string Logo *string AdditionalConfig *map[string]string + State *int ApprovalType *ApprovalType } diff --git a/service/service/service.go b/service/service/service.go index d91e2d89..a9f67ada 100644 --- a/service/service/service.go +++ b/service/service/service.go @@ -20,6 +20,7 @@ type IServiceService interface { ServiceList(ctx context.Context, serviceIds ...string) ([]*Service, error) ServiceListByKind(ctx context.Context, kind Kind, serviceIds ...string) ([]*Service, error) AppList(ctx context.Context, appIds ...string) ([]*Service, error) + ForceDelete(ctx context.Context, id string) error } func init() { diff --git a/service/universally/create-softDelete.go b/service/universally/create-softDelete.go index d790cd8f..807bb6f8 100644 --- a/service/universally/create-softDelete.go +++ b/service/universally/create-softDelete.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/eolinker/go-common/utils" "github.com/eolinker/go-common/auto" diff --git a/stores/service/model.go b/stores/service/model.go index 22b0fb5a..eafc2933 100644 --- a/stores/service/model.go +++ b/stores/service/model.go @@ -17,6 +17,7 @@ type Service struct { UpdateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;column:update_at;comment:修改时间"` IsDelete int `gorm:"type:tinyint(1);not null;column:is_delete;comment:是否删除"` Kind int `gorm:"type:tinyint(4);not null;column:kind;comment:服务种类,0:Rest服务,1:AI服务"` + State int `gorm:"type:tinyint(4);not null;column:state;comment:状态"` AdditionalConfig string `gorm:"type:text;not null;column:additional_config;comment:额外配置"` ApprovalType int `gorm:"type:tinyint(4);not null;column:approval_type;comment:审核类型"` AsServer bool `gorm:"type:tinyint(1);not null;column:as_server;comment:是否为服务端项目"`