New provider and models API and CLI (#13865)

### What problem does this PR solve?

As title.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Refactoring

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
Jin Hai
2026-03-31 18:42:12 +08:00
committed by GitHub
parent 68b4287892
commit efd6ecc3e5
13 changed files with 528 additions and 99 deletions

View File

@@ -193,9 +193,10 @@ func startServer(config *server.Config) {
searchHandler := handler.NewSearchHandler(searchService, userService)
fileHandler := handler.NewFileHandler(fileService, userService)
memoryHandler := handler.NewMemoryHandler(memoryService)
providerHandler := handler.NewProviderHandler(userService)
// Initialize router
r := router.NewRouter(authHandler, userHandler, tenantHandler, documentHandler, datasetsHandler, systemHandler, kbHandler, chunkHandler, llmHandler, chatHandler, chatSessionHandler, connectorHandler, searchHandler, fileHandler, memoryHandler)
r := router.NewRouter(authHandler, userHandler, tenantHandler, documentHandler, datasetsHandler, systemHandler, kbHandler, chunkHandler, llmHandler, chatHandler, chatSessionHandler, connectorHandler, searchHandler, fileHandler, memoryHandler, providerHandler)
// Create Gin engine
ginEngine := gin.New()

View File

@@ -21,11 +21,13 @@ import (
"fmt"
"net/http"
"ragflow/internal/common"
"ragflow/internal/dao"
"ragflow/internal/logger"
"ragflow/internal/server"
"ragflow/internal/service"
"ragflow/internal/utility"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
@@ -794,6 +796,115 @@ func (h *Handler) RestartService(c *gin.Context) {
success(c, result, "")
}
func (h *Handler) ListProviders(c *gin.Context) {
keywords := ""
if queryKeywords := c.Query("available"); queryKeywords != "" {
keywords = queryKeywords
}
// convert keywords to small case
keywords = strings.ToLower(keywords)
if keywords == "true" {
// list pool providers
providers, err := dao.GetModelProviderManager().ListProviders()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": common.CodeNotFound,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "success",
"data": providers,
})
}
}
func (h *Handler) ShowProvider(c *gin.Context) {
providerName := c.Param("provider_name")
if providerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "Provider name is required",
})
return
}
provider, err := dao.GetModelProviderManager().GetProviderByName(providerName)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": common.CodeNotFound,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "success",
"data": provider,
})
}
func (h *Handler) ListModels(c *gin.Context) {
providerName := c.Param("provider_name")
if providerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "Provider name is required",
})
return
}
models, err := dao.GetModelProviderManager().ListModels(providerName)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": common.CodeNotFound,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "success",
"data": models,
})
}
func (h *Handler) ShowModel(c *gin.Context) {
providerName := c.Param("provider_name")
if providerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "Provider name is required",
})
return
}
modelName := c.Param("model_name")
if modelName == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "Model name is required",
})
return
}
model, err := dao.GetModelProviderManager().GetModelByName(providerName, modelName)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": common.CodeNotFound,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "success",
"data": model,
})
}
// GetVariables handle get variables
// Python logic: if request body is empty, list all variables; otherwise get single variable by var_name from body
func (h *Handler) GetVariables(c *gin.Context) {

View File

@@ -17,8 +17,6 @@
package admin
import (
"ragflow/internal/handler"
"github.com/gin-gonic/gin"
)
@@ -48,15 +46,6 @@ func (r *Router) Setup(engine *gin.Engine) {
admin.POST("/reports", r.handler.Reports)
// provider pool route group
provider := admin.Group("providers")
{
provider.GET("/", handler.ListPoolProviders)
provider.GET("/:provider_name", handler.ShowPoolProvider)
provider.GET("/:provider_name/models", handler.ListPoolModels)
provider.GET("/:provider_name/models/:model_name", handler.ShowPoolModel)
}
// Protected routes
protected := admin.Group("")
protected.Use(r.handler.AuthMiddleware())
@@ -136,6 +125,14 @@ func (r *Router) Setup(engine *gin.Engine) {
// Log level
protected.GET("/log_level", r.handler.GetLogLevel)
protected.PUT("/log_level", r.handler.SetLogLevel)
provider := protected.Group("/providers")
{
provider.GET("/", r.handler.ListProviders)
provider.GET("/:provider_name", r.handler.ShowProvider)
provider.GET("/:provider_name/models", r.handler.ListModels)
provider.GET("/:provider_name/models/:model_name", r.handler.ShowModel)
}
}
}

View File

@@ -166,8 +166,10 @@ func (p *Parser) parseAdminListCommand() (*Command, error) {
return p.parseAdminListModelProviders()
case TokenDefault:
return p.parseAdminListDefaultModels()
case TokenPool:
return p.parseCommonListPoolModels()
case TokenAvailable:
return p.parseCommonListProviders()
case TokenModels:
return p.parseListModelsOfProvider()
case TokenChats:
p.nextToken()
// Semicolon is optional for SHOW TOKEN
@@ -273,31 +275,38 @@ func (p *Parser) parseAdminListDefaultModels() (*Command, error) {
return NewCommand("list_user_default_models"), nil
}
func (p *Parser) parseCommonListPoolModels() (*Command, error) {
p.nextToken() // consume POOL
if p.curToken.Type == TokenProviders {
return NewCommand("list_pool_providers"), nil
} else if p.curToken.Type == TokenModels {
p.nextToken()
if p.curToken.Type != TokenFrom {
return nil, fmt.Errorf("expected FROM")
}
p.nextToken()
providerName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
cmd := NewCommand("list_pool_models")
cmd.Params["provider_name"] = providerName
p.nextToken()
// Semicolon is optional for UNSET TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
} else {
return nil, fmt.Errorf("expected PROVIDERS or MODELS")
func (p *Parser) parseListModelsOfProvider() (*Command, error) {
if p.curToken.Type != TokenModels {
return nil, fmt.Errorf("expected MODELS")
}
p.nextToken()
if p.curToken.Type != TokenFrom {
return nil, fmt.Errorf("expected FROM")
}
p.nextToken()
providerName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
cmd := NewCommand("list_provider_models")
cmd.Params["provider_name"] = providerName
p.nextToken()
// Semicolon is optional for UNSET TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
func (p *Parser) parseCommonListProviders() (*Command, error) {
p.nextToken() // consume AVAILABLE
if p.curToken.Type != TokenProviders {
return nil, fmt.Errorf("expected PROVIDERS")
}
return NewCommand("list_available_providers"), nil
}
func (p *Parser) parseCommonShowPoolModel() (*Command, error) {
@@ -409,8 +418,10 @@ func (p *Parser) parseAdminShowCommand() (*Command, error) {
return p.parseShowVariable()
case TokenService:
return p.parseShowService()
case TokenPool:
return p.parseCommonShowPoolModel()
case TokenProvider:
return p.parseShowProvider()
case TokenModel:
return p.parseShowModel()
default:
return nil, fmt.Errorf("unknown SHOW target: %s", p.curToken.Value)
}

View File

@@ -1006,15 +1006,17 @@ Commands (User Mode):
LIST MODEL PROVIDERS; - List model providers
LIST DEFAULT MODELS; - List default models
LIST TOKENS; - List API tokens
LIST PROVIDERS; - List available LLM providers
CREATE TOKEN; - Create new API token
CREATE PROVIDER 'name'; - Create a provider without API key
CREATE PROVIDER 'name' 'api_key'; - Create a provider with API key
DROP TOKEN 'token_value'; - Delete an API token
DROP PROVIDER 'name'; - Delete a provider
SET TOKEN 'token_value'; - Set and validate API token
SHOW TOKEN; - Show current API token
SHOW PROVIDER 'name'; - Show provider details
UNSET TOKEN; - Remove current API token
CREATE INDEX FOR DATASET 'name' VECTOR_SIZE N; - Create index for dataset
DROP INDEX FOR DATASET 'name'; - Drop index for dataset
CREATE INDEX DOC_META; - Create doc meta index
DROP INDEX DOC_META; - Drop doc meta index
ALTER PROVIDER 'name' NAME 'new_name'; - Rename a provider
Context Engine Commands (no quotes):
ls [path] - List resources

View File

@@ -152,14 +152,14 @@ func (c *RAGFlowClient) ExecuteAdminCommand(cmd *Command) (ResponseIf, error) {
return c.ListAdminTokens(cmd)
case "drop_token":
return c.DropAdminToken(cmd)
case "list_pool_providers":
return c.ListPoolProviders(cmd)
case "show_pool_provider":
return c.ShowPoolProvider(cmd)
case "list_pool_models":
return c.ListPoolModels(cmd)
case "show_pool_model":
return c.ShowPoolModel(cmd)
case "list_available_providers":
return c.ListAvailableProviders(cmd)
case "show_provider":
return c.ShowProvider(cmd)
case "list_provider_models":
return c.ListModels(cmd)
case "show_model":
return c.ShowModel(cmd)
// TODO: Implement other commands
default:
return nil, fmt.Errorf("command '%s' would be executed with API", cmd.Type)
@@ -204,13 +204,20 @@ func (c *RAGFlowClient) ExecuteUserCommand(cmd *Command) (ResponseIf, error) {
case "drop_doc_meta_index":
return c.DropDocMetaIndex(cmd)
case "list_pool_providers":
return c.ListPoolProviders(cmd)
case "show_pool_provider":
return c.ShowPoolProvider(cmd)
case "list_pool_models":
return c.ListPoolModels(cmd)
case "show_pool_model":
return c.ShowPoolModel(cmd)
return c.ListAvailableProviders(cmd)
case "show_provider":
return c.ShowProvider(cmd)
case "list_provider_models":
return c.ListModels(cmd)
case "show_model":
return c.ShowModel(cmd)
// Provider commands
case "create_provider":
return c.CreateProvider(cmd)
case "list_providers":
return c.ListProviders(cmd)
case "drop_provider":
return c.DropProvider(cmd)
// ContextEngine commands
case "ce_ls":
return c.CEList(cmd)

View File

@@ -237,13 +237,13 @@ func (c *RAGFlowClient) Logout() (ResponseIf, error) {
return &result, nil
}
func (c *RAGFlowClient) ListPoolProviders(cmd *Command) (ResponseIf, error) {
func (c *RAGFlowClient) ListAvailableProviders(cmd *Command) (ResponseIf, error) {
var endPoint string
if c.ServerType == "admin" {
endPoint = fmt.Sprintf("/admin/providers")
endPoint = fmt.Sprintf("/admin/providers?available=true")
} else {
endPoint = fmt.Sprintf("/providers")
endPoint = fmt.Sprintf("/providers?available=true")
}
resp, err := c.HTTPClient.Request("GET", endPoint, true, "web", nil, nil)
@@ -267,7 +267,7 @@ func (c *RAGFlowClient) ListPoolProviders(cmd *Command) (ResponseIf, error) {
return &result, nil
}
func (c *RAGFlowClient) ShowPoolProvider(cmd *Command) (ResponseIf, error) {
func (c *RAGFlowClient) ShowProvider(cmd *Command) (ResponseIf, error) {
providerName, ok := cmd.Params["provider_name"].(string)
if !ok {
return nil, fmt.Errorf("provider_name not provided")
@@ -301,7 +301,7 @@ func (c *RAGFlowClient) ShowPoolProvider(cmd *Command) (ResponseIf, error) {
return &result, nil
}
func (c *RAGFlowClient) ListPoolModels(cmd *Command) (ResponseIf, error) {
func (c *RAGFlowClient) ListModels(cmd *Command) (ResponseIf, error) {
providerName, ok := cmd.Params["provider_name"].(string)
if !ok {
@@ -336,7 +336,7 @@ func (c *RAGFlowClient) ListPoolModels(cmd *Command) (ResponseIf, error) {
return &result, nil
}
func (c *RAGFlowClient) ShowPoolModel(cmd *Command) (ResponseIf, error) {
func (c *RAGFlowClient) ShowModel(cmd *Command) (ResponseIf, error) {
providerName, ok := cmd.Params["provider_name"].(string)
if !ok {
return nil, fmt.Errorf("provider_name not provided")

View File

@@ -301,8 +301,10 @@ func (l *Lexer) lookupIdent(ident string) Token {
return Token{Type: TokenVectorSize, Value: ident}
case "DOC_META":
return Token{Type: TokenDocMeta, Value: ident}
case "POOL":
return Token{Type: TokenPool, Value: ident}
case "AVAILABLE":
return Token{Type: TokenAvailable, Value: ident}
case "NAME":
return Token{Type: TokenName, Value: ident}
default:
return Token{Type: TokenIdentifier, Value: ident}
}

View File

@@ -69,7 +69,7 @@ const (
TokenKey
TokenKeys
TokenGenerate
TokenPool
TokenAvailable
TokenModel
TokenModels
TokenProvider
@@ -103,6 +103,7 @@ const (
TokenIndex
TokenVectorSize
TokenDocMeta
TokenName // For ALTER PROVIDER <name> NAME <new_name>
// Literals
TokenIdentifier

View File

@@ -751,6 +751,119 @@ func (c *RAGFlowClient) DropDocMetaIndex(cmd *Command) (ResponseIf, error) {
return &result, nil
}
// CreateProvider creates a new model provider
// CREATE PROVIDER <name>
// CREATE PROVIDER <name> <api_key>
func (c *RAGFlowClient) CreateProvider(cmd *Command) (ResponseIf, error) {
if c.ServerType != "user" {
return nil, fmt.Errorf("this command is only allowed in USER mode")
}
providerName, ok := cmd.Params["provider_name"].(string)
if !ok {
return nil, fmt.Errorf("provider name not provided")
}
// Get optional api_key
apiKey, _ := cmd.Params["api_key"].(string)
// Build payload
payload := map[string]interface{}{
"llm_factory": providerName,
"api_key": apiKey,
"verify": apiKey != "", // Only verify if api_key is provided
}
resp, err := c.HTTPClient.Request("POST", "/llm/set_api_key", true, "web", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to create provider: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to create provider: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("create provider failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
// ListProviders lists all providers
// LIST PROVIDERS
func (c *RAGFlowClient) ListProviders(cmd *Command) (ResponseIf, error) {
if c.ServerType != "user" {
return nil, fmt.Errorf("this command is only allowed in USER mode")
}
resp, err := c.HTTPClient.Request("GET", "/llm/factories", true, "web", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to list providers: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to list providers: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("list providers failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
// DropProvider deletes a provider
// DROP PROVIDER <name>
func (c *RAGFlowClient) DropProvider(cmd *Command) (ResponseIf, error) {
if c.ServerType != "user" {
return nil, fmt.Errorf("this command is only allowed in USER mode")
}
providerName, ok := cmd.Params["provider_name"].(string)
if !ok {
return nil, fmt.Errorf("provider name not provided")
}
// Build payload
payload := map[string]interface{}{
"llm_factory": providerName,
}
resp, err := c.HTTPClient.Request("DELETE", "/llm/factory", true, "web", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to drop provider: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to drop provider: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result SimpleResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("drop provider failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
// Context related commands
// CEList handles the ls command - lists nodes using Context Engine

View File

@@ -151,10 +151,14 @@ func (p *Parser) parseListCommand() (*Command, error) {
return p.parseListTokens()
case TokenModel:
return p.parseListModelProviders()
case TokenModels:
return p.parseListModelsOfProvider()
case TokenProviders:
return p.parseListProviders()
case TokenDefault:
return p.parseListDefaultModels()
case TokenPool:
return p.parseCommonListPoolModels()
case TokenAvailable:
return p.parseCommonListProviders()
case TokenChats:
p.nextToken()
// Semicolon is optional for SHOW TOKEN
@@ -259,6 +263,16 @@ func (p *Parser) parseListModelProviders() (*Command, error) {
return NewCommand("list_user_model_providers"), nil
}
// parseListProviders parses LIST PROVIDERS command
func (p *Parser) parseListProviders() (*Command, error) {
p.nextToken() // consume PROVIDERS
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return NewCommand("list_providers"), nil
}
func (p *Parser) parseListDefaultModels() (*Command, error) {
p.nextToken() // consume DEFAULT
if p.curToken.Type != TokenModels {
@@ -336,8 +350,10 @@ func (p *Parser) parseShowCommand() (*Command, error) {
return p.parseShowVariable()
case TokenService:
return p.parseShowService()
case TokenPool:
return p.parseCommonShowPoolModel()
case TokenProvider:
return p.parseShowProvider()
case TokenModel:
return p.parseShowModel()
default:
return nil, fmt.Errorf("unknown SHOW target: %s", p.curToken.Value)
}
@@ -433,6 +449,56 @@ func (p *Parser) parseShowService() (*Command, error) {
return cmd, nil
}
func (p *Parser) parseShowModel() (*Command, error) {
p.nextToken() // consume model
modelName, err := p.parseQuotedString()
if err != nil {
return nil, fmt.Errorf("expected model name: %w", err)
}
cmd := NewCommand("show_model")
cmd.Params["model_name"] = modelName
p.nextToken() // consume model_name
if p.curToken.Type != TokenFrom {
return nil, fmt.Errorf("expected FROM")
}
p.nextToken() // consume from
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()
}
return cmd, nil
}
// parseShowProvider parses SHOW PROVIDER <name> command
func (p *Parser) parseShowProvider() (*Command, error) {
p.nextToken() // consume PROVIDER
providerName, err := p.parseQuotedString()
if err != nil {
return nil, fmt.Errorf("expected provider name: %w", err)
}
cmd := NewCommand("show_provider")
cmd.Params["provider_name"] = providerName
p.nextToken()
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
func (p *Parser) parseCreateCommand() (*Command, error) {
p.nextToken() // consume CREATE
@@ -443,6 +509,8 @@ func (p *Parser) parseCreateCommand() (*Command, error) {
return p.parseCreateRole()
case TokenModel:
return p.parseCreateModelProvider()
case TokenProvider:
return p.parseCreateProvider()
case TokenDataset:
return p.parseCreateDataset()
case TokenChat:
@@ -606,6 +674,39 @@ func (p *Parser) parseCreateModelProvider() (*Command, error) {
return cmd, nil
}
// parseCreateProvider parses CREATE PROVIDER commands
// CREATE PROVIDER <name>
// CREATE PROVIDER <name> <api_key>
func (p *Parser) parseCreateProvider() (*Command, error) {
p.nextToken() // consume PROVIDER
providerName, err := p.parseQuotedString()
if err != nil {
return nil, fmt.Errorf("expected provider name: %w", err)
}
cmd := NewCommand("create_provider")
cmd.Params["provider_name"] = providerName
p.nextToken()
// Check if api_key is provided (optional)
if p.curToken.Type == TokenQuotedString {
apiKey, err := p.parseQuotedString()
if err != nil {
return nil, fmt.Errorf("expected api key: %w", err)
}
cmd.Params["api_key"] = apiKey
p.nextToken()
}
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
func (p *Parser) parseCreateDataset() (*Command, error) {
p.nextToken() // consume DATASET
datasetName, err := p.parseQuotedString()
@@ -688,6 +789,8 @@ func (p *Parser) parseDropCommand() (*Command, error) {
return p.parseDropRole()
case TokenModel:
return p.parseDropModelProvider()
case TokenProvider:
return p.parseDropProvider()
case TokenDataset:
return p.parseDropDataset()
case TokenChat:
@@ -831,6 +934,26 @@ func (p *Parser) parseDropModelProvider() (*Command, error) {
return cmd, nil
}
// parseDropProvider parses DROP PROVIDER <name> command
func (p *Parser) parseDropProvider() (*Command, error) {
p.nextToken() // consume PROVIDER
providerName, err := p.parseQuotedString()
if err != nil {
return nil, fmt.Errorf("expected provider name: %w", err)
}
cmd := NewCommand("drop_provider")
cmd.Params["provider_name"] = providerName
p.nextToken()
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
func (p *Parser) parseDropDataset() (*Command, error) {
p.nextToken() // consume DATASET
datasetName, err := p.parseQuotedString()
@@ -875,6 +998,8 @@ func (p *Parser) parseAlterCommand() (*Command, error) {
return p.parseAlterUser()
case TokenRole:
return p.parseAlterRole()
case TokenProvider:
return p.parseAlterProvider()
default:
return nil, fmt.Errorf("unknown ALTER target: %s", p.curToken.Value)
}
@@ -1004,6 +1129,38 @@ func (p *Parser) parseAlterRole() (*Command, error) {
return cmd, nil
}
// parseAlterProvider parses ALTER PROVIDER <name> NAME <new_name> command
func (p *Parser) parseAlterProvider() (*Command, error) {
p.nextToken() // consume PROVIDER
providerName, err := p.parseQuotedString()
if err != nil {
return nil, fmt.Errorf("expected provider name: %w", err)
}
p.nextToken()
if p.curToken.Type != TokenName {
return nil, fmt.Errorf("expected NAME")
}
p.nextToken()
newName, err := p.parseQuotedString()
if err != nil {
return nil, fmt.Errorf("expected new provider name: %w", err)
}
cmd := NewCommand("alter_provider")
cmd.Params["provider_name"] = providerName
cmd.Params["new_name"] = newName
p.nextToken()
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
func (p *Parser) parseGrantCommand() (*Command, error) {
p.nextToken() // consume GRANT

View File

@@ -20,28 +20,53 @@ import (
"net/http"
"ragflow/internal/common"
"ragflow/internal/dao"
"ragflow/internal/service"
"strings"
"github.com/gin-gonic/gin"
)
func ListPoolProviders(c *gin.Context) {
providers, err := dao.GetModelProviderManager().ListProviders()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": common.CodeNotFound,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "success",
"data": providers,
})
// ProviderHandler provider handler
type ProviderHandler struct {
userService *service.UserService
}
func ShowPoolProvider(c *gin.Context) {
// NewProviderHandler create provider handler
func NewProviderHandler(userService *service.UserService) *ProviderHandler {
return &ProviderHandler{
userService: userService,
}
}
func (h *ProviderHandler) ListProviders(c *gin.Context) {
keywords := ""
if queryKeywords := c.Query("available"); queryKeywords != "" {
keywords = queryKeywords
}
// convert keywords to small case
keywords = strings.ToLower(keywords)
if keywords == "true" {
// list pool providers
providers, err := dao.GetModelProviderManager().ListProviders()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": common.CodeNotFound,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "success",
"data": providers,
})
}
}
func (h *ProviderHandler) ShowProvider(c *gin.Context) {
providerName := c.Param("provider_name")
if providerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
@@ -66,7 +91,7 @@ func ShowPoolProvider(c *gin.Context) {
})
}
func ListPoolModels(c *gin.Context) {
func (h *ProviderHandler) ListModels(c *gin.Context) {
providerName := c.Param("provider_name")
if providerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
@@ -90,7 +115,7 @@ func ListPoolModels(c *gin.Context) {
})
}
func ShowPoolModel(c *gin.Context) {
func (h *ProviderHandler) ShowModel(c *gin.Context) {
providerName := c.Param("provider_name")
if providerName == "" {
c.JSON(http.StatusBadRequest, gin.H{

View File

@@ -39,6 +39,7 @@ type Router struct {
searchHandler *handler.SearchHandler
fileHandler *handler.FileHandler
memoryHandler *handler.MemoryHandler
providerHandler *handler.ProviderHandler
}
// NewRouter create router
@@ -58,6 +59,7 @@ func NewRouter(
searchHandler *handler.SearchHandler,
fileHandler *handler.FileHandler,
memoryHandler *handler.MemoryHandler,
providerHandler *handler.ProviderHandler,
) *Router {
return &Router{
authHandler: authHandler,
@@ -75,6 +77,7 @@ func NewRouter(
searchHandler: searchHandler,
fileHandler: fileHandler,
memoryHandler: memoryHandler,
providerHandler: providerHandler,
}
}
@@ -100,15 +103,6 @@ func (r *Router) Setup(engine *gin.Engine) {
// User logout endpoint
engine.GET("/v1/user/logout", r.userHandler.Logout)
// provider pool route group
provider := engine.Group("/api/v1/providers")
{
provider.GET("/", handler.ListPoolProviders)
provider.GET("/:provider_name", handler.ShowPoolProvider)
provider.GET("/:provider_name/models", handler.ListPoolModels)
provider.GET("/:provider_name/models/:model_name", handler.ShowPoolModel)
}
// Protected routes
authorized := engine.Group("")
authorized.Use(r.authHandler.AuthMiddleware())
@@ -195,6 +189,14 @@ func (r *Router) Setup(engine *gin.Engine) {
// message.GET("", r.memoryHandler.GetMessages)
// message.GET("/:memory_id/:message_id/content", r.memoryHandler.GetMessageContent)
// }
// provider pool route group
provider := v1.Group("/providers")
{
provider.GET("/", r.providerHandler.ListProviders)
provider.GET("/:provider_name", r.providerHandler.ShowProvider)
provider.GET("/:provider_name/models", r.providerHandler.ListModels)
provider.GET("/:provider_name/models/:model_name", r.providerHandler.ShowModel)
}
}
// Knowledge base routes