mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-15 05:04:27 +08:00
Refactor model provider and command (#13887)
### What problem does this PR solve? Introduce 5 new tables, including model groups and provider instance. ### 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:
@@ -275,30 +275,6 @@ func (p *Parser) parseAdminListDefaultModels() (*Command, error) {
|
||||
return NewCommand("list_user_default_models"), nil
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -332,7 +332,7 @@ func looksLikeSQL(s string) bool {
|
||||
"LIST ", "SHOW ", "CREATE ", "DROP ", "ALTER ",
|
||||
"LOGIN ", "REGISTER ", "PING", "GRANT ", "REVOKE ",
|
||||
"SET ", "UNSET ", "UPDATE ", "DELETE ", "INSERT ",
|
||||
"SELECT ", "DESCRIBE ", "EXPLAIN ",
|
||||
"SELECT ", "DESCRIBE ", "EXPLAIN ", "ADD ", "ENABLE ", "DISABLE ", "CHAT ", "USE",
|
||||
}
|
||||
for _, prefix := range sqlPrefixes {
|
||||
if strings.HasPrefix(s, prefix) {
|
||||
@@ -1008,15 +1008,19 @@ Commands (User Mode):
|
||||
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
|
||||
ADD PROVIDER 'name'; - Create a provider without API key
|
||||
ADD PROVIDER 'name' 'api_key'; - Create a provider with API key
|
||||
DROP TOKEN 'token_value'; - Delete an API token
|
||||
DROP PROVIDER 'name'; - Delete a provider
|
||||
DELETE 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
|
||||
SHOW CURRENT MODEL; - Show current model settings
|
||||
UNSET TOKEN; - Remove current API token
|
||||
ALTER PROVIDER 'name' NAME 'new_name'; - Rename a provider
|
||||
USE MODEL 'provider/instance/model'; - Set current model for chat
|
||||
CHAT 'message'; - Chat using current model
|
||||
CHAT 'provider/instance/model' 'message'; - Chat with specified model
|
||||
|
||||
Context Engine Commands (no quotes):
|
||||
ls [path] - List resources
|
||||
|
||||
@@ -24,6 +24,13 @@ import (
|
||||
// PasswordPromptFunc is a function type for password input
|
||||
type PasswordPromptFunc func(prompt string) (string, error)
|
||||
|
||||
// CurrentModel holds the current model configuration
|
||||
type CurrentModel struct {
|
||||
Provider string
|
||||
Instance string
|
||||
Model string
|
||||
}
|
||||
|
||||
// RAGFlowClient handles API interactions with the RAGFlow server
|
||||
type RAGFlowClient struct {
|
||||
HTTPClient *HTTPClient
|
||||
@@ -31,6 +38,7 @@ type RAGFlowClient struct {
|
||||
PasswordPrompt PasswordPromptFunc // Function for password input
|
||||
OutputFormat OutputFormat // Output format: table, plain, json
|
||||
ContextEngine *ce.Engine // Context Engine for virtual filesystem
|
||||
CurrentModel *CurrentModel // Current model configuration
|
||||
}
|
||||
|
||||
// NewRAGFlowClient creates a new RAGFlow client
|
||||
@@ -158,6 +166,8 @@ func (c *RAGFlowClient) ExecuteAdminCommand(cmd *Command) (ResponseIf, error) {
|
||||
return c.ShowProvider(cmd)
|
||||
case "list_provider_models":
|
||||
return c.ListModels(cmd)
|
||||
case "list_instance_models":
|
||||
return c.ListInstanceModels(cmd)
|
||||
case "show_model":
|
||||
return c.ShowModel(cmd)
|
||||
// TODO: Implement other commands
|
||||
@@ -203,21 +213,44 @@ func (c *RAGFlowClient) ExecuteUserCommand(cmd *Command) (ResponseIf, error) {
|
||||
return c.CreateDocMetaIndex(cmd)
|
||||
case "drop_doc_meta_index":
|
||||
return c.DropDocMetaIndex(cmd)
|
||||
case "list_pool_providers":
|
||||
case "list_available_providers":
|
||||
return c.ListAvailableProviders(cmd)
|
||||
case "show_provider":
|
||||
return c.ShowProvider(cmd)
|
||||
case "list_provider_models":
|
||||
return c.ListModels(cmd)
|
||||
case "list_instance_models":
|
||||
return c.ListInstanceModels(cmd)
|
||||
case "show_model":
|
||||
return c.ShowModel(cmd)
|
||||
// Provider commands
|
||||
case "create_provider":
|
||||
return c.CreateProvider(cmd)
|
||||
case "add_provider":
|
||||
return c.AddProvider(cmd)
|
||||
case "list_providers":
|
||||
return c.ListProviders(cmd)
|
||||
case "drop_provider":
|
||||
return c.DropProvider(cmd)
|
||||
case "delete_provider":
|
||||
return c.DeleteProvider(cmd)
|
||||
// Provider instance commands
|
||||
case "create_provider_instance":
|
||||
return c.CreateProviderInstance(cmd)
|
||||
case "list_provider_instances":
|
||||
return c.ListProviderInstances(cmd)
|
||||
case "show_provider_instance":
|
||||
return c.ShowProviderInstance(cmd)
|
||||
case "alter_provider_instance":
|
||||
return c.AlterProviderInstance(cmd)
|
||||
case "drop_provider_instance":
|
||||
return c.DropProviderInstance(cmd)
|
||||
case "enable_model":
|
||||
return c.EnableOrDisableModel(cmd, "enable")
|
||||
case "disable_model":
|
||||
return c.EnableOrDisableModel(cmd, "disable")
|
||||
case "chat_to_model":
|
||||
return c.ChatToModel(cmd)
|
||||
case "use_model":
|
||||
return c.UseModel(cmd)
|
||||
case "show_current_model":
|
||||
return c.ShowCurrentModel(cmd)
|
||||
// ContextEngine commands
|
||||
case "ce_ls":
|
||||
return c.CEList(cmd)
|
||||
|
||||
@@ -181,6 +181,10 @@ func (l *Lexer) lookupIdent(ident string) Token {
|
||||
return Token{Type: TokenActive, Value: ident}
|
||||
case "ADMIN":
|
||||
return Token{Type: TokenAdmin, Value: ident}
|
||||
case "ADD":
|
||||
return Token{Type: TokenAdd, Value: ident}
|
||||
case "DELETE":
|
||||
return Token{Type: TokenDelete, Value: ident}
|
||||
case "PASSWORD":
|
||||
return Token{Type: TokenPassword, Value: ident}
|
||||
case "DATASET":
|
||||
@@ -305,14 +309,22 @@ func (l *Lexer) lookupIdent(ident string) Token {
|
||||
return Token{Type: TokenAvailable, Value: ident}
|
||||
case "NAME":
|
||||
return Token{Type: TokenName, Value: ident}
|
||||
case "POOL":
|
||||
return Token{Type: TokenPool, Value: ident}
|
||||
case "INSTANCE":
|
||||
return Token{Type: TokenInstance, Value: ident}
|
||||
case "INSTANCES":
|
||||
return Token{Type: TokenInstances, Value: ident}
|
||||
case "DISABLE":
|
||||
return Token{Type: TokenDisable, Value: ident}
|
||||
case "ENABLE":
|
||||
return Token{Type: TokenEnable, Value: ident}
|
||||
case "INSERT":
|
||||
return Token{Type: TokenInsert, Value: ident}
|
||||
case "FILE":
|
||||
return Token{Type: TokenFile, Value: ident}
|
||||
case "METADATA":
|
||||
return Token{Type: TokenMetadata, Value: ident}
|
||||
case "USE":
|
||||
return Token{Type: TokenUse, Value: ident}
|
||||
default:
|
||||
return Token{Type: TokenIdentifier, Value: ident}
|
||||
}
|
||||
|
||||
@@ -150,6 +150,10 @@ func (p *Parser) parseUserCommand() (*Command, error) {
|
||||
return p.parseCreateCommand()
|
||||
case TokenDrop:
|
||||
return p.parseDropCommand()
|
||||
case TokenAdd:
|
||||
return p.parseAddCommand()
|
||||
case TokenDelete:
|
||||
return p.parseDeleteCommand()
|
||||
case TokenAlter:
|
||||
return p.parseAlterCommand()
|
||||
case TokenGrant:
|
||||
@@ -182,6 +186,14 @@ func (p *Parser) parseUserCommand() (*Command, error) {
|
||||
return p.parseShutdownCommand()
|
||||
case TokenRestart:
|
||||
return p.parseRestartCommand()
|
||||
case TokenEnable:
|
||||
return p.parseEnableCommand()
|
||||
case TokenDisable:
|
||||
return p.parseDisableCommand()
|
||||
case TokenChat:
|
||||
return p.parseChatCommand()
|
||||
case TokenUse:
|
||||
return p.parseUseCommand()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown command: %s", p.curToken.Value)
|
||||
}
|
||||
|
||||
@@ -113,6 +113,34 @@ func (r *SimpleResponse) PrintOut() {
|
||||
}
|
||||
}
|
||||
|
||||
type MessageResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *MessageResponse) Type() string {
|
||||
return "message"
|
||||
}
|
||||
|
||||
func (r *MessageResponse) TimeCost() float64 {
|
||||
return r.Duration
|
||||
}
|
||||
|
||||
func (r *MessageResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
}
|
||||
|
||||
func (r *MessageResponse) PrintOut() {
|
||||
if r.Code == 0 {
|
||||
fmt.Println(r.Message)
|
||||
} else {
|
||||
fmt.Println("ERROR")
|
||||
fmt.Printf("%d, %s\n", r.Code, r.Message)
|
||||
}
|
||||
}
|
||||
|
||||
type RegisterResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
|
||||
@@ -42,6 +42,8 @@ const (
|
||||
TokenAlter
|
||||
TokenActive
|
||||
TokenAdmin
|
||||
TokenAdd
|
||||
TokenDelete
|
||||
TokenPassword
|
||||
TokenDataset
|
||||
TokenDatasets
|
||||
@@ -104,6 +106,11 @@ const (
|
||||
TokenVectorSize
|
||||
TokenDocMeta
|
||||
TokenName // For ALTER PROVIDER <name> NAME <new_name>
|
||||
TokenInstance
|
||||
TokenInstances
|
||||
TokenDisable
|
||||
TokenEnable
|
||||
TokenUse
|
||||
TokenInsert
|
||||
TokenFile
|
||||
TokenMetadata
|
||||
|
||||
@@ -751,10 +751,10 @@ 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) {
|
||||
// AddProvider creates a new model provider
|
||||
// ADD PROVIDER <name>
|
||||
// ADD PROVIDER <name> <api_key>
|
||||
func (c *RAGFlowClient) AddProvider(cmd *Command) (ResponseIf, error) {
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
@@ -764,28 +764,23 @@ func (c *RAGFlowClient) CreateProvider(cmd *Command) (ResponseIf, error) {
|
||||
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
|
||||
"provider_name": providerName,
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("POST", "/llm/set_api_key", true, "web", nil, payload)
|
||||
resp, err := c.HTTPClient.Request("POST", "/providers", true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create provider: %w", err)
|
||||
return nil, fmt.Errorf("failed to add provider: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to create provider: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
return nil, fmt.Errorf("failed to add provider: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
var result CommonDataResponse
|
||||
var result SimpleResponse
|
||||
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
||||
return nil, fmt.Errorf("create provider failed: invalid JSON (%w)", err)
|
||||
return nil, fmt.Errorf("add provider failed: invalid JSON (%w)", err)
|
||||
}
|
||||
|
||||
if result.Code != 0 {
|
||||
@@ -803,7 +798,7 @@ func (c *RAGFlowClient) ListProviders(cmd *Command) (ResponseIf, error) {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("GET", "/llm/factories", true, "web", nil, nil)
|
||||
resp, err := c.HTTPClient.Request("GET", "/providers", true, "web", nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list providers: %w", err)
|
||||
}
|
||||
@@ -825,9 +820,9 @@ func (c *RAGFlowClient) ListProviders(cmd *Command) (ResponseIf, error) {
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// DropProvider deletes a provider
|
||||
// DROP PROVIDER <name>
|
||||
func (c *RAGFlowClient) DropProvider(cmd *Command) (ResponseIf, error) {
|
||||
// DeleteProvider deletes a provider
|
||||
// DELETE PROVIDER <name>
|
||||
func (c *RAGFlowClient) DeleteProvider(cmd *Command) (ResponseIf, error) {
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
@@ -837,23 +832,25 @@ func (c *RAGFlowClient) DropProvider(cmd *Command) (ResponseIf, error) {
|
||||
return nil, fmt.Errorf("provider name not provided")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/providers/%s", providerName)
|
||||
|
||||
// Build payload
|
||||
payload := map[string]interface{}{
|
||||
"llm_factory": providerName,
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("DELETE", "/llm/factory", true, "web", nil, payload)
|
||||
resp, err := c.HTTPClient.Request("DELETE", url, true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to drop provider: %w", err)
|
||||
return nil, fmt.Errorf("failed to delete provider: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to drop provider: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
return nil, fmt.Errorf("failed to delete 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)
|
||||
return nil, fmt.Errorf("delete provider failed: invalid JSON (%w)", err)
|
||||
}
|
||||
|
||||
if result.Code != 0 {
|
||||
@@ -864,6 +861,410 @@ func (c *RAGFlowClient) DropProvider(cmd *Command) (ResponseIf, error) {
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// CreateProviderInstance creates a new provider instance
|
||||
// CREATE PROVIDER <name> INSTANCE <instance_name> <api_key>
|
||||
func (c *RAGFlowClient) CreateProviderInstance(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")
|
||||
}
|
||||
|
||||
instanceName, ok := cmd.Params["instance_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("instance name not provided")
|
||||
}
|
||||
|
||||
apiKey, ok := cmd.Params["api_key"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("API key not provided")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/providers/%s/instances", providerName)
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"instance_name": instanceName,
|
||||
"api_key": apiKey,
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("POST", url, true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create provider instance: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to create provider instance: 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("create provider instance failed: invalid JSON (%w)", err)
|
||||
}
|
||||
|
||||
if result.Code != 0 {
|
||||
return nil, fmt.Errorf("%s", result.Message)
|
||||
}
|
||||
|
||||
result.Duration = resp.Duration
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// ListProviderInstances lists all instances of a provider
|
||||
// LIST INSTANCES FROM PROVIDER <name>
|
||||
func (c *RAGFlowClient) ListProviderInstances(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")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/providers/%s/instances", providerName)
|
||||
|
||||
resp, err := c.HTTPClient.Request("GET", url, true, "web", nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list instances: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to list instances: 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 instances failed: invalid JSON (%w)", err)
|
||||
}
|
||||
|
||||
if result.Code != 0 {
|
||||
return nil, fmt.Errorf("%s", result.Message)
|
||||
}
|
||||
|
||||
result.Duration = resp.Duration
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// ShowProviderInstance shows details of a specific instance
|
||||
// SHOW INSTANCE <name> FROM PROVIDER <name>
|
||||
func (c *RAGFlowClient) ShowProviderInstance(cmd *Command) (ResponseIf, error) {
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
instanceName, ok := cmd.Params["instance_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("instance name not provided")
|
||||
}
|
||||
|
||||
providerName, ok := cmd.Params["provider_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("provider name not provided")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/providers/%s/instances/%s", providerName, instanceName)
|
||||
|
||||
resp, err := c.HTTPClient.Request("GET", url, true, "web", nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to show instance: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to show instance: 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("show instance failed: invalid JSON (%w)", err)
|
||||
}
|
||||
|
||||
if result.Code != 0 {
|
||||
return nil, fmt.Errorf("%s", result.Message)
|
||||
}
|
||||
|
||||
result.Duration = resp.Duration
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// AlterProviderInstance renames a provider instance
|
||||
// ALTER INSTANCE <name> NAME <new_name> FROM PROVIDER <name>
|
||||
func (c *RAGFlowClient) AlterProviderInstance(cmd *Command) (ResponseIf, error) {
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
instanceName, ok := cmd.Params["instance_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("instance name not provided")
|
||||
}
|
||||
|
||||
newName, ok := cmd.Params["new_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("new name not provided")
|
||||
}
|
||||
|
||||
providerName, ok := cmd.Params["provider_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("provider name not provided")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/providers/%s/instances/%s", providerName, instanceName)
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"llm_name": newName,
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("PUT", url, true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to alter instance: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to alter instance: 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("alter instance failed: invalid JSON (%w)", err)
|
||||
}
|
||||
|
||||
if result.Code != 0 {
|
||||
return nil, fmt.Errorf("%s", result.Message)
|
||||
}
|
||||
|
||||
result.Duration = resp.Duration
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// DropProviderInstance deletes a provider instance
|
||||
// DROP INSTANCE <name> FROM PROVIDER <name>
|
||||
func (c *RAGFlowClient) DropProviderInstance(cmd *Command) (ResponseIf, error) {
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
instanceName, ok := cmd.Params["instance_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("instance name not provided")
|
||||
}
|
||||
|
||||
providerName, ok := cmd.Params["provider_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("provider name not provided")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/providers/%s/instances/%s", providerName, instanceName)
|
||||
|
||||
resp, err := c.HTTPClient.Request("DELETE", url, true, "web", nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to drop instance: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to drop instance: 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 instance failed: 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) ListInstanceModels(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")
|
||||
}
|
||||
instanceName, ok := cmd.Params["instance_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("instance_name not provided")
|
||||
}
|
||||
|
||||
var endPoint string
|
||||
endPoint = fmt.Sprintf("/providers/%s/instances/%s/models", providerName, instanceName)
|
||||
|
||||
resp, err := c.HTTPClient.Request("GET", endPoint, true, "web", nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list instance models: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to list instance models: 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("failed to list instance models: 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) EnableOrDisableModel(cmd *Command, status string) (ResponseIf, error) {
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
modelName, ok := cmd.Params["model_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("model name not provided")
|
||||
}
|
||||
|
||||
instanceName, ok := cmd.Params["instance_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("instance name not provided")
|
||||
}
|
||||
|
||||
providerName, ok := cmd.Params["provider_name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("provider name not provided")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/providers/%s/instances/%s/models/%s", providerName, instanceName, modelName)
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"status": status,
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("PUT", url, true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to enable/disable model: %w", err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to enable/disable 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("enable/disable model failed: 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) ChatToModel(cmd *Command) (ResponseIf, error) {
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
var providerName, instanceName, modelName string
|
||||
|
||||
// Check if model_name is provided in command
|
||||
if compositeModelName, ok := cmd.Params["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'")
|
||||
}
|
||||
providerName = names[0]
|
||||
instanceName = names[1]
|
||||
modelName = names[2]
|
||||
} else if c.CurrentModel != nil {
|
||||
// Use current model if set
|
||||
providerName = c.CurrentModel.Provider
|
||||
instanceName = c.CurrentModel.Instance
|
||||
modelName = c.CurrentModel.Model
|
||||
} else {
|
||||
return nil, fmt.Errorf("model name not provided and no current model set. Use 'use model' command first")
|
||||
}
|
||||
|
||||
message := cmd.Params["message"].(string)
|
||||
|
||||
url := fmt.Sprintf("/providers/%s/instances/%s/models/%s", providerName, instanceName, modelName)
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"message": message,
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("POST", url, true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to chat model: %w", err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to chat model: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
var result MessageResponse
|
||||
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
||||
return nil, fmt.Errorf("chat model failed: invalid JSON (%w)", err)
|
||||
}
|
||||
if result.Code != 0 {
|
||||
return nil, fmt.Errorf("%s", result.Message)
|
||||
}
|
||||
result.Duration = resp.Duration
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// UseModel sets the current model for chat
|
||||
func (c *RAGFlowClient) UseModel(cmd *Command) (ResponseIf, error) {
|
||||
if c.HTTPClient.APIToken == "" && c.HTTPClient.LoginToken == "" {
|
||||
return nil, fmt.Errorf("API token not set. Please login first")
|
||||
}
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
modelIdentifier, ok := cmd.Params["model_identifier"].(string)
|
||||
if !ok || modelIdentifier == "" {
|
||||
return nil, fmt.Errorf("model identifier not provided")
|
||||
}
|
||||
|
||||
names := strings.Split(modelIdentifier, "/")
|
||||
if len(names) != 3 {
|
||||
return nil, fmt.Errorf("model identifier must be in format 'provider/instance/model'")
|
||||
}
|
||||
|
||||
c.CurrentModel = &CurrentModel{
|
||||
Provider: names[0],
|
||||
Instance: names[1],
|
||||
Model: names[2],
|
||||
}
|
||||
|
||||
var result SimpleResponse
|
||||
result.Code = 0
|
||||
result.Message = fmt.Sprintf("Current model set to: %s/%s/%s", c.CurrentModel.Provider, c.CurrentModel.Instance, c.CurrentModel.Model)
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// ShowCurrentModel displays the current model configuration
|
||||
func (c *RAGFlowClient) ShowCurrentModel(cmd *Command) (ResponseIf, error) {
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
if c.CurrentModel == nil {
|
||||
return nil, fmt.Errorf("no current model set. Use 'use model' command first")
|
||||
}
|
||||
|
||||
var result CommonResponse
|
||||
result.Code = 0
|
||||
result.Data = []map[string]interface{}{
|
||||
{
|
||||
"provider": c.CurrentModel.Provider,
|
||||
"instance": c.CurrentModel.Instance,
|
||||
"model": c.CurrentModel.Model,
|
||||
},
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// Context related commands
|
||||
|
||||
// CEList handles the ls command - lists nodes using Context Engine
|
||||
@@ -947,7 +1348,6 @@ func (c *RAGFlowClient) InsertDatasetFromFile(cmd *Command) (ResponseIf, error)
|
||||
if c.ServerType != "user" {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
|
||||
filePath, ok := cmd.Params["file_path"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("file_path not provided")
|
||||
|
||||
@@ -3,6 +3,7 @@ package cli
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Command parsers
|
||||
@@ -170,6 +171,8 @@ func (p *Parser) parseListCommand() (*Command, error) {
|
||||
return p.parseListModelsOfProvider()
|
||||
case TokenProviders:
|
||||
return p.parseListProviders()
|
||||
case TokenInstances:
|
||||
return p.parseListInstances()
|
||||
case TokenDefault:
|
||||
return p.parseListDefaultModels()
|
||||
case TokenAvailable:
|
||||
@@ -348,15 +351,23 @@ func (p *Parser) parseShowCommand() (*Command, error) {
|
||||
return NewCommand("show_token"), nil
|
||||
case TokenCurrent:
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenUser {
|
||||
return nil, fmt.Errorf("expected USER after CURRENT")
|
||||
}
|
||||
p.nextToken()
|
||||
// Semicolon is optional for SHOW TOKEN
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
if p.curToken.Type == TokenUser {
|
||||
p.nextToken()
|
||||
// Semicolon is optional for SHOW CURRENT USER
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return NewCommand("show_current_user"), nil
|
||||
} else if p.curToken.Type == TokenModel {
|
||||
p.nextToken()
|
||||
// Semicolon is optional for SHOW CURRENT MODEL
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return NewCommand("show_current_model"), nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("expected USER or MODEL after CURRENT")
|
||||
}
|
||||
return NewCommand("show_current_user"), nil
|
||||
case TokenUser:
|
||||
return p.parseShowUser()
|
||||
case TokenRole:
|
||||
@@ -369,6 +380,8 @@ func (p *Parser) parseShowCommand() (*Command, error) {
|
||||
return p.parseShowProvider()
|
||||
case TokenModel:
|
||||
return p.parseShowModel()
|
||||
case TokenInstance:
|
||||
return p.parseShowInstance()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown SHOW target: %s", p.curToken.Value)
|
||||
}
|
||||
@@ -524,8 +537,6 @@ 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:
|
||||
@@ -534,11 +545,23 @@ func (p *Parser) parseCreateCommand() (*Command, error) {
|
||||
return p.parseCreateToken()
|
||||
case TokenIndex:
|
||||
return p.parseCreateIndex()
|
||||
case TokenProvider:
|
||||
return p.parseCreateProviderInstance()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown CREATE target: %s", p.curToken.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseAddCommand() (*Command, error) {
|
||||
p.nextToken() // consume ADD
|
||||
switch p.curToken.Type {
|
||||
case TokenProvider:
|
||||
return p.parseAddProvider()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown ADD target: %s", p.curToken.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseCreateToken() (*Command, error) {
|
||||
p.nextToken() // consume TOKEN
|
||||
|
||||
@@ -689,10 +712,10 @@ 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) {
|
||||
// parseAddProvider parses ADD PROVIDER commands
|
||||
// ADD PROVIDER <name>
|
||||
// ADD PROVIDER <name> <api_key>
|
||||
func (p *Parser) parseAddProvider() (*Command, error) {
|
||||
p.nextToken() // consume PROVIDER
|
||||
|
||||
providerName, err := p.parseQuotedString()
|
||||
@@ -700,7 +723,7 @@ func (p *Parser) parseCreateProvider() (*Command, error) {
|
||||
return nil, fmt.Errorf("expected provider name: %w", err)
|
||||
}
|
||||
|
||||
cmd := NewCommand("create_provider")
|
||||
cmd := NewCommand("add_provider")
|
||||
cmd.Params["provider_name"] = providerName
|
||||
|
||||
p.nextToken()
|
||||
@@ -804,8 +827,6 @@ 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:
|
||||
@@ -814,6 +835,19 @@ func (p *Parser) parseDropCommand() (*Command, error) {
|
||||
return p.parseDropToken()
|
||||
case TokenIndex:
|
||||
return p.parseDropIndex()
|
||||
case TokenInstance:
|
||||
return p.parseDropInstance()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown DROP target: %s", p.curToken.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseDeleteCommand() (*Command, error) {
|
||||
p.nextToken() // consume DELETE
|
||||
|
||||
switch p.curToken.Type {
|
||||
case TokenProvider:
|
||||
return p.parseDeleteProvider()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown DROP target: %s", p.curToken.Value)
|
||||
}
|
||||
@@ -949,8 +983,8 @@ func (p *Parser) parseDropModelProvider() (*Command, error) {
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseDropProvider parses DROP PROVIDER <name> command
|
||||
func (p *Parser) parseDropProvider() (*Command, error) {
|
||||
// parseDeleteProvider parses DELETE PROVIDER <name> command
|
||||
func (p *Parser) parseDeleteProvider() (*Command, error) {
|
||||
p.nextToken() // consume PROVIDER
|
||||
|
||||
providerName, err := p.parseQuotedString()
|
||||
@@ -958,7 +992,7 @@ func (p *Parser) parseDropProvider() (*Command, error) {
|
||||
return nil, fmt.Errorf("expected provider name: %w", err)
|
||||
}
|
||||
|
||||
cmd := NewCommand("drop_provider")
|
||||
cmd := NewCommand("delete_provider")
|
||||
cmd.Params["provider_name"] = providerName
|
||||
|
||||
p.nextToken()
|
||||
@@ -1015,6 +1049,8 @@ func (p *Parser) parseAlterCommand() (*Command, error) {
|
||||
return p.parseAlterRole()
|
||||
case TokenProvider:
|
||||
return p.parseAlterProvider()
|
||||
case TokenInstance:
|
||||
return p.parseAlterInstance()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown ALTER target: %s", p.curToken.Value)
|
||||
}
|
||||
@@ -1176,6 +1212,189 @@ func (p *Parser) parseAlterProvider() (*Command, error) {
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseCreateProviderInstance parses CREATE PROVIDER <name> INSTANCE <instance_name> <api_key> command
|
||||
// instance_name cannot be "default"
|
||||
func (p *Parser) parseCreateProviderInstance() (*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 != TokenInstance {
|
||||
return nil, fmt.Errorf("expected INSTANCE after provider name")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
instanceName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected instance name: %w", err)
|
||||
}
|
||||
|
||||
// Check if instance_name is "default"
|
||||
if instanceName == "default" {
|
||||
return nil, fmt.Errorf("instance name cannot be 'default'")
|
||||
}
|
||||
|
||||
p.nextToken()
|
||||
apiKey, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected API key: %w", err)
|
||||
}
|
||||
|
||||
cmd := NewCommand("create_provider_instance")
|
||||
cmd.Params["provider_name"] = providerName
|
||||
cmd.Params["instance_name"] = instanceName
|
||||
cmd.Params["api_key"] = apiKey
|
||||
|
||||
p.nextToken()
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseListInstances parses LIST INSTANCES FROM PROVIDER <name> command
|
||||
func (p *Parser) parseListInstances() (*Command, error) {
|
||||
p.nextToken() // consume INSTANCES
|
||||
|
||||
if p.curToken.Type != TokenFrom {
|
||||
return nil, fmt.Errorf("expected FROM")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
providerName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err)
|
||||
}
|
||||
|
||||
cmd := NewCommand("list_provider_instances")
|
||||
cmd.Params["provider_name"] = providerName
|
||||
|
||||
p.nextToken()
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseShowInstance parses SHOW INSTANCE <name> FROM PROVIDER <name> command
|
||||
func (p *Parser) parseShowInstance() (*Command, error) {
|
||||
p.nextToken() // consume INSTANCE
|
||||
|
||||
instanceName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected instance name: %w", err)
|
||||
}
|
||||
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenFrom {
|
||||
return nil, fmt.Errorf("expected FROM")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
providerName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err)
|
||||
}
|
||||
|
||||
cmd := NewCommand("show_provider_instance")
|
||||
cmd.Params["instance_name"] = instanceName
|
||||
cmd.Params["provider_name"] = providerName
|
||||
|
||||
p.nextToken()
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseAlterInstance parses ALTER INSTANCE <name> NAME <new_name> FROM PROVIDER <name> command
|
||||
func (p *Parser) parseAlterInstance() (*Command, error) {
|
||||
p.nextToken() // consume INSTANCE
|
||||
|
||||
instanceName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected instance 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 instance name: %w", err)
|
||||
}
|
||||
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenFrom {
|
||||
return nil, fmt.Errorf("expected FROM")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
if p.curToken.Type != TokenProvider {
|
||||
return nil, fmt.Errorf("expected PROVIDER after FROM")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
providerName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err)
|
||||
}
|
||||
|
||||
cmd := NewCommand("alter_provider_instance")
|
||||
cmd.Params["instance_name"] = instanceName
|
||||
cmd.Params["new_name"] = newName
|
||||
cmd.Params["provider_name"] = providerName
|
||||
|
||||
p.nextToken()
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseDropInstance parses DROP INSTANCE <name> FROM PROVIDER <name> command
|
||||
func (p *Parser) parseDropInstance() (*Command, error) {
|
||||
p.nextToken() // consume INSTANCE
|
||||
|
||||
instanceName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected instance name: %w", err)
|
||||
}
|
||||
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenFrom {
|
||||
return nil, fmt.Errorf("expected FROM")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
providerName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err)
|
||||
}
|
||||
|
||||
cmd := NewCommand("drop_provider_instance")
|
||||
cmd.Params["instance_name"] = instanceName
|
||||
cmd.Params["provider_name"] = providerName
|
||||
|
||||
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
|
||||
|
||||
@@ -1662,6 +1881,215 @@ func (p *Parser) parseSearchCommand() (*Command, error) {
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
// Parse first quoted string (could be instance_name or provider_name)
|
||||
firstName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Check if there's a second quoted string (provider_name)
|
||||
// If so, format is: LIST MODELS FROM <instance_name> <provider_name>
|
||||
// If not, format is: LIST MODELS FROM <provider_name>
|
||||
if p.curToken.Type == TokenQuotedString {
|
||||
// Two arguments: instance_name and provider_name
|
||||
instanceName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd := NewCommand("list_instance_models")
|
||||
cmd.Params["instance_name"] = instanceName
|
||||
cmd.Params["provider_name"] = firstName
|
||||
p.nextToken()
|
||||
// Semicolon is optional for UNSET TOKEN
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// Only one argument: provider_name
|
||||
cmd := NewCommand("list_provider_models")
|
||||
cmd.Params["provider_name"] = firstName
|
||||
// Semicolon is optional for UNSET TOKEN
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseEnableCommand() (*Command, error) {
|
||||
p.nextToken() // consume ENABLE
|
||||
|
||||
if p.curToken.Type != TokenModel {
|
||||
return nil, fmt.Errorf("expected MODEL")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
modelName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
if p.curToken.Type != TokenFrom {
|
||||
return nil, fmt.Errorf("expected FROM")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
modelProvider, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
modelInstance, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Semicolon is optional for UNSET TOKEN
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
cmd := NewCommand("enable_model")
|
||||
cmd.Params["model_name"] = modelName
|
||||
cmd.Params["instance_name"] = modelInstance
|
||||
cmd.Params["provider_name"] = modelProvider
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseDisableCommand() (*Command, error) {
|
||||
p.nextToken() // consume DISABLE
|
||||
|
||||
if p.curToken.Type != TokenModel {
|
||||
return nil, fmt.Errorf("expected MODEL")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
modelName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
if p.curToken.Type != TokenFrom {
|
||||
return nil, fmt.Errorf("expected FROM")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
modelProvider, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
modelInstance, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Semicolon is optional for UNSET TOKEN
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
cmd := NewCommand("disable_model")
|
||||
cmd.Params["model_name"] = modelName
|
||||
cmd.Params["instance_name"] = modelInstance
|
||||
cmd.Params["provider_name"] = modelProvider
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseChatCommand() (*Command, error) {
|
||||
p.nextToken() // consume CHAT
|
||||
|
||||
var modelName string
|
||||
var message string
|
||||
|
||||
// Check if we have a quoted string that looks like a model identifier (contains two slashes)
|
||||
// Format: 'provider/instance/model' or just 'message'
|
||||
if p.curToken.Type == TokenQuotedString {
|
||||
firstArg := p.curToken.Value
|
||||
|
||||
// Check if it looks like a model identifier (contains exactly 2 slashes)
|
||||
slashCount := strings.Count(firstArg, "/")
|
||||
if slashCount == 2 {
|
||||
// This is likely a model identifier, expect another quoted string for message
|
||||
modelName = firstArg
|
||||
p.nextToken()
|
||||
|
||||
// After model name, expect message
|
||||
if p.curToken.Type != TokenQuotedString {
|
||||
return nil, fmt.Errorf("expected message after model name")
|
||||
}
|
||||
message = p.curToken.Value
|
||||
p.nextToken()
|
||||
} else {
|
||||
// This is just a message, use current model
|
||||
message = firstArg
|
||||
p.nextToken()
|
||||
}
|
||||
} else if p.curToken.Type == TokenIdentifier {
|
||||
// Context engine style: chat <message>
|
||||
message = p.curToken.Value
|
||||
p.nextToken()
|
||||
} else {
|
||||
return nil, fmt.Errorf("expected model name (quoted string) or message")
|
||||
}
|
||||
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
cmd := NewCommand("chat_to_model")
|
||||
if modelName != "" {
|
||||
cmd.Params["model_name"] = modelName
|
||||
}
|
||||
cmd.Params["message"] = message
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseUseCommand() (*Command, error) {
|
||||
p.nextToken() // consume USE
|
||||
|
||||
if p.curToken.Type != TokenModel {
|
||||
return nil, fmt.Errorf("expected MODEL after USE")
|
||||
}
|
||||
p.nextToken() // consume MODEL
|
||||
|
||||
// Parse model identifier in format 'provider/instance/model'
|
||||
modelIdentifier, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected model identifier in format 'provider/instance/model': %w", err)
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
cmd := NewCommand("use_model")
|
||||
cmd.Params["model_identifier"] = modelIdentifier
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseParseCommand() (*Command, error) {
|
||||
p.nextToken() // consume PARSE
|
||||
|
||||
@@ -1788,6 +2216,7 @@ func (p *Parser) parseUserStatement() (*Command, error) {
|
||||
return p.parseInsertCommand()
|
||||
case TokenSearch:
|
||||
return p.parseSearchCommand()
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid user statement: %s", p.curToken.Value)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user