diff --git a/.gitignore b/.gitignore
index cb2bf660..6ab23ba1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,5 @@
/apipark
.gitlab-ci.yml
/.vscode/
+.vscode/
+.air.toml
\ No newline at end of file
diff --git a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx
index 7cda49e0..d5bcaa05 100644
--- a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx
+++ b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx
@@ -241,8 +241,18 @@ function BasicLayout({ project = 'core' }: { project: string }) {
headerTitleRender={() => (
)}
diff --git a/frontend/packages/core/src/pages/system/SystemConfig.tsx b/frontend/packages/core/src/pages/system/SystemConfig.tsx
index cbd9c34c..df38c6ee 100644
--- a/frontend/packages/core/src/pages/system/SystemConfig.tsx
+++ b/frontend/packages/core/src/pages/system/SystemConfig.tsx
@@ -87,10 +87,12 @@ const SystemConfig = forwardRef((_, ref) => {
if (serviceId && configuredProvider.length > 0) {
const providerID = form.getFieldValue('provider')
const provider = configuredProvider?.find((item: any) => item.id === providerID)
- if (provider?.type === 'local') {
- getLocalModelList(false)
- } else {
- getOnlineModelList(provider?.id, false)
+ if (provider) {
+ if (provider?.type === 'local') {
+ getLocalModelList(false)
+ } else {
+ getOnlineModelList(provider?.id, false)
+ }
}
}
} else {
diff --git a/go.mod b/go.mod
index d7878223..a347fe38 100644
--- a/go.mod
+++ b/go.mod
@@ -17,6 +17,7 @@ require (
github.com/influxdata/influxdb-client-go/v2 v2.14.0
github.com/nsqio/go-nsq v1.1.0
github.com/ollama/ollama v0.5.8
+ github.com/stretchr/testify v1.9.0
github.com/urfave/cli v1.22.16
golang.org/x/crypto v0.31.0
gopkg.in/yaml.v3 v3.0.1
@@ -31,6 +32,7 @@ require (
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
@@ -59,6 +61,7 @@ require (
github.com/oapi-codegen/runtime v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/redis/go-redis/v9 v9.5.3 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
diff --git a/module/service/dto/input.go b/module/service/dto/input.go
index dcea95b4..7569d1b5 100644
--- a/module/service/dto/input.go
+++ b/module/service/dto/input.go
@@ -23,6 +23,7 @@ type CreateService struct {
Model *string `json:"model"`
AsApp *bool `json:"as_app"`
AsServer *bool `json:"as_server"`
+ ModelMapping string `json:"model_mapping"`
}
type EditService struct {
@@ -36,6 +37,7 @@ type EditService struct {
Model *string `json:"model"`
ApprovalType *string `json:"approval_type"`
State *string `json:"state"`
+ ModelMapping string `json:"model_mapping"`
}
type CreateApp struct {
diff --git a/module/service/dto/output.go b/module/service/dto/output.go
index ef4e6820..636420f0 100644
--- a/module/service/dto/output.go
+++ b/module/service/dto/output.go
@@ -104,6 +104,7 @@ type Service struct {
AsApp bool `json:"as_app"`
ServiceKind string `json:"service_kind"`
State string `json:"state"`
+ ModelMapping string `json:"model_mapping"`
}
type App struct {
@@ -191,16 +192,17 @@ type ServiceDoc struct {
}
type ExportService struct {
- Id string `json:"id"`
- Name string `json:"name"`
- Prefix string `json:"prefix,omitempty"`
- Description string `json:"description"`
- Team string `json:"team"`
- ServiceType string `json:"service_type"`
- Catalogue string `json:"catalogue"`
- Tags []string `json:"tags"`
- Logo string `json:"logo"`
- Doc string `json:"doc"`
+ Id string `json:"id"`
+ Name string `json:"name"`
+ Prefix string `json:"prefix,omitempty"`
+ Description string `json:"description"`
+ Team string `json:"team"`
+ ServiceType string `json:"service_type"`
+ Catalogue string `json:"catalogue"`
+ Tags []string `json:"tags"`
+ Logo string `json:"logo"`
+ Doc string `json:"doc"`
+ ModelMapping string `json:"model_mapping"`
}
type ExportApp struct {
diff --git a/module/service/iml.go b/module/service/iml.go
index a36197cd..f081fc86 100644
--- a/module/service/iml.go
+++ b/module/service/iml.go
@@ -19,6 +19,7 @@ import (
"github.com/eolinker/ap-account/service/role"
application_authorization "github.com/APIParkLab/APIPark/service/application-authorization"
+ service_model_mapping "github.com/APIParkLab/APIPark/service/service-model-mapping"
api_doc "github.com/APIParkLab/APIPark/service/api-doc"
@@ -68,6 +69,8 @@ type imlServiceModule struct {
apiService api.IAPIService `autowired:""`
apiDocService api_doc.IAPIDocService `autowired:""`
transaction store.ITransaction `autowired:""`
+
+ serviceModelMappingService service_model_mapping.IServiceModelMappingService `autowired:""`
}
func (i *imlServiceModule) ExportAll(ctx context.Context) ([]*service_dto.ExportService, error) {
@@ -116,11 +119,9 @@ func (i *imlServiceModule) ExportAll(ctx context.Context) ([]*service_dto.Export
items = append(items, info)
}
return items, nil
-
}
func (i *imlServiceModule) searchMyServices(ctx context.Context, teamId string, keyword string) ([]*service.Service, error) {
-
userID := utils.UserId(ctx)
condition := make(map[string]interface{})
condition["as_server"] = true
@@ -140,7 +141,6 @@ func (i *imlServiceModule) searchMyServices(ctx context.Context, teamId string,
condition["team"] = teamIds
return i.serviceService.Search(ctx, keyword, condition, "create_at desc")
}
-
}
func (i *imlServiceModule) SearchMyServices(ctx context.Context, teamId string, keyword string) ([]*service_dto.ServiceItem, error) {
@@ -182,7 +182,6 @@ func (i *imlServiceModule) Simple(ctx context.Context) ([]*service_dto.SimpleSer
items := make([]*service_dto.SimpleServiceItem, 0, len(services))
for _, p := range services {
-
items = append(items, &service_dto.SimpleServiceItem{
Id: p.Id,
Name: p.Name,
@@ -195,14 +194,12 @@ func (i *imlServiceModule) Simple(ctx context.Context) ([]*service_dto.SimpleSer
func (i *imlServiceModule) MySimple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error) {
services, err := i.searchMyServices(ctx, "", "")
-
if err != nil {
return nil, err
}
items := make([]*service_dto.SimpleServiceItem, 0, len(services))
for _, p := range services {
-
items = append(items, &service_dto.SimpleServiceItem{
Id: p.Id,
Name: p.Name,
@@ -247,6 +244,13 @@ func (i *imlServiceModule) Get(ctx context.Context, id string) (*service_dto.Ser
}
}
+
+ serviceModelMapping, err := i.serviceModelMappingService.Get(ctx, id)
+ if err != nil {
+ return nil, err
+ }
+ s.ModelMapping = serviceModelMapping.Content
+
log.Infof("get service cost %d ms", time.Since(now).Milliseconds())
return s, nil
}
@@ -318,7 +322,6 @@ func toServiceItem(model *service.Service) *service_dto.ServiceItem {
}
func (i *imlServiceModule) Create(ctx context.Context, teamID string, input *service_dto.CreateService) (*service_dto.Service, error) {
-
if input.Id == "" {
input.Id = uuid.New().String()
}
@@ -356,7 +359,6 @@ func (i *imlServiceModule) Create(ctx context.Context, teamID string, input *ser
return nil, fmt.Errorf("ai service: model can not be empty")
}
mo.AdditionalConfig["model"] = *input.Model
-
}
if input.AsApp == nil {
// 默认值为false
@@ -388,6 +390,14 @@ func (i *imlServiceModule) Create(ctx context.Context, teamID string, input *ser
}
}
}
+
+ err := i.serviceModelMappingService.Save(ctx, &service_model_mapping.Save{
+ Sid: input.Id,
+ Content: input.ModelMapping,
+ })
+ if err != nil {
+ return err
+ }
return i.serviceService.Create(ctx, mo)
})
if err != nil {
@@ -410,7 +420,6 @@ func (i *imlServiceModule) Edit(ctx context.Context, id string, input *service_d
if input.Model != nil {
info.AdditionalConfig["model"] = *input.Model
}
-
}
err = i.transaction.Transaction(ctx, func(ctx context.Context) error {
serviceType := (*service.ServiceType)(input.ServiceType)
@@ -457,9 +466,15 @@ func (i *imlServiceModule) Edit(ctx context.Context, id string, input *service_d
}
}
}
+ err = i.serviceModelMappingService.Save(ctx, &service_model_mapping.Save{
+ Sid: id,
+ Content: input.ModelMapping,
+ })
+ if err != nil {
+ return err
+ }
return nil
})
-
if err != nil {
return nil, err
}
@@ -523,7 +538,6 @@ type imlServiceDocModule struct {
func (i *imlServiceDocModule) ServiceDoc(ctx context.Context, pid string) (*serviceDto.ServiceDoc, error) {
_, err := i.serviceService.Check(ctx, pid, map[string]bool{"as_server": true})
-
if err != nil {
return nil, err
}
@@ -555,7 +569,6 @@ func (i *imlServiceDocModule) ServiceDoc(ctx context.Context, pid string) (*serv
func (i *imlServiceDocModule) SaveServiceDoc(ctx context.Context, pid string, input *serviceDto.SaveServiceDoc) error {
_, err := i.serviceService.Check(ctx, pid, map[string]bool{"as_server": true})
-
if err != nil {
return err
}
@@ -737,7 +750,6 @@ func (i *imlAppModule) Search(ctx context.Context, teamId string, keyword string
}
func (i *imlAppModule) CreateApp(ctx context.Context, teamID string, input *service_dto.CreateApp) (*service_dto.App, error) {
-
if input.Id == "" {
input.Id = uuid.New().String()
}
@@ -759,9 +771,7 @@ func (i *imlAppModule) CreateApp(ctx context.Context, teamID string, input *serv
}
err = i.transaction.Transaction(ctx, func(ctx context.Context) error {
-
return i.serviceService.Create(ctx, mo)
-
})
if err != nil {
return nil, err
@@ -770,7 +780,7 @@ func (i *imlAppModule) CreateApp(ctx context.Context, teamID string, input *serv
}
func (i *imlAppModule) UpdateApp(ctx context.Context, appId string, input *service_dto.UpdateApp) (*service_dto.App, error) {
- //userId := utils.UserId(ctx)
+ // userId := utils.UserId(ctx)
info, err := i.serviceService.Get(ctx, appId)
if err != nil {
return nil, err
@@ -907,7 +917,6 @@ func (i *imlAppModule) MySimpleApps(ctx context.Context, keyword string) ([]*ser
}
items := make([]*service_dto.SimpleAppItem, 0, len(services))
for _, p := range services {
-
items = append(items, &service_dto.SimpleAppItem{
Id: p.Id,
Name: p.Name,
diff --git a/service/service-doc/iml.go b/service/service-doc/iml.go
index ddfcf67a..4546af02 100644
--- a/service/service-doc/iml.go
+++ b/service/service-doc/iml.go
@@ -3,9 +3,10 @@ package service_doc
import (
"context"
"errors"
- "github.com/APIParkLab/APIPark/service/universally/commit"
"time"
+ "github.com/APIParkLab/APIPark/service/universally/commit"
+
"github.com/eolinker/go-common/utils"
"gorm.io/gorm"
diff --git a/service/service-doc/service.go b/service/service-doc/service.go
index 109bae1f..71ff1cc0 100644
--- a/service/service-doc/service.go
+++ b/service/service-doc/service.go
@@ -2,9 +2,10 @@ package service_doc
import (
"context"
- "github.com/APIParkLab/APIPark/service/universally/commit"
"reflect"
+ "github.com/APIParkLab/APIPark/service/universally/commit"
+
"github.com/eolinker/go-common/autowire"
)
diff --git a/service/service-model-mapping/iml.go b/service/service-model-mapping/iml.go
new file mode 100644
index 00000000..69b7ed5e
--- /dev/null
+++ b/service/service-model-mapping/iml.go
@@ -0,0 +1,67 @@
+package service_model_mapping
+
+import (
+ "context"
+ "errors"
+ "time"
+
+ "github.com/APIParkLab/APIPark/stores/service"
+ "github.com/eolinker/go-common/utils"
+ "gorm.io/gorm"
+)
+
+var _ IServiceModelMappingService = (*imlServiceModelMappingService)(nil)
+
+type imlServiceModelMappingService struct {
+ store service.IServiceModelMappingStore `autowired:""`
+}
+
+func (i *imlServiceModelMappingService) Get(ctx context.Context, sid string) (*ModelMapping, error) {
+ entity, err := i.store.First(ctx, map[string]interface{}{"sid": sid})
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return &ModelMapping{
+ Sid: sid,
+ Content: "",
+ }, nil
+ }
+ return nil, err
+ }
+ return FromEntity(entity), nil
+}
+
+func FromEntity(e *service.ModelMapping) *ModelMapping {
+ content := ""
+ if e.Content != "" {
+ content = e.Content
+ }
+ return &ModelMapping{
+ ID: e.Id,
+ Sid: e.Sid,
+ Content: content,
+ CreateAt: e.CreateAt,
+ UpdateAt: e.UpdateAt,
+ }
+}
+
+func (i *imlServiceModelMappingService) Save(ctx context.Context, input *Save) error {
+ info, err := i.store.First(ctx, map[string]interface{}{"sid": input.Sid})
+ if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+ return err
+ }
+ userID := utils.UserId(ctx)
+ if info != nil {
+ info.Content = input.Content
+ info.Updater = userID
+ info.UpdateAt = time.Now()
+ return i.store.Save(ctx, info)
+ }
+ return i.store.Insert(ctx, &service.ModelMapping{
+ Sid: input.Sid,
+ Content: input.Content,
+ CreateAt: time.Now(),
+ UpdateAt: time.Now(),
+ Creator: userID,
+ Updater: userID,
+ })
+}
diff --git a/service/service-model-mapping/model.go b/service/service-model-mapping/model.go
new file mode 100644
index 00000000..66dec9e4
--- /dev/null
+++ b/service/service-model-mapping/model.go
@@ -0,0 +1,20 @@
+package service_model_mapping
+
+import (
+ "time"
+)
+
+type ModelMapping struct {
+ ID int64 `json:"id"`
+ Sid string `json:"sid"`
+ Content string `json:"content"`
+ Creator string `json:"creator"`
+ Updater string `json:"updater"`
+ CreateAt time.Time `json:"create_at"`
+ UpdateAt time.Time `json:"update_at"`
+}
+
+type Save struct {
+ Sid string `json:"sid" validate:"required"`
+ Content string `json:"content" validate:"required"`
+}
diff --git a/service/service-model-mapping/service.go b/service/service-model-mapping/service.go
new file mode 100644
index 00000000..533614ce
--- /dev/null
+++ b/service/service-model-mapping/service.go
@@ -0,0 +1,19 @@
+package service_model_mapping
+
+import (
+ "context"
+ "reflect"
+
+ "github.com/eolinker/go-common/autowire"
+)
+
+type IServiceModelMappingService interface {
+ Get(ctx context.Context, sid string) (*ModelMapping, error)
+ Save(ctx context.Context, input *Save) error
+}
+
+func init() {
+ autowire.Auto[IServiceModelMappingService](func() reflect.Value {
+ return reflect.ValueOf(new(imlServiceModelMappingService))
+ })
+}
diff --git a/service/service/iml.go b/service/service/iml.go
index 47f015fd..8e42fea6 100644
--- a/service/service/iml.go
+++ b/service/service/iml.go
@@ -14,9 +14,7 @@ import (
"github.com/APIParkLab/APIPark/stores/service"
)
-var (
- _ IServiceService = (*imlServiceService)(nil)
-)
+var _ IServiceService = (*imlServiceService)(nil)
type imlServiceService struct {
store service.IServiceStore `autowired:""`
@@ -154,9 +152,11 @@ func (i *imlServiceService) OnComplete() {
func labelHandler(e *service.Service) []string {
return []string{e.Name, e.UUID, e.Description}
}
+
func uniquestHandler(i *Create) []map[string]interface{} {
return []map[string]interface{}{{"uuid": i.Id}}
}
+
func createEntityHandler(i *Create) *service.Service {
cfg, _ := json.Marshal(i.AdditionalConfig)
now := time.Now()
diff --git a/service/universally/delete.go b/service/universally/delete.go
index 565237a9..2677278e 100644
--- a/service/universally/delete.go
+++ b/service/universally/delete.go
@@ -4,15 +4,14 @@ import (
"context"
"errors"
"fmt"
+
"github.com/eolinker/go-common/auto"
"github.com/eolinker/go-common/store"
"github.com/eolinker/go-common/utils"
"gorm.io/gorm"
)
-var (
- _ IServiceDelete = (*imlServiceDelete[any])(nil)
-)
+var _ IServiceDelete = (*imlServiceDelete[any])(nil)
type IServiceDelete interface {
Delete(ctx context.Context, uuid string) error
@@ -26,10 +25,12 @@ func NewDelete[E any](store store.ISearchStore[E]) IServiceDelete {
assert(new(E))
return &imlServiceDelete[E]{store: store}
}
+
func NewSoftDelete[E any](s store.ISearchStore[E]) IServiceDelete {
assert(new(E))
return &imlServiceSoftDelete[E]{store: s}
}
+
func (p *imlServiceDelete[E]) Delete(ctx context.Context, uuid string) error {
return p.store.Transaction(ctx, func(ctx context.Context) error {
o, err := p.store.First(ctx, map[string]interface{}{"uuid": uuid})
@@ -46,7 +47,6 @@ func (p *imlServiceDelete[E]) Delete(ctx context.Context, uuid string) error {
}
return p.store.SetLabels(ctx, idValue(o))
})
-
}
type imlServiceSoftDelete[E any] struct {
@@ -66,7 +66,5 @@ func (p *imlServiceSoftDelete[E]) Delete(ctx context.Context, uuid string) error
auto.Auto("operator", operator, o)
return p.store.SoftDelete(ctx, map[string]interface{}{"uuid": uuid})
-
})
-
}
diff --git a/stores/service/model.go b/stores/service/model.go
index d0d42d30..3e205ace 100644
--- a/stores/service/model.go
+++ b/stores/service/model.go
@@ -1,6 +1,8 @@
package service
-import "time"
+import (
+ "time"
+)
type Service struct {
Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:id;primary_key;comment:主键ID;"`
@@ -27,6 +29,7 @@ type Service struct {
func (p *Service) IdValue() int64 {
return p.Id
}
+
func (p *Service) TableName() string {
return "service"
}
@@ -87,3 +90,21 @@ func (d *Doc) IdValue() int64 {
func (d *Doc) TableName() string {
return "server_doc"
}
+
+type ModelMapping struct {
+ Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:PRIMARY ID;primary_key"`
+ Sid string `gorm:"size:36;not null;column:sid;comment:service uuid;uniqueIndex:unique_sid;"`
+ Content string `gorm:"type:text;not null;column:content;comment:mapping json"`
+ Creator string `gorm:"type:varchar(36);not null;column:creator;comment:creator" aovalue:"creator"`
+ Updater string `gorm:"type:varchar(36);not null;column:updater;comment:updater" aovalue:"updater"`
+ CreateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:create_at;comment:create_at"`
+ UpdateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;column:update_at;comment:update_at"`
+}
+
+func (m *ModelMapping) TableName() string {
+ return "service_model_mapping"
+}
+
+func (m *ModelMapping) IdValue() int64 {
+ return m.Id
+}
diff --git a/stores/service/store.go b/stores/service/store.go
index 8c24fc15..702a358c 100644
--- a/stores/service/store.go
+++ b/stores/service/store.go
@@ -1,10 +1,11 @@
package service
import (
+ "reflect"
+
"github.com/eolinker/go-common/autowire"
"github.com/eolinker/go-common/store"
)
-import "reflect"
type IServiceStore interface {
store.ISearchStore[Service]
@@ -37,6 +38,14 @@ type imlAuthorizationStore struct {
store.SearchStore[Authorization]
}
+type IServiceModelMappingStore interface {
+ store.ISearchStore[ModelMapping]
+}
+
+type imlServiceModelMappingStore struct {
+ store.SearchStore[ModelMapping]
+}
+
func init() {
autowire.Auto[IServiceStore](func() reflect.Value {
return reflect.ValueOf(new(imlServiceStore))
@@ -52,4 +61,7 @@ func init() {
return reflect.ValueOf(new(imlServiceDocStore))
})
+ autowire.Auto[IServiceModelMappingStore](func() reflect.Value {
+ return reflect.ValueOf(new(imlServiceModelMappingStore))
+ })
}