From 2667995b257691c6e33ca2f84c06c2de19cbf18f Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Fri, 26 Jun 2026 15:36:01 +0800 Subject: [PATCH] Go CLI: Fix show model and list models (#16380) ### What problem does this PR solve? ``` RAGFlow(api/default)> show model 'WiseDiag-Z1 Think'; RAGFlow(api/default)> list models; RAGFlow(admin)> show model 'WiseDiag-Z1 Think'; RAGFlow(admin)> list models; ``` ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) Signed-off-by: Jin Hai --- internal/admin/enterprise_handler.go | 42 ---------- internal/admin/enterprise_service.go | 18 ---- internal/admin/handler.go | 57 +++++++++++++ internal/admin/service.go | 17 ++++ internal/cli/cli_http.go | 8 +- internal/cli/common_command.go | 2 +- internal/cli/user_parser.go | 30 ++----- internal/handler/models.go | 118 ++++++++++++++++----------- internal/router/router.go | 1 + 9 files changed, 154 insertions(+), 139 deletions(-) diff --git a/internal/admin/enterprise_handler.go b/internal/admin/enterprise_handler.go index 5e9b8b7b74..3209c2f02b 100644 --- a/internal/admin/enterprise_handler.go +++ b/internal/admin/enterprise_handler.go @@ -876,48 +876,6 @@ func (h *Handler) DeleteModels(c *gin.Context) { success(c, result, "Model deleted successfully") } -func (h *Handler) ListAllModels(c *gin.Context) { - // List models - models, err := h.service.ListAllModels() - if err != nil { - errorResponse(c, err.Error(), 500) - return - } - - success(c, models, "") -} - -func (h *Handler) ShowModel(c *gin.Context) { - encodedModelName := c.Param("model_name") - if encodedModelName == "" { - c.JSON(http.StatusBadRequest, gin.H{ - "code": 400, - "message": "Encoded model name is empty", - }) - return - } - - decodedModelName, err := common.DecodeFromBase64(encodedModelName) - if err != nil { - errorResponse(c, err.Error(), 400) - return - } - if decodedModelName == "" { - errorResponse(c, "Decoded model name is empty", 400) - return - } - - // Get model - model, err := h.service.GetModelByModelName(decodedModelName) - if err != nil { - errorResponse(c, err.Error(), 500) - return - } - - success(c, model, "") - -} - // GetSystemFingerprint handle get system fingerprint func (h *Handler) GetSystemFingerprint(c *gin.Context) { fingerprint, err := h.service.GetSystemFingerprint() diff --git a/internal/admin/enterprise_service.go b/internal/admin/enterprise_service.go index 12897cd3e3..d2c6e71d7f 100644 --- a/internal/admin/enterprise_service.go +++ b/internal/admin/enterprise_service.go @@ -343,24 +343,6 @@ func (s *Service) DeleteModels(userID, providerName, instanceName string, models }, nil } -// ListAllModels list all models -func (s *Service) ListAllModels() ([]map[string]interface{}, error) { - return []map[string]interface{}{ - { - "command": "list_all_models", - "error": "'list all models' is implemented in enterprise edition", - }, - }, nil -} - -func (s *Service) GetModelByModelName(modelName string) (map[string]interface{}, error) { - return map[string]interface{}{ - "command": "get_model_by_model_name", - "model_name": modelName, - "error": "'get model by model name' is implemented in enterprise edition", - }, nil -} - func (s *Service) GetSystemFingerprint() (map[string]interface{}, error) { result := map[string]interface{}{ "command": "get_system_fingerprint", diff --git a/internal/admin/handler.go b/internal/admin/handler.go index 716db06aaf..9cfc65bd93 100644 --- a/internal/admin/handler.go +++ b/internal/admin/handler.go @@ -1294,3 +1294,60 @@ func (h *Handler) Reports(c *gin.Context) { responseWithCode(c, message, http.StatusOK, errCode) } + +func (h *Handler) ListAllModels(c *gin.Context) { + + page := 0 + if v := c.Query("page"); v != "" { + if p, err := strconv.Atoi(v); err == nil && p > 0 { + page = p + } + } + + pageSize := 0 + if v := c.Query("page_size"); v != "" { + if ps, err := strconv.Atoi(v); err == nil && ps > 0 { + pageSize = ps + } + } + + // List models + models, err := h.service.ListAllModels(page, pageSize) + if err != nil { + errorResponse(c, err.Error(), 500) + return + } + + success(c, models, "") +} + +func (h *Handler) ShowModel(c *gin.Context) { + encodedModelName := c.Param("model_name") + if encodedModelName == "" { + c.JSON(http.StatusBadRequest, gin.H{ + "code": 400, + "message": "Encoded model name is empty", + }) + return + } + + decodedModelName, err := common.DecodeFromBase64(encodedModelName) + if err != nil { + errorResponse(c, err.Error(), 400) + return + } + if decodedModelName == "" { + errorResponse(c, "Decoded model name is empty", 400) + return + } + + // Get model + model, err := h.service.GetModelByModelName(decodedModelName) + if err != nil { + errorResponse(c, err.Error(), 500) + return + } + + success(c, model, "") + +} diff --git a/internal/admin/service.go b/internal/admin/service.go index 3991f376f2..bd559e6393 100644 --- a/internal/admin/service.go +++ b/internal/admin/service.go @@ -31,6 +31,7 @@ import ( "ragflow/internal/engine/elasticsearch" "ragflow/internal/engine/redis" "ragflow/internal/entity" + modelModule "ragflow/internal/entity/models" "ragflow/internal/server" "ragflow/internal/utility" "regexp" @@ -1762,3 +1763,19 @@ func (s *Service) addTenantForAdmin(userID, nickname string) error { return dao.DB.Create(userTenant).Error } + +// ListAllModels list all models +func (s *Service) ListAllModels(pageIndex, pageSize int) ([]map[string]interface{}, error) { + models, err := dao.GetModelProviderManager().ListAllModels() + if err != nil { + return nil, err + } + if pageSize > 0 && pageIndex >= 0 && pageIndex*pageSize < len(models) { + return models[pageIndex*pageSize : (pageIndex+1)*pageSize], nil + } + return models, nil +} + +func (s *Service) GetModelByModelName(modelName string) (*modelModule.Model, error) { + return dao.GetModelProviderManager().GetModelByNameOrAlias(modelName), nil +} diff --git a/internal/cli/cli_http.go b/internal/cli/cli_http.go index c4689adcde..8c28a8be93 100644 --- a/internal/cli/cli_http.go +++ b/internal/cli/cli_http.go @@ -132,7 +132,7 @@ func (c *CLI) ExecuteAdminCommand(cmd *Command) (ResponseIf, error) { case "admin_list_provider_instances": return c.CommonListProviderInstances(cmd) case "admin_show_model": - return c.CommonShowModel(cmd) + return c.CommonShowModelCommand(cmd) case "admin_list_providers": return c.AdminListProvidersCommand(cmd) case "admin_list_all_models": @@ -358,10 +358,8 @@ func (c *CLI) ExecuteUserCommand(cmd *Command) (ResponseIf, error) { return c.CommonListInstanceModelsSyncCommand(cmd) case "api_list_provider_instance_tasks": return c.APIListModelInstanceTasksCommand(cmd) - case "show_provider_model": - return c.CommonShowProviderModelCommand(cmd) - case "show_model": - return c.CommonShowModel(cmd) + case "api_show_model": + return c.CommonShowModelCommand(cmd) case "list_all_models": return c.ListAllModels(cmd) // Provider commands diff --git a/internal/cli/common_command.go b/internal/cli/common_command.go index fd49e86bf3..ab18672f77 100644 --- a/internal/cli/common_command.go +++ b/internal/cli/common_command.go @@ -1432,7 +1432,7 @@ func (c *CLI) ListAllModels(cmd *Command) (ResponseIf, error) { return &result, nil } -func (c *CLI) CommonShowModel(cmd *Command) (ResponseIf, error) { +func (c *CLI) CommonShowModelCommand(cmd *Command) (ResponseIf, error) { modelName, ok := cmd.Params["model_name"].(string) if !ok { diff --git a/internal/cli/user_parser.go b/internal/cli/user_parser.go index f952969c06..db7dd6fd13 100644 --- a/internal/cli/user_parser.go +++ b/internal/cli/user_parser.go @@ -526,7 +526,7 @@ func (p *Parser) parseAPIShowCommands() (*Command, error) { case TokenProvider: return p.parseAPIShowProviderCommands() case TokenModel: - return p.parseShowModel() + return p.parseAPIShowModel() case TokenTask: return p.parseShowTask() case TokenQuotedString: @@ -590,8 +590,9 @@ func (p *Parser) parseAPIShowVariable() (*Command, error) { return cmd, nil } -func (p *Parser) parseShowModel() (*Command, error) { - p.nextToken() // consume model +// SHOW MODEL 'model_name' +func (p *Parser) parseAPIShowModel() (*Command, error) { + p.nextToken() // consume MODEL modelName, err := p.parseQuotedString() if err != nil { @@ -599,30 +600,11 @@ func (p *Parser) parseShowModel() (*Command, error) { } p.nextToken() // consume model_name - if p.curToken.Type != TokenFrom { - // SHOW MODEL 'model_name' - if p.curToken.Type == TokenSemicolon { - p.nextToken() - } - cmd := NewCommand("show_model") - cmd.Params["model_name"] = modelName - return cmd, nil - } - p.nextToken() // consume from - - cmd := NewCommand("show_provider_model") - cmd.Params["model_name"] = modelName - - providerName, err := p.parseQuotedString() - if err != nil { - return nil, fmt.Errorf("expected provider name: %w", err) - } - cmd.Params["provider_name"] = providerName - p.nextToken() // consume provider name - // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } + cmd := NewCommand("api_show_model") + cmd.Params["model_name"] = modelName return cmd, nil } diff --git a/internal/handler/models.go b/internal/handler/models.go index 19a47dd118..d37d0c70cc 100644 --- a/internal/handler/models.go +++ b/internal/handler/models.go @@ -20,6 +20,7 @@ import ( "net/http" "ragflow/internal/common" "ragflow/internal/service" + "strconv" "github.com/gin-gonic/gin" ) @@ -36,63 +37,82 @@ func NewModelHandler(modelProviderService *service.ModelProviderService) *ModelH } } -type ShowModelRequest struct { - ModelName *string `json:"model_name"` - Page int `json:"page"` - PageSize int `json:"page_size"` -} - func (h *ModelHandler) ListAllModels(c *gin.Context) { - var req ShowModelRequest - if err := c.ShouldBindJSON(&req); err != nil { - println("JSON bind error: %v (type: %T)", err, err) + page := 0 + if v := c.Query("page"); v != "" { + if p, err := strconv.Atoi(v); err == nil && p > 0 { + page = p + } + } + + pageSize := 0 + if v := c.Query("page_size"); v != "" { + if ps, err := strconv.Atoi(v); err == nil && ps > 0 { + pageSize = ps + } + } + + // list tenant models + models, err := h.modelProviderService.ListAllModels(page, pageSize) + if err != nil { c.JSON(http.StatusOK, gin.H{ - "code": common.CodeBadRequest, + "code": common.CodeDataError, "message": err.Error(), + "data": nil, }) return } - if req.ModelName == nil { - // list models - page := req.Page - pageSize := req.PageSize - - // list tenant models - models, err := h.modelProviderService.ListAllModels(page, pageSize) - if err != nil { - c.JSON(http.StatusOK, gin.H{ - "code": common.CodeDataError, - "message": err.Error(), - "data": nil, - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "code": 0, - "message": "success", - "data": models, - }) - } else { - // show model - model, err := h.modelProviderService.ShowModel(*req.ModelName) - if err != nil { - c.JSON(http.StatusOK, gin.H{ - "code": common.CodeDataError, - "message": err.Error(), - "data": nil, - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "code": 0, - "message": "success", - "data": model, - }) - } + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": models, + }) return } + +func (h *ModelHandler) ShowModel(c *gin.Context) { + encodedModelName := c.Param("model_name") + if encodedModelName == "" { + c.JSON(http.StatusOK, gin.H{ + "code": 400, + "message": "Encoded model name is empty", + }) + return + } + + decodedModelName, err := common.DecodeFromBase64(encodedModelName) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": 400, + "message": err.Error(), + }) + return + } + if decodedModelName == "" { + c.JSON(http.StatusOK, gin.H{ + "code": 400, + "message": "Decoded model name is empty", + }) + return + } + + // Get model + model, err := h.modelProviderService.ShowModel(decodedModelName) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": common.CodeDataError, + "message": err.Error(), + "data": nil, + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "code": common.CodeSuccess, + "message": "success", + "data": model, + }) +} diff --git a/internal/router/router.go b/internal/router/router.go index d320ded31b..e1f17cc551 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -501,6 +501,7 @@ func (r *Router) Setup(engine *gin.Engine) { allModels := v1.Group("/all-models") { allModels.GET("", r.modelHandler.ListAllModels) + allModels.GET("/:model_name", r.modelHandler.ShowModel) } // Agent routes