Merge branch 'feature/1.5-local-model' into 'main'

Feature/1.5 local model

See merge request apipark/APIPark!177
This commit is contained in:
刘健
2025-02-14 20:25:11 +08:00
12 changed files with 145 additions and 11 deletions
+1
View File
@@ -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",
+34
View File
@@ -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"`
+4
View File
@@ -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,
})
+3 -2
View File
@@ -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 {
+23 -6
View File
@@ -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 {
+46
View File
@@ -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"])
+16 -3
View File
@@ -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
}
+11
View File
@@ -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()
}
+4
View File
@@ -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
}
+1
View File
@@ -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() {
+1
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/eolinker/go-common/utils"
"github.com/eolinker/go-common/auto"
+1
View File
@@ -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:是否为服务端项目"`