Add extra field to model instance (#14203)

### What problem does this PR solve?

Now each model support region with different URL

### Type of change

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

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
Jin Hai
2026-04-20 15:31:12 +08:00
committed by GitHub
parent 939933649a
commit af2ed416a7
22 changed files with 398 additions and 550 deletions

View File

@@ -1187,35 +1187,36 @@ func (p *Parser) parseAdminSetVariable() (*Command, error) {
func (p *Parser) parseAdminSetDefault() (*Command, error) {
p.nextToken() // consume DEFAULT
var modelType, modelID string
var modelType string
switch p.curToken.Type {
case TokenLLM:
modelType = "llm_id"
case TokenVLM:
modelType = "img2txt_id"
case TokenChat:
modelType = "chat"
case TokenVision:
modelType = "vision"
case TokenEmbedding:
modelType = "embd_id"
case TokenReranker:
modelType = "reranker_id"
modelType = "embedding"
case TokenRerank:
modelType = "rerank"
case TokenASR:
modelType = "asr_id"
modelType = "asr"
case TokenTTS:
modelType = "tts_id"
modelType = "tts"
case TokenOCR:
modelType = "ocr"
default:
return nil, fmt.Errorf("unknown model type: %s", p.curToken.Value)
}
p.nextToken()
id, err := p.parseQuotedString()
compositeModelName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
modelID = id
cmd := NewCommand("set_default_model")
cmd.Params["model_type"] = modelType
cmd.Params["model_id"] = modelID
cmd.Params["composite_model_name"] = compositeModelName
p.nextToken()
// Semicolon is optional for UNSET TOKEN
@@ -1254,18 +1255,20 @@ func (p *Parser) parseAdminResetCommand() (*Command, error) {
var modelType string
switch p.curToken.Type {
case TokenLLM:
modelType = "llm_id"
case TokenVLM:
modelType = "img2txt_id"
case TokenChat:
modelType = "chat"
case TokenVision:
modelType = "vision"
case TokenEmbedding:
modelType = "embd_id"
case TokenReranker:
modelType = "reranker_id"
modelType = "embedding"
case TokenRerank:
modelType = "rerank"
case TokenASR:
modelType = "asr_id"
modelType = "asr"
case TokenTTS:
modelType = "tts_id"
modelType = "tts"
case TokenOCR:
modelType = "ocr"
default:
return nil, fmt.Errorf("unknown model type: %s", p.curToken.Value)
}

View File

@@ -250,6 +250,8 @@ func (c *RAGFlowClient) ExecuteUserCommand(cmd *Command) (ResponseIf, error) {
return c.ShowCurrentModel(cmd)
case "set_default_model":
return c.SetDefaultModel(cmd)
case "reset_default_model":
return c.ResetDefaultModel(cmd)
case "list_user_default_models":
return c.ListDefaultModels(cmd)
// Dataset, metadata commands

View File

@@ -375,27 +375,29 @@ func (c *RAGFlowClient) ShowModel(cmd *Command) (ResponseIf, error) {
func (c *RAGFlowClient) SetDefaultModel(cmd *Command) (ResponseIf, error) {
modeType, ok := cmd.Params["model_type"].(string)
modelType, ok := cmd.Params["model_type"].(string)
if !ok {
return nil, fmt.Errorf("model_type not provided")
}
modelProvider, ok := cmd.Params["model_provider"].(string)
if !ok {
return nil, fmt.Errorf("model_provider not provided")
}
modelInstance, ok := cmd.Params["model_instance"].(string)
if !ok {
return nil, fmt.Errorf("model_instance not provided")
}
modelName, ok := cmd.Params["model_name"].(string)
compositeModelName, ok := cmd.Params["composite_model_name"].(string)
if !ok {
return nil, fmt.Errorf("model_name not provided")
}
var providerName, instanceName, modelName string
names := strings.Split(compositeModelName, "/")
if len(names) != 3 {
return nil, fmt.Errorf("model name must be in format 'provider/instance/model'")
}
providerName = names[0]
instanceName = names[1]
modelName = names[2]
payload := map[string]interface{}{
"model_type": modeType,
"model_provider": modelProvider,
"model_instance": modelInstance,
"model_type": modelType,
"model_provider": providerName,
"model_instance": instanceName,
"model_name": modelName,
}
@@ -420,6 +422,38 @@ func (c *RAGFlowClient) SetDefaultModel(cmd *Command) (ResponseIf, error) {
return &result, nil
}
func (c *RAGFlowClient) ResetDefaultModel(cmd *Command) (ResponseIf, error) {
modelType, ok := cmd.Params["model_type"].(string)
if !ok {
return nil, fmt.Errorf("model_type not provided")
}
payload := map[string]interface{}{
"model_type": modelType,
}
resp, err := c.HTTPClient.Request("PATCH", "/models", true, "web", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to reset default model: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to reset default model: 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("failed to reset default model: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *RAGFlowClient) ListDefaultModels(cmd *Command) (ResponseIf, error) {
resp, err := c.HTTPClient.Request("GET", "/models", true, "web", nil, nil)
if err != nil {

View File

@@ -327,18 +327,18 @@ func (l *Lexer) lookupIdent(ident string) Token {
return Token{Type: TokenSearch, Value: ident}
case "CURRENT":
return Token{Type: TokenCurrent, Value: ident}
case "LLM":
return Token{Type: TokenLLM, Value: ident}
case "VLM":
return Token{Type: TokenVLM, Value: ident}
case "VISION":
return Token{Type: TokenVision, Value: ident}
case "EMBEDDING":
return Token{Type: TokenEmbedding, Value: ident}
case "RERANKER":
return Token{Type: TokenReranker, Value: ident}
case "RERANK":
return Token{Type: TokenRerank, Value: ident}
case "ASR":
return Token{Type: TokenASR, Value: ident}
case "TTS":
return Token{Type: TokenTTS, Value: ident}
case "OCR":
return Token{Type: TokenOCR, Value: ident}
case "ASYNC":
return Token{Type: TokenAsync, Value: ident}
case "SYNC":

View File

@@ -90,12 +90,12 @@ const (
TokenPipeline
TokenSearch
TokenCurrent
TokenLLM
TokenVLM
TokenVision
TokenEmbedding
TokenReranker
TokenRerank
TokenASR
TokenTTS
TokenOCR
TokenAsync
TokenSync
TokenBenchmark

View File

@@ -1417,8 +1417,8 @@ func (c *RAGFlowClient) ChatToModel(cmd *Command) (ResponseIf, error) {
var providerName, instanceName, modelName string
// Check if model_name is provided in command
if compositeModelName, ok := cmd.Params["model_name"].(string); ok && compositeModelName != "" {
// Check if composite_model_name is provided in command
if compositeModelName, ok := cmd.Params["composite_model_name"].(string); ok && compositeModelName != "" {
names := strings.Split(compositeModelName, "/")
if len(names) != 3 {
return nil, fmt.Errorf("model name must be in format 'provider/instance/model'")
@@ -1524,12 +1524,12 @@ func (c *RAGFlowClient) UseModel(cmd *Command) (ResponseIf, error) {
return nil, fmt.Errorf("this command is only allowed in USER mode")
}
modelIdentifier, ok := cmd.Params["model_identifier"].(string)
if !ok || modelIdentifier == "" {
compositeModelName, ok := cmd.Params["composite_model_name"].(string)
if !ok || compositeModelName == "" {
return nil, fmt.Errorf("model identifier not provided")
}
names := strings.Split(modelIdentifier, "/")
names := strings.Split(compositeModelName, "/")
if len(names) != 3 {
return nil, fmt.Errorf("model identifier must be in format 'provider/instance/model'")
}

View File

@@ -1597,49 +1597,48 @@ func (p *Parser) parseSetVariable() (*Command, error) {
func (p *Parser) parseSetDefault() (*Command, error) {
p.nextToken() // consume DEFAULT
var modelType, modelProvider, modelInstance, modelName string
var modelType, compositeModelName string
var err error
switch p.curToken.Type {
case TokenLLM:
case TokenChat:
modelType = "chat"
case TokenVLM:
modelType = "image2text"
case TokenVision:
modelType = "vision"
case TokenEmbedding:
modelType = "embedding"
case TokenReranker:
case TokenRerank:
modelType = "rerank"
case TokenASR:
modelType = "asr"
case TokenTTS:
modelType = "tts"
case TokenOCR:
modelType = "ocr"
default:
return nil, fmt.Errorf("unknown model type: %s", p.curToken.Value)
}
p.nextToken() // pass model type
p.nextToken()
modelProvider, err = p.parseQuotedString()
if p.curToken.Type != TokenModel {
return nil, fmt.Errorf("expected MODEL")
}
p.nextToken() // pass MODEL
// Format: 'provider/instance/model' or just 'message'
if p.curToken.Type != TokenQuotedString {
return nil, fmt.Errorf("expected quoted string with format provider/instance/model")
}
compositeModelName, err = p.parseQuotedString()
if err != nil {
return nil, err
}
p.nextToken()
modelInstance, err = p.parseQuotedString()
if err != nil {
return nil, err
}
p.nextToken()
modelName, err = p.parseQuotedString()
if err != nil {
return nil, err
}
cmd := NewCommand("set_default_model")
cmd.Params["model_type"] = modelType
cmd.Params["model_provider"] = modelProvider
cmd.Params["model_instance"] = modelInstance
cmd.Params["model_name"] = modelName
cmd.Params["composite_model_name"] = compositeModelName
p.nextToken()
// Semicolon is optional for UNSET TOKEN
@@ -1717,26 +1716,33 @@ func (p *Parser) parseResetCommand() (*Command, error) {
var modelType string
switch p.curToken.Type {
case TokenLLM:
modelType = "llm_id"
case TokenVLM:
modelType = "img2txt_id"
case TokenChat:
modelType = "chat"
case TokenVision:
modelType = "vision"
case TokenEmbedding:
modelType = "embd_id"
case TokenReranker:
modelType = "reranker_id"
modelType = "embedding"
case TokenRerank:
modelType = "rerank"
case TokenASR:
modelType = "asr_id"
modelType = "asr"
case TokenTTS:
modelType = "tts_id"
modelType = "tts"
case TokenOCR:
modelType = "ocr"
default:
return nil, fmt.Errorf("unknown model type: %s", p.curToken.Value)
}
cmd := NewCommand("reset_default_model")
cmd.Params["model_type"] = modelType
p.nextToken()
if p.curToken.Type != TokenModel {
return nil, fmt.Errorf("expected MODEL")
}
p.nextToken() // pass MODEL
// Semicolon is optional for UNSET TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
@@ -2144,7 +2150,7 @@ func (p *Parser) parseDisableCommand() (*Command, error) {
func (p *Parser) parseChatCommand() (*Command, error) {
p.nextToken() // consume CHAT
var modelName string
var compositeModelName string
var message string
// Check if we have a quoted string that looks like a model identifier (contains two slashes)
@@ -2156,7 +2162,7 @@ func (p *Parser) parseChatCommand() (*Command, error) {
slashCount := strings.Count(firstArg, "/")
if slashCount == 2 {
// This is likely a model identifier, expect another quoted string for message
modelName = firstArg
compositeModelName = firstArg
p.nextToken()
// After model name, expect message
@@ -2184,8 +2190,8 @@ func (p *Parser) parseChatCommand() (*Command, error) {
}
cmd := NewCommand("chat_to_model")
if modelName != "" {
cmd.Params["model_name"] = modelName
if compositeModelName != "" {
cmd.Params["composite_model_name"] = compositeModelName
}
cmd.Params["message"] = message
cmd.Params["reasoning"] = false
@@ -2213,7 +2219,7 @@ func (p *Parser) parseUseCommand() (*Command, error) {
p.nextToken() // consume MODEL
// Parse model identifier in format 'provider/instance/model'
modelIdentifier, err := p.parseQuotedString()
compositeModelName, err := p.parseQuotedString()
if err != nil {
return nil, fmt.Errorf("expected model identifier in format 'provider/instance/model': %w", err)
}
@@ -2225,7 +2231,7 @@ func (p *Parser) parseUseCommand() (*Command, error) {
}
cmd := NewCommand("use_model")
cmd.Params["model_identifier"] = modelIdentifier
cmd.Params["composite_model_name"] = compositeModelName
return cmd, nil
}