mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-06 03:18:36 +08:00
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:
@@ -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()
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user