mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-26 16:01:56 +08:00
Merge branch 'feature/1.5-local-model' into 'main'
fix: ai deploy bug See merge request apipark/APIPark!198
This commit is contained in:
+15
-22
@@ -3,15 +3,12 @@ package ai_local
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/APIParkLab/APIPark/module/router"
|
||||
|
||||
"github.com/APIParkLab/APIPark/model/plugin_model"
|
||||
@@ -100,13 +97,13 @@ func (i *imlLocalModelController) Deploy(ctx *gin.Context) {
|
||||
return
|
||||
|
||||
}
|
||||
err = i.initAILocalService(ctx, input.Model, input.Team)
|
||||
if err != nil {
|
||||
ctx.JSON(200, gin.H{
|
||||
"code": -1, "msg": err.Error(), "success": "fail",
|
||||
})
|
||||
return
|
||||
}
|
||||
//err = i.initAILocalService(ctx, input.Model, input.Team)
|
||||
//if err != nil {
|
||||
// ctx.JSON(200, gin.H{
|
||||
// "code": -1, "msg": err.Error(), "success": "fail",
|
||||
// })
|
||||
// return
|
||||
//}
|
||||
id := uuid.NewString()
|
||||
p, err := i.module.Deploy(ctx, input.Model, id)
|
||||
if err != nil {
|
||||
@@ -199,23 +196,15 @@ func (i *imlLocalModelController) DeployStart(ctx *gin.Context, input *ai_local_
|
||||
|
||||
func (i *imlLocalModelController) initAILocalService(ctx context.Context, model string, teamID string) error {
|
||||
err := i.transaction.Transaction(ctx, func(ctx context.Context) error {
|
||||
_, err := i.serviceModule.Get(ctx, model)
|
||||
if err == nil {
|
||||
return nil
|
||||
} else {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
catalogueInfo, err := i.catalogueModule.DefaultCatalogue(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceId := uuid.NewString()
|
||||
prefix := fmt.Sprintf("/%s", serviceId[:8])
|
||||
providerId := "ollama"
|
||||
prefix := strings.Replace("/"+model, ":", "_", -1)
|
||||
info, err := i.serviceModule.Create(ctx, teamID, &service_dto.CreateService{
|
||||
Id: model,
|
||||
Id: serviceId,
|
||||
Name: model,
|
||||
Prefix: prefix,
|
||||
Description: "Auto generated service for AI model " + model,
|
||||
@@ -229,6 +218,10 @@ func (i *imlLocalModelController) initAILocalService(ctx context.Context, model
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = i.module.SaveCache(ctx, model, serviceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := fmt.Sprintf("/%s/chat", strings.Trim(prefix, "/"))
|
||||
timeout := 300000
|
||||
retry := 0
|
||||
@@ -244,7 +237,7 @@ func (i *imlLocalModelController) initAILocalService(ctx context.Context, model
|
||||
}
|
||||
name := "Demo AI API"
|
||||
description := "A demo that shows you how to use a e a Chat API."
|
||||
apiId := uuid.New().String()
|
||||
apiId := uuid.NewString()
|
||||
err = i.aiAPIModule.Create(
|
||||
ctx,
|
||||
info.Id,
|
||||
|
||||
+81
-21
@@ -7,6 +7,8 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/api"
|
||||
|
||||
"github.com/eolinker/eosc/env"
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
@@ -43,8 +45,10 @@ type imlLocalModel struct {
|
||||
localModelService ai_local.ILocalModelService `autowired:""`
|
||||
localModelPackageService ai_local.ILocalModelPackageService `autowired:""`
|
||||
localModelStateService ai_local.ILocalModelInstallStateService `autowired:""`
|
||||
localModelCacheService ai_local.ILocalModelCacheService `autowired:""`
|
||||
clusterService cluster.IClusterService `autowired:""`
|
||||
aiAPIService ai_api.IAPIService `autowired:""`
|
||||
routerService api.IAPIService `autowired:""`
|
||||
serviceService service.IServiceService `autowired:""`
|
||||
transaction store.ITransaction `autowired:""`
|
||||
}
|
||||
@@ -181,7 +185,7 @@ func (i *imlLocalModel) pullHook() func(msg ai_provider_local.PullMessage) error
|
||||
State: state,
|
||||
Msg: msg.Msg,
|
||||
})
|
||||
|
||||
info, err = i.localModelStateService.Get(ctx, msg.Model)
|
||||
} else {
|
||||
if info.Complete < msg.Completed {
|
||||
info.Complete = msg.Completed
|
||||
@@ -201,30 +205,54 @@ func (i *imlLocalModel) pullHook() func(msg ai_provider_local.PullMessage) error
|
||||
if msg.Status == "error" {
|
||||
state = 2
|
||||
}
|
||||
err = i.serviceService.Save(ctx, msg.Model, &service.Edit{State: &serviceState})
|
||||
list, err := i.localModelCacheService.List(ctx, msg.Model, ai_local.CacheTypeService)
|
||||
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
|
||||
}
|
||||
cfg := make(map[string]interface{})
|
||||
cfg["provider"] = "ollama"
|
||||
cfg["model"] = msg.Model
|
||||
cfg["model_config"] = ollamaConfig
|
||||
cfg["priority"] = 0
|
||||
cfg["base"] = ollamaBase
|
||||
return i.syncGateway(ctx, cluster.DefaultClusterID, []*gateway.DynamicRelease{
|
||||
{
|
||||
BasicItem: &gateway.BasicItem{
|
||||
ID: msg.Model,
|
||||
Description: msg.Model,
|
||||
Resource: "ai-provider",
|
||||
Version: info.UpdateAt.Format("20060102150405"),
|
||||
MatchLabels: map[string]string{
|
||||
"module": "ai-provider",
|
||||
if state == ai_local_dto.DeployStateFinish.Int() {
|
||||
cfg := make(map[string]interface{})
|
||||
cfg["provider"] = "ollama"
|
||||
cfg["model"] = msg.Model
|
||||
cfg["model_config"] = ollamaConfig
|
||||
cfg["priority"] = 0
|
||||
cfg["base"] = ollamaBase
|
||||
|
||||
return i.syncGateway(ctx, cluster.DefaultClusterID, []*gateway.DynamicRelease{
|
||||
{
|
||||
BasicItem: &gateway.BasicItem{
|
||||
ID: msg.Model,
|
||||
Description: msg.Model,
|
||||
Resource: "ai-provider",
|
||||
Version: info.UpdateAt.Format("20060102150405"),
|
||||
MatchLabels: map[string]string{
|
||||
"module": "ai-provider",
|
||||
},
|
||||
},
|
||||
},
|
||||
Attr: cfg,
|
||||
}}, true)
|
||||
Attr: cfg,
|
||||
}}, true)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -294,9 +322,41 @@ func (i *imlLocalModel) Deploy(ctx context.Context, model string, session string
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (i *imlLocalModel) SaveCache(ctx context.Context, model string, target string) error {
|
||||
return i.localModelCacheService.Save(ctx, model, ai_local.CacheTypeService, target)
|
||||
}
|
||||
|
||||
func (i *imlLocalModel) CancelDeploy(ctx context.Context, model string) error {
|
||||
return i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||
err := i.serviceService.ForceDelete(ctx, model)
|
||||
list, err := i.localModelCacheService.List(ctx, model, ai_local.CacheTypeService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, l := range list {
|
||||
info, 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.Delete(ctx, info.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = i.aiAPIService.DeleteByService(ctx, info.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = i.routerService.DeleteByService(ctx, info.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = i.localModelCacheService.Delete(ctx, model)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ type ILocalModelModule interface {
|
||||
Disable(ctx context.Context, model string) error
|
||||
ModelState(ctx context.Context, model string) (*ai_local_dto.DeployState, *ai_local_dto.ModelInfo, error)
|
||||
SimpleList(ctx context.Context) ([]*ai_local_dto.SimpleItem, error)
|
||||
SaveCache(ctx context.Context, model string, target string) error
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -26,7 +26,7 @@ func (s ServiceState) Int() int {
|
||||
case ServiceStateDeployError:
|
||||
return 2
|
||||
default:
|
||||
return -1
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -282,6 +282,7 @@ func toServiceItem(model *service.Service) *service_dto.ServiceItem {
|
||||
|
||||
switch model.Kind {
|
||||
case service.RestService:
|
||||
item.State = model.ServiceType.String()
|
||||
return item
|
||||
case service.AIService:
|
||||
provider := auto.UUID(model.AdditionalConfig["provider"])
|
||||
|
||||
@@ -23,6 +23,14 @@ type imlAPIService struct {
|
||||
universally.IServiceDelete
|
||||
}
|
||||
|
||||
func (i *imlAPIService) DeleteByService(ctx context.Context, serviceId string) error {
|
||||
_, err := i.store.DeleteWhere(ctx, map[string]interface{}{"service": serviceId})
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *imlAPIService) CountMapByModel(ctx context.Context, keyword string, conditions map[string]interface{}) (map[string]int64, error) {
|
||||
return i.store.CountByGroup(ctx, keyword, conditions, "model")
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ type IAPIService interface {
|
||||
universally.IServiceDelete
|
||||
CountMapByProvider(ctx context.Context, keyword string, conditions map[string]interface{}) (map[string]int64, error)
|
||||
CountMapByModel(ctx context.Context, keyword string, conditions map[string]interface{}) (map[string]int64, error)
|
||||
DeleteByService(ctx context.Context, serviceId string) error
|
||||
}
|
||||
|
||||
type IAPIUseService interface {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package ai_local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally"
|
||||
"github.com/APIParkLab/APIPark/stores/ai"
|
||||
)
|
||||
@@ -187,3 +190,39 @@ func (i *imlLocalModelInstallStateService) updateHandler(e *ai.LocalModelInstall
|
||||
}
|
||||
e.UpdateAt = time.Now()
|
||||
}
|
||||
|
||||
var _ ILocalModelCacheService = &imlLocalModelCacheService{}
|
||||
|
||||
type imlLocalModelCacheService struct {
|
||||
store ai.ILocalModelCacheStore `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlLocalModelCacheService) List(ctx context.Context, model string, typ CacheType) ([]*LocalModelCache, error) {
|
||||
list, err := i.store.List(ctx, map[string]interface{}{"model": model, "type": typ.Int()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, func(s *ai.LocalModelCache) *LocalModelCache {
|
||||
return &LocalModelCache{
|
||||
Model: s.Model,
|
||||
Target: s.Target,
|
||||
Type: CacheType(s.Type),
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (i *imlLocalModelCacheService) Delete(ctx context.Context, model string) error {
|
||||
_, err := i.store.DeleteWhere(ctx, map[string]interface{}{"model": model})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *imlLocalModelCacheService) Save(ctx context.Context, model string, typ CacheType, target string) error {
|
||||
return i.store.Insert(ctx, &ai.LocalModelCache{
|
||||
Model: model,
|
||||
Target: target,
|
||||
Type: typ.Int(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -75,3 +75,37 @@ type EditLocalModelInstallState struct {
|
||||
State *int
|
||||
Msg *string
|
||||
}
|
||||
|
||||
type LocalModelCache struct {
|
||||
Model string
|
||||
Target string
|
||||
Type CacheType
|
||||
}
|
||||
|
||||
type CacheType string
|
||||
|
||||
func (c CacheType) String() string {
|
||||
return string(c)
|
||||
}
|
||||
|
||||
func (c CacheType) Int() int {
|
||||
switch c {
|
||||
case CacheTypeService:
|
||||
return 0
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func FromCacheType(s int) CacheType {
|
||||
switch s {
|
||||
case 0:
|
||||
return CacheTypeService
|
||||
default:
|
||||
return CacheTypeService
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
CacheTypeService CacheType = "service"
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ai_local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally"
|
||||
@@ -28,6 +29,12 @@ type ILocalModelInstallStateService interface {
|
||||
universally.IServiceDelete
|
||||
}
|
||||
|
||||
type ILocalModelCacheService interface {
|
||||
List(ctx context.Context, model string, typ CacheType) ([]*LocalModelCache, error)
|
||||
Delete(ctx context.Context, model string) error
|
||||
Save(ctx context.Context, model string, typ CacheType, target string) error
|
||||
}
|
||||
|
||||
func init() {
|
||||
autowire.Auto[ILocalModelService](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlLocalModelService))
|
||||
@@ -39,4 +46,8 @@ func init() {
|
||||
autowire.Auto[ILocalModelInstallStateService](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlLocalModelInstallStateService))
|
||||
})
|
||||
|
||||
autowire.Auto[ILocalModelCacheService](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlLocalModelCacheService))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -41,6 +41,13 @@ type imlAPIService struct {
|
||||
universally.IServiceDelete
|
||||
}
|
||||
|
||||
func (i *imlAPIService) DeleteByService(ctx context.Context, serviceId string) error {
|
||||
_, err := i.store.DeleteWhere(ctx, map[string]interface{}{
|
||||
"service": serviceId,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListForServices(ctx context.Context, serviceIds ...string) ([]*API, error) {
|
||||
w := map[string]interface{}{}
|
||||
if len(serviceIds) > 0 {
|
||||
|
||||
@@ -43,6 +43,7 @@ type IAPIService interface {
|
||||
|
||||
Save(ctx context.Context, id string, model *Edit) error
|
||||
Create(ctx context.Context, input *Create) (err error)
|
||||
DeleteByService(ctx context.Context, serviceId string) error
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -149,3 +149,18 @@ func (i *LocalModelPackage) TableName() string {
|
||||
func (i *LocalModelPackage) IdValue() int64 {
|
||||
return i.Id
|
||||
}
|
||||
|
||||
type LocalModelCache struct {
|
||||
Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:id;primary_key;comment:主键ID;"`
|
||||
Model string `gorm:"type:varchar(100);not null;column:model;comment:模型ID"`
|
||||
Target string `gorm:"type:varchar(100);not null;column:target;comment:目标"`
|
||||
Type int `gorm:"type:tinyint(1);not null;column:type;comment:类型,0: 服务"`
|
||||
}
|
||||
|
||||
func (i *LocalModelCache) TableName() string {
|
||||
return "ai_local_model_cache"
|
||||
}
|
||||
|
||||
func (i *LocalModelCache) IdValue() int64 {
|
||||
return i.Id
|
||||
}
|
||||
|
||||
@@ -63,6 +63,14 @@ type imlLocalModelInstallStateStore struct {
|
||||
store.SearchStore[LocalModelInstallState]
|
||||
}
|
||||
|
||||
type ILocalModelCacheStore interface {
|
||||
store.IBaseStore[LocalModelCache]
|
||||
}
|
||||
|
||||
type imlLocalModelCacheStore struct {
|
||||
store.Store[LocalModelCache]
|
||||
}
|
||||
|
||||
func init() {
|
||||
autowire.Auto[IProviderStore](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlProviderStore))
|
||||
@@ -91,4 +99,8 @@ func init() {
|
||||
autowire.Auto[ILocalModelInstallStateStore](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlLocalModelInstallStateStore))
|
||||
})
|
||||
|
||||
autowire.Auto[ILocalModelCacheStore](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlLocalModelCacheStore))
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user