Refactor Go server model provider reading and access (#13831)

### What problem does this PR solve?

1. Refactor model provider json file format
2. Use memory data structure to replace database
3. Add CLI command to access

```
RAGFlow(user)> list pool models from 'xai';
+-------------------------------------------------------------------------------------+------------+-------------+-----------------------+
| features                                                                            | max_tokens | model_types | name                  |
+-------------------------------------------------------------------------------------+------------+-------------+-----------------------+
| map[]                                                                               | 256000     | [llm]       | grok-4                |
| map[]                                                                               | 131072     | [llm]       | grok-3                |
| map[]                                                                               | 131072     | [llm]       | grok-3-fast           |
| map[]                                                                               | 131072     | [llm]       | grok-3-mini           |
| map[]                                                                               | 131072     | [llm]       | grok-3-mini-mini-fast |
| map[multimodal:map[enabled:true input_modalities:[image] output_modalities:[text]]] | 32768      | [vlm]       | grok-2-vision         |
+-------------------------------------------------------------------------------------+------------+-------------+-----------------------+
RAGFlow(user)> show pool model 'grok-2-vision' from 'xai';
+-------------------------------------------------------------------------------------+------------+-------------+---------------+
| features                                                                            | max_tokens | model_types | name          |
+-------------------------------------------------------------------------------------+------------+-------------+---------------+
| map[multimodal:map[enabled:true input_modalities:[image] output_modalities:[text]]] | 32768      | [vlm]       | grok-2-vision |
+-------------------------------------------------------------------------------------+------------+-------------+---------------+
RAGFlow(user)> list pool providers;
+--------+------------------------------------------------------------+---------------------------+
| name   | tags                                                       | url                       |
+--------+------------------------------------------------------------+---------------------------+
| OpenAI | LLM,TEXT EMBEDDING,TTS,TEXT RE-RANK,SPEECH2TEXT,MODERATION | https://api.openai.com/v1 |
| xAI    | LLM                                                        | https://api.x.ai/v1       |
+--------+------------------------------------------------------------+---------------------------+
RAGFlow(user)> show pool provider 'openai';
+---------------------------+--------+------------------------------------------------------------+--------------+
| base_url                  | name   | tags                                                       | total_models |
+---------------------------+--------+------------------------------------------------------------+--------------+
| https://api.openai.com/v1 | OpenAI | LLM,TEXT EMBEDDING,TTS,TEXT RE-RANK,SPEECH2TEXT,MODERATION | 27           |
+---------------------------+--------+------------------------------------------------------------+--------------+
```

### 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-30 12:00:49 +08:00
committed by GitHub
parent a8bbe167a9
commit e20cf39735
16 changed files with 1867 additions and 632 deletions

View File

@@ -1,3 +1,19 @@
//
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package cli
import "fmt"
@@ -150,6 +166,8 @@ func (p *Parser) parseAdminListCommand() (*Command, error) {
return p.parseAdminListModelProviders()
case TokenDefault:
return p.parseAdminListDefaultModels()
case TokenPool:
return p.parseCommonListPoolModels()
case TokenChats:
p.nextToken()
// Semicolon is optional for SHOW TOKEN
@@ -255,6 +273,78 @@ 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) parseCommonShowPoolModel() (*Command, error) {
p.nextToken() // consume POOL
if p.curToken.Type == TokenProvider {
p.nextToken()
providerName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
cmd := NewCommand("show_pool_provider")
cmd.Params["provider_name"] = providerName
p.nextToken()
// Semicolon is optional for UNSET TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
} else if p.curToken.Type == TokenModel {
p.nextToken() // skip model
modelName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
p.nextToken() // skip model name
if p.curToken.Type != TokenFrom {
return nil, fmt.Errorf("expected FROM")
}
p.nextToken() // skip from
providerName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
p.nextToken() // skip provider name
cmd := NewCommand("show_pool_model")
cmd.Params["provider_name"] = providerName
cmd.Params["model_name"] = modelName
// 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) parseAdminListFiles() (*Command, error) {
p.nextToken() // consume FILES
if p.curToken.Type != TokenOf {
@@ -319,6 +409,8 @@ func (p *Parser) parseAdminShowCommand() (*Command, error) {
return p.parseShowVariable()
case TokenService:
return p.parseShowService()
case TokenPool:
return p.parseCommonShowPoolModel()
default:
return nil, fmt.Errorf("unknown SHOW target: %s", p.curToken.Value)
}