Download controller/model.go from Jack698/velo: direct link, hf CLI and curl.
- Browser
- Download file 13 kB
-
https://huggingface.co/spaces/Jack698/velo/resolve/main/controller/model.go
- Command line
-
hf download hf://spaces/Jack698/velo/controller/model.go
-
curl -L -o model.go https://huggingface.co/spaces/Jack698/velo/resolve/main/controller/model.go
13 kB
| // Copyright (c) 2025 Tethys Plex | |
| // | |
| // This file is part of Veloera. | |
| // | |
| // This program is free software: you can redistribute it and/or modify | |
| // it under the terms of the GNU General Public License as published by | |
| // the Free Software Foundation, either version 3 of the License, or | |
| // (at your option) any later version. | |
| // | |
| // This program is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // GNU General Public License for more details. | |
| // | |
| // You should have received a copy of the GNU General Public License | |
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | |
| package controller | |
| import ( | |
| "fmt" | |
| "github.com/gin-gonic/gin" | |
| "net/http" | |
| "strings" | |
| "veloera/common" | |
| "veloera/constant" | |
| "veloera/dto" | |
| "veloera/middleware" | |
| "veloera/model" | |
| "veloera/relay" | |
| "veloera/relay/channel/ai360" | |
| "veloera/relay/channel/lingyiwanwu" | |
| "veloera/relay/channel/minimax" | |
| "veloera/relay/channel/moonshot" | |
| relaycommon "veloera/relay/common" | |
| relayconstant "veloera/relay/constant" | |
| ) | |
| // https://platform.openai.com/docs/api-reference/models/list | |
| var openAIModels []dto.OpenAIModels | |
| var openAIModelsMap map[string]dto.OpenAIModels | |
| var channelId2Models map[int][]string | |
| func getPermission() []dto.OpenAIModelPermission { | |
| var permission []dto.OpenAIModelPermission | |
| permission = append(permission, dto.OpenAIModelPermission{ | |
| Id: "modelperm-LwHkVFn8AcMItP432fKKDIKJ", | |
| Object: "model_permission", | |
| Created: 1626777600, | |
| AllowCreateEngine: true, | |
| AllowSampling: true, | |
| AllowLogprobs: true, | |
| AllowSearchIndices: false, | |
| AllowView: true, | |
| AllowFineTuning: false, | |
| Organization: "*", | |
| Group: nil, | |
| IsBlocking: false, | |
| }) | |
| return permission | |
| } | |
| func init() { | |
| // https://platform.openai.com/docs/models/model-endpoint-compatibility | |
| permission := getPermission() | |
| for i := 0; i < relayconstant.APITypeDummy; i++ { | |
| if i == relayconstant.APITypeAIProxyLibrary { | |
| continue | |
| } | |
| adaptor := relay.GetAdaptor(i) | |
| channelName := adaptor.GetChannelName() | |
| modelNames := adaptor.GetModelList() | |
| for _, modelName := range modelNames { | |
| openAIModels = append(openAIModels, dto.OpenAIModels{ | |
| Id: modelName, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: channelName, | |
| Permission: permission, | |
| Root: modelName, | |
| Parent: nil, | |
| }) | |
| } | |
| } | |
| for _, modelName := range ai360.ModelList { | |
| openAIModels = append(openAIModels, dto.OpenAIModels{ | |
| Id: modelName, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: ai360.ChannelName, | |
| Permission: permission, | |
| Root: modelName, | |
| Parent: nil, | |
| }) | |
| } | |
| for _, modelName := range moonshot.ModelList { | |
| openAIModels = append(openAIModels, dto.OpenAIModels{ | |
| Id: modelName, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: moonshot.ChannelName, | |
| Permission: permission, | |
| Root: modelName, | |
| Parent: nil, | |
| }) | |
| } | |
| for _, modelName := range lingyiwanwu.ModelList { | |
| openAIModels = append(openAIModels, dto.OpenAIModels{ | |
| Id: modelName, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: lingyiwanwu.ChannelName, | |
| Permission: permission, | |
| Root: modelName, | |
| Parent: nil, | |
| }) | |
| } | |
| for _, modelName := range minimax.ModelList { | |
| openAIModels = append(openAIModels, dto.OpenAIModels{ | |
| Id: modelName, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: minimax.ChannelName, | |
| Permission: permission, | |
| Root: modelName, | |
| Parent: nil, | |
| }) | |
| } | |
| for modelName := range constant.MidjourneyModel2Action { | |
| openAIModels = append(openAIModels, dto.OpenAIModels{ | |
| Id: modelName, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: "midjourney", | |
| Permission: permission, | |
| Root: modelName, | |
| Parent: nil, | |
| }) | |
| } | |
| openAIModelsMap = make(map[string]dto.OpenAIModels) | |
| for _, aiModel := range openAIModels { | |
| openAIModelsMap[aiModel.Id] = aiModel | |
| } | |
| channelId2Models = make(map[int][]string) | |
| for i := 1; i <= common.ChannelTypeDummy; i++ { | |
| apiType, success := relayconstant.ChannelType2APIType(i) | |
| if !success || apiType == relayconstant.APITypeAIProxyLibrary { | |
| continue | |
| } | |
| meta := &relaycommon.RelayInfo{ChannelType: i} | |
| adaptor := relay.GetAdaptor(apiType) | |
| adaptor.Init(meta) | |
| channelId2Models[i] = adaptor.GetModelList() | |
| } | |
| } | |
| func ListModels(c *gin.Context) { | |
| userOpenAiModels := make([]dto.OpenAIModels, 0) | |
| permission := getPermission() | |
| modelPrefixMap := make(map[string][]string) // Map to store all prefixed versions for each model | |
| // Get the user group to look up available channels | |
| userId := c.GetInt("id") | |
| userGroup, err := model.GetUserGroup(userId, true) | |
| if err != nil { | |
| c.JSON(http.StatusOK, gin.H{ | |
| "success": false, | |
| "message": "get user group failed", | |
| }) | |
| return | |
| } | |
| group := userGroup | |
| tokenGroup := c.GetString("token_group") | |
| if tokenGroup != "" { | |
| group = tokenGroup | |
| } | |
| // Get channels with prefixes | |
| prefixChannels := middleware.GetPrefixChannels(group) | |
| for prefix, channels := range prefixChannels { | |
| if prefix == "" { | |
| continue // Skip channels without prefixes | |
| } | |
| // For each channel with a prefix, add its models to the prefix map | |
| for _, channel := range channels { | |
| for _, modelName := range channel.GetModels() { | |
| if modelPrefixMap[modelName] == nil { | |
| modelPrefixMap[modelName] = make([]string, 0) | |
| } | |
| prefixedModel := prefix + modelName | |
| // Check if this prefixed model already exists to avoid duplicates | |
| exists := false | |
| for _, existing := range modelPrefixMap[modelName] { | |
| if existing == prefixedModel { | |
| exists = true | |
| break | |
| } | |
| } | |
| if !exists { | |
| modelPrefixMap[modelName] = append(modelPrefixMap[modelName], prefixedModel) | |
| } | |
| } | |
| } | |
| } | |
| modelLimitEnable := c.GetBool("token_model_limit_enabled") | |
| if modelLimitEnable { | |
| s, ok := c.Get("token_model_limit") | |
| var tokenModelLimit map[string]bool | |
| if ok { | |
| tokenModelLimit = s.(map[string]bool) | |
| } else { | |
| tokenModelLimit = map[string]bool{} | |
| } | |
| for allowModel := range tokenModelLimit { | |
| // Check if this model has prefix mappings | |
| prefixedModels := modelPrefixMap[allowModel] | |
| // Add base model first | |
| if _, ok := openAIModelsMap[allowModel]; ok { | |
| modelInfo := openAIModelsMap[allowModel] | |
| userOpenAiModels = append(userOpenAiModels, modelInfo) | |
| } else { | |
| userOpenAiModels = append(userOpenAiModels, dto.OpenAIModels{ | |
| Id: allowModel, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: "custom", | |
| Permission: permission, | |
| Root: allowModel, | |
| Parent: nil, | |
| }) | |
| } | |
| // Add all prefixed versions | |
| for _, prefixedModel := range prefixedModels { | |
| if _, ok := openAIModelsMap[allowModel]; ok { | |
| modelInfo := openAIModelsMap[allowModel] | |
| // Create a copy and replace ID with prefixed model | |
| prefixedModelInfo := modelInfo | |
| prefixedModelInfo.Id = prefixedModel | |
| userOpenAiModels = append(userOpenAiModels, prefixedModelInfo) | |
| } else { | |
| userOpenAiModels = append(userOpenAiModels, dto.OpenAIModels{ | |
| Id: prefixedModel, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: "custom", | |
| Permission: permission, | |
| Root: allowModel, // Keep the original model name as root | |
| Parent: nil, | |
| }) | |
| } | |
| } | |
| } | |
| } else { // modelLimitEnable is false | |
| models := model.GetGroupModels(group) // Models available to the user's group | |
| processedModels := make(map[string]bool) // Tracks models already added to userOpenAiModels to prevent duplicates | |
| // First, add all models from channels with prefixes | |
| for baseModel, prefixedModelNameVersions := range modelPrefixMap { | |
| isBaseModelAllowed := false | |
| for _, groupModel := range models { | |
| if groupModel == baseModel { | |
| isBaseModelAllowed = true | |
| break | |
| } | |
| } | |
| if isBaseModelAllowed { | |
| for _, prefixedModelName := range prefixedModelNameVersions { | |
| if processedModels[prefixedModelName] { | |
| continue // Skip if this specific prefixed model was already added | |
| } | |
| // Construct and add the prefixed model to userOpenAiModels | |
| if modelData, ok := openAIModelsMap[baseModel]; ok { // Use baseModel for template | |
| modelInfo := modelData // Make a copy to modify | |
| modelInfo.Id = prefixedModelName | |
| modelInfo.Root = baseModel // Ensure Root is the base model | |
| userOpenAiModels = append(userOpenAiModels, modelInfo) | |
| } else { | |
| userOpenAiModels = append(userOpenAiModels, dto.OpenAIModels{ | |
| Id: prefixedModelName, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: "custom", // Or derive from channel if possible | |
| Permission: permission, | |
| Root: baseModel, | |
| Parent: nil, | |
| }) | |
| } | |
| processedModels[prefixedModelName] = true | |
| } | |
| } | |
| } | |
| // Second, add all models available to the group (including non-prefixed ones) | |
| // that haven't been added yet and don't have prefixed versions already added. | |
| for _, modelName := range models { | |
| if processedModels[modelName] { | |
| continue // Skip if this model (prefixed or non-prefixed) was already added | |
| } | |
| // Check if this model has prefixed versions that were already added | |
| hasProcessedPrefixedVersion := false | |
| if prefixedVersions, exists := modelPrefixMap[modelName]; exists { | |
| for _, prefixedVersion := range prefixedVersions { | |
| if processedModels[prefixedVersion] { | |
| hasProcessedPrefixedVersion = true | |
| break | |
| } | |
| } | |
| } | |
| // Only add the non-prefixed model if no prefixed version was added | |
| if !hasProcessedPrefixedVersion { | |
| // Construct and add the non-prefixed model to userOpenAiModels | |
| if modelData, ok := openAIModelsMap[modelName]; ok { | |
| userOpenAiModels = append(userOpenAiModels, modelData) | |
| } else { | |
| userOpenAiModels = append(userOpenAiModels, dto.OpenAIModels{ | |
| Id: modelName, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: "custom", // Or derive from channel if possible | |
| Permission: permission, | |
| Root: modelName, | |
| Parent: nil, | |
| }) | |
| } | |
| processedModels[modelName] = true | |
| } | |
| } | |
| } | |
| // 添加虚拟模型到返回列表中 | |
| virtualModels := model.GetAllVirtualModels() | |
| for _, virtualModel := range virtualModels { | |
| // 检查是否已经存在该虚拟模型,避免重复添加 | |
| exists := false | |
| for _, existingModel := range userOpenAiModels { | |
| if existingModel.Id == virtualModel { | |
| exists = true | |
| break | |
| } | |
| } | |
| if !exists { | |
| // 检查是否有对应的实际模型信息,如果有则使用 | |
| if modelData, ok := openAIModelsMap[virtualModel]; ok { | |
| userOpenAiModels = append(userOpenAiModels, modelData) | |
| } else { | |
| // 创建虚拟模型的 OpenAI 格式信息 | |
| userOpenAiModels = append(userOpenAiModels, dto.OpenAIModels{ | |
| Id: virtualModel, | |
| Object: "model", | |
| Created: 1626777600, | |
| OwnedBy: "virtual", | |
| Permission: permission, | |
| Root: virtualModel, | |
| Parent: nil, | |
| }) | |
| } | |
| } | |
| } | |
| c.JSON(200, gin.H{ | |
| "success": true, | |
| "data": userOpenAiModels, | |
| }) | |
| } | |
| func ChannelListModels(c *gin.Context) { | |
| c.JSON(200, gin.H{ | |
| "success": true, | |
| "data": openAIModels, | |
| }) | |
| } | |
| func DashboardListModels(c *gin.Context) { | |
| c.JSON(200, gin.H{ | |
| "success": true, | |
| "data": channelId2Models, | |
| }) | |
| } | |
| func EnabledListModels(c *gin.Context) { | |
| c.JSON(200, gin.H{ | |
| "success": true, | |
| "data": model.GetEnabledModels(), | |
| }) | |
| } | |
| func RetrieveModel(c *gin.Context) { | |
| modelId := c.Param("model") | |
| // Check if the model ID has a prefix | |
| userId := c.GetInt("id") | |
| userGroup, err := model.GetUserGroup(userId, true) | |
| if err == nil { | |
| group := userGroup | |
| tokenGroup := c.GetString("token_group") | |
| if tokenGroup != "" { | |
| group = tokenGroup | |
| } | |
| prefixChannels := middleware.GetPrefixChannels(group) | |
| for prefix := range prefixChannels { | |
| if prefix != "" && strings.HasPrefix(modelId, prefix) { | |
| // We found a model with a prefix, try to retrieve the base model | |
| baseModelId := strings.TrimPrefix(modelId, prefix) | |
| if aiModel, ok := openAIModelsMap[baseModelId]; ok { | |
| modelCopy := aiModel | |
| modelCopy.Id = modelId // Use the prefixed model ID | |
| c.JSON(200, modelCopy) | |
| return | |
| } | |
| } | |
| } | |
| } | |
| // No prefix found or base model doesn't exist, try the original model ID | |
| if aiModel, ok := openAIModelsMap[modelId]; ok { | |
| c.JSON(200, aiModel) | |
| } else { | |
| openAIError := dto.OpenAIError{ | |
| Message: fmt.Sprintf("The model '%s' does not exist", modelId), | |
| Type: "invalid_request_error", | |
| Param: "model", | |
| Code: "model_not_found", | |
| } | |
| c.JSON(200, gin.H{ | |
| "error": openAIError, | |
| }) | |
| } | |
| } |