Merge pull request #239 from APIParkLab/feature/sunanzhi/1.6

refactor: adjust character limit for custom provider/model name
This commit is contained in:
sunanzhi
2025-03-11 15:23:12 +08:00
committed by GitHub
10 changed files with 58 additions and 32 deletions
+9
View File
@@ -25,6 +25,8 @@ const (
CIDRIpv4Exp = `^(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([1-9]|[1-2]\d|3[0-2]))?$`
// CheckPathIPPortExp (scheme://)?ip:port
CheckPathIPPortExp = `([a-zA-z]+://)?((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}:[0-9]+`
// EnglishOrNumberOrSpecialChars a-zA-Z0-9-_.:
EnglishOrNumberOrSpecialChars = `^(?i)[-:._a-z0-9]+$`
)
var (
@@ -47,6 +49,8 @@ var (
restfulPathMatchRegexp = regexp.MustCompile(`({[0-9a-zA-Z-_]+})+`)
//restfulParamMatchRegexp 匹配restful参数 {xxx}
restfulParamMatchRegexp = regexp.MustCompile(`^{[0-9a-zA-Z-_]+}$`)
// modelNameRegexp match model name
modelNameRegexp = regexp.MustCompile(EnglishOrNumberOrSpecialChars)
)
func IsMatchString(regexpPattern RegexpPattern, s string) error {
@@ -129,3 +133,8 @@ func ReplaceRestfulPath(path, replaceStr string) string {
func CheckPathContainsIPPort(path string) bool {
return checkIPPortRegexp.MatchString(path)
}
// ModelNameValid check model name is valid
func ModelNameValid(param string) bool {
return modelNameRegexp.MatchString(param)
}
+5 -4
View File
@@ -3,6 +3,7 @@ package ai_model
import (
"encoding/json"
"fmt"
"github.com/APIParkLab/APIPark/common"
ai_model "github.com/APIParkLab/APIPark/module/ai-model"
model_dto "github.com/APIParkLab/APIPark/module/ai-model/dto"
"github.com/gin-gonic/gin"
@@ -22,8 +23,8 @@ func (i *imlProviderModelController) GetModelParametersTemplate(ctx *gin.Context
}
func (i *imlProviderModelController) UpdateProviderModel(ctx *gin.Context, provider string, input *model_dto.EditModel) error {
if strings.TrimSpace(input.Name) == "" {
return fmt.Errorf("name is empty")
if !common.ModelNameValid(input.Name) {
return fmt.Errorf("model name is invalid(a-zA-Z0-9-_.:)")
}
if strings.TrimSpace(input.Id) == "" {
return fmt.Errorf("id is empty")
@@ -54,8 +55,8 @@ func (i *imlProviderModelController) DeleteProviderModel(ctx *gin.Context, provi
}
func (i *imlProviderModelController) AddProviderModel(ctx *gin.Context, provider string, input *model_dto.Model) (*model_dto.SimpleModel, error) {
if strings.TrimSpace(input.Name) == "" {
return nil, fmt.Errorf("name is empty")
if !common.ModelNameValid(input.Name) {
return nil, fmt.Errorf("model name illegal(a-zA-Z0-9-_.:)")
}
if strings.TrimSpace(provider) == "" {
return nil, fmt.Errorf("provider is empty")
+3 -2
View File
@@ -3,6 +3,7 @@ package ai
import (
"encoding/json"
"fmt"
"github.com/APIParkLab/APIPark/common"
"strconv"
"strings"
@@ -24,8 +25,8 @@ func (i *imlProviderController) Delete(ctx *gin.Context, id string) error {
}
func (i *imlProviderController) AddProvider(ctx *gin.Context, input *ai_dto.NewProvider) (*ai_dto.SimpleProvider, error) {
if strings.TrimSpace(input.Name) == "" {
return nil, fmt.Errorf("name is empty")
if !common.ModelNameValid(input.Name) {
return nil, fmt.Errorf("name illegal(a-zA-Z0-9-_.:)")
}
return i.module.AddProvider(ctx, input)
}
+1
View File
@@ -25,6 +25,7 @@ type AiPromptVariable struct {
type AiModel struct {
Id string `json:"id"`
Name string `json:"name"`
Config string `json:"config"`
Provider string `json:"provider"`
Type string `json:"type"`
+1
View File
@@ -66,6 +66,7 @@ type APIItem struct {
type ModelItem struct {
Id string `json:"id"`
Name string `json:"name"`
Logo string `json:"logo"`
}
+21 -9
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
ai_model "github.com/APIParkLab/APIPark/service/ai-model"
"net/http"
"strings"
@@ -32,11 +33,12 @@ var (
)
type imlAPIModule struct {
serviceService service.IServiceService `autowired:""`
apiDocService api_doc.IAPIDocService `autowired:""`
aiAPIService ai_api.IAPIService `autowired:""`
apiService api.IAPIService `autowired:""`
transaction store.ITransaction `autowired:""`
serviceService service.IServiceService `autowired:""`
apiDocService api_doc.IAPIDocService `autowired:""`
aiAPIService ai_api.IAPIService `autowired:""`
aiModelService ai_model.IProviderModelService `autowired:""`
apiService api.IAPIService `autowired:""`
transaction store.ITransaction `autowired:""`
}
func (i *imlAPIModule) getAPIDoc(ctx context.Context, serviceId string) (*openapi3.T, error) {
@@ -242,19 +244,20 @@ func (i *imlAPIModule) List(ctx context.Context, keyword string, serviceId strin
item.Provider = ai_api_dto.ProviderItem{
Id: p.ID(),
Name: p.Name(),
Logo: p.Logo(),
Logo: "",
}
m, has := p.GetModel(t.Model)
if has {
item.Model = ai_api_dto.ModelItem{
Id: m.ID(),
Logo: m.Logo(),
Name: m.Name(),
Logo: "",
}
}
} else {
item.Model = ai_api_dto.ModelItem{
Id: aiModel.Id,
Id: aiModel.Id,
Name: "unknown",
}
}
return item
@@ -281,6 +284,15 @@ func (i *imlAPIModule) Get(ctx context.Context, serviceId string, apiId string)
if err != nil {
return nil, err
}
if aiModel.Name == "" {
// get provider model
modelInfo, _ := i.aiModelService.Get(ctx, aiModel.Id)
if modelInfo != nil {
aiModel.Name = modelInfo.Name
} else {
aiModel.Name = aiModel.Id
}
}
return &ai_api_dto.API{
Id: apiInfo.ID,
+7 -8
View File
@@ -5,6 +5,7 @@ import (
model_runtime "github.com/APIParkLab/APIPark/ai-provider/model-runtime"
model_dto "github.com/APIParkLab/APIPark/module/ai-model/dto"
"github.com/APIParkLab/APIPark/service/ai"
ai_api "github.com/APIParkLab/APIPark/service/ai-api"
ai_model "github.com/APIParkLab/APIPark/service/ai-model"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
@@ -19,6 +20,7 @@ var (
type imlProviderModelModule struct {
providerService ai.IProviderService `autowired:""`
aiApiService ai_api.IAPIService `autowired:""`
providerModelService ai_model.IProviderModelService `autowired:""`
transaction store.ITransaction `autowired:""`
}
@@ -91,6 +93,11 @@ func (i *imlProviderModelModule) DeleteProviderModel(ctx *gin.Context, provider
if modelInfo == nil || modelInfo.Provider != provider {
return fmt.Errorf("model not found")
}
// check model in use
countMapByModel, _ := i.aiApiService.CountMapByModel(ctx, "", map[string]interface{}{"model": id})
if countValue, has := countMapByModel[id]; has && countValue > 0 {
return fmt.Errorf("model in use")
}
if err := i.providerModelService.Delete(ctx, id); err != nil {
return err
}
@@ -104,14 +111,6 @@ func (i *imlProviderModelModule) AddProviderModel(ctx *gin.Context, provider str
if !has {
return nil, fmt.Errorf("ai provider not found")
}
// check provider exist
providerInfo, err := i.providerService.Get(ctx, provider)
if err != nil {
return nil, err
}
if providerInfo == nil {
return nil, fmt.Errorf("provider not found")
}
// check model name duplicate
if has := i.providerModelService.CheckNameDuplicate(ctx, provider, input.Name, ""); has {
return nil, fmt.Errorf("model name: `%s` duplicate", input.Name)
+8 -6
View File
@@ -198,13 +198,13 @@ func (i *imlProviderModule) Delete(ctx context.Context, id string) error {
}
func (i *imlProviderModule) AddProvider(ctx context.Context, input *ai_dto.NewProvider) (*ai_dto.SimpleProvider, error) {
if has := i.providerService.CheckNameDuplicate(ctx, input.Name); has {
// uuid = name
if has := i.providerService.CheckUuidDuplicate(ctx, input.Name); has {
return nil, fmt.Errorf("provider `%s` duplicate", input.Name)
}
id := uuid.New().String()
config, defaultLLM := "{\"base_url\": \"\", \"api_key\": \"\"}", ""
if err := i.providerService.Create(ctx, &ai.CreateProvider{
Id: id,
Id: input.Name,
Name: input.Name,
DefaultLLM: defaultLLM,
Config: config,
@@ -213,10 +213,10 @@ func (i *imlProviderModule) AddProvider(ctx context.Context, input *ai_dto.NewPr
return nil, err
}
// register provider
iProvider, _ := model_runtime.NewCustomizeProvider(id, input.Name, []model_runtime.IModel{}, "", "")
model_runtime.Register(id, iProvider)
iProvider, _ := model_runtime.NewCustomizeProvider(input.Name, input.Name, []model_runtime.IModel{}, "", "")
model_runtime.Register(input.Name, iProvider)
return &ai_dto.SimpleProvider{
Id: id,
Id: input.Name,
Name: input.Name,
DefaultConfig: config,
Logo: model_runtime.GetCustomizeLogo(),
@@ -482,6 +482,8 @@ func (i *imlProviderModule) Provider(ctx context.Context, id string) (*ai_dto.Pr
model, has := p.DefaultModel(model_runtime.ModelTypeLLM)
if !has || model == nil {
defaultLLM, _ = model_runtime.NewCustomizeModel("", "", "", "", "")
} else {
defaultLLM = model
}
}
+2 -2
View File
@@ -70,8 +70,8 @@ type imlProviderService struct {
// return i.store.Save(ctx, info)
//}
func (i *imlProviderService) CheckNameDuplicate(ctx context.Context, name string) bool {
v, _ := i.store.First(ctx, map[string]interface{}{"name": name})
func (i *imlProviderService) CheckUuidDuplicate(ctx context.Context, uuid string) bool {
v, _ := i.store.First(ctx, map[string]interface{}{"uuid": uuid})
return v != nil
}
+1 -1
View File
@@ -15,7 +15,7 @@ type IProviderService interface {
universally.IServiceDelete
//Save(ctx context.Context, id string, cfg *SetProvider) error
//MaxPriority(ctx context.Context) (int, error)
CheckNameDuplicate(ctx context.Context, name string) bool
CheckUuidDuplicate(ctx context.Context, uuid string) bool
}
func init() {