mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 23:41:12 +08:00
Refactor context command (#13948)
### What problem does this PR solve? As title ### Type of change - [x] Refactoring --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
@@ -40,7 +40,7 @@ func main() {
|
||||
}()
|
||||
|
||||
// Check if we have a single command to execute
|
||||
if args.Command != "" {
|
||||
if args.Command != nil {
|
||||
// Single command mode
|
||||
if err = cliApp.RunSingleCommand(args.Command); err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/peterh/liner"
|
||||
"golang.org/x/term"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"ragflow/internal/cli/contextengine"
|
||||
@@ -59,7 +58,7 @@ type ConnectionArgs struct {
|
||||
Password string
|
||||
APIToken string
|
||||
UserName string
|
||||
Command string // Original command string (for SQL mode)
|
||||
Command *string // Original command string (for SQL mode)
|
||||
CommandArgs []string // Split command arguments (for ContextEngine mode)
|
||||
IsSQLMode bool // true=SQL mode (quoted), false=ContextEngine mode (unquoted)
|
||||
ShowHelp bool
|
||||
@@ -304,22 +303,12 @@ func ParseConnectionArgs(args []string) (*ConnectionArgs, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get command from remaining args (non-flag arguments)
|
||||
// Get command from remaining args (non-flag arguments)
|
||||
if len(nonFlagArgs) > 0 {
|
||||
// Check if this is SQL mode or ContextEngine mode
|
||||
// SQL mode: single argument that looks like SQL (e.g., "LIST DATASETS")
|
||||
// ContextEngine mode: multiple arguments (e.g., "ls", "datasets")
|
||||
if len(nonFlagArgs) == 1 && looksLikeSQL(nonFlagArgs[0]) {
|
||||
// SQL mode: single argument that looks like SQL
|
||||
result.IsSQLMode = true
|
||||
result.Command = nonFlagArgs[0]
|
||||
} else {
|
||||
// ContextEngine mode: multiple arguments
|
||||
result.IsSQLMode = false
|
||||
result.CommandArgs = nonFlagArgs
|
||||
// Also store joined version for backward compatibility
|
||||
result.Command = strings.Join(nonFlagArgs, " ")
|
||||
}
|
||||
command := strings.Join(nonFlagArgs, " ")
|
||||
result.Command = &command
|
||||
fmt.Printf("COMMAND: %s\n", command)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@@ -485,17 +474,9 @@ func (c *CLI) Run() error {
|
||||
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
||||
fmt.Print("Please input your password: ")
|
||||
|
||||
passwordBytes, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||||
fmt.Println()
|
||||
password, err := ReadPassword()
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading password: %v\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
input := strings.TrimSpace(string(passwordBytes))
|
||||
|
||||
if input == "" {
|
||||
if password == "" {
|
||||
if attempt < maxAttempts {
|
||||
fmt.Println("Password cannot be empty, please try again")
|
||||
continue
|
||||
@@ -503,7 +484,7 @@ func (c *CLI) Run() error {
|
||||
return errors.New("no password provided after 3 attempts")
|
||||
}
|
||||
|
||||
c.args.Password = input
|
||||
c.args.Password = password
|
||||
|
||||
if err = c.VerifyAuth(); err != nil {
|
||||
if attempt < maxAttempts {
|
||||
@@ -557,7 +538,7 @@ func (c *CLI) Run() error {
|
||||
c.line.AppendHistory(input)
|
||||
}
|
||||
|
||||
if err = c.execute(input); err != nil {
|
||||
if err = c.executeNew(input); err != nil {
|
||||
fmt.Printf("CLI error: %v\n", err)
|
||||
}
|
||||
}
|
||||
@@ -565,6 +546,31 @@ func (c *CLI) Run() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CLI) executeNew(input string) error {
|
||||
p := NewParser(input)
|
||||
cmd, err := p.Parse(c.args.AdminMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle meta commands
|
||||
if cmd.Type == "meta" {
|
||||
return c.handleMetaCommand(cmd)
|
||||
}
|
||||
|
||||
// Execute the command using the client
|
||||
var result ResponseIf
|
||||
result, err = c.client.ExecuteCommand(cmd)
|
||||
if result != nil {
|
||||
result.PrintOut()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *CLI) execute(input string) error {
|
||||
// Determine execution mode based on input and args
|
||||
input = strings.TrimSpace(input)
|
||||
@@ -699,9 +705,9 @@ func (c *CLI) executeContextEngine(input string) error {
|
||||
fmt.Println("(empty file)")
|
||||
} else if isBinaryContent(content) {
|
||||
return fmt.Errorf("cannot display binary file content")
|
||||
} else {
|
||||
fmt.Println(string(content))
|
||||
}
|
||||
|
||||
fmt.Println(string(content))
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unknown context engine command: %s", cmdType)
|
||||
@@ -1068,12 +1074,12 @@ func RunInteractive() error {
|
||||
}
|
||||
|
||||
// RunSingleCommand executes a single command and exits
|
||||
func (c *CLI) RunSingleCommand(command string) error {
|
||||
func (c *CLI) RunSingleCommand(command *string) error {
|
||||
// Ensure cleanup is called on exit to restore terminal settings
|
||||
defer c.Cleanup()
|
||||
|
||||
// Execute the command
|
||||
if err := c.execute(command); err != nil {
|
||||
if err := c.executeNew(*command); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -254,6 +254,12 @@ func (c *RAGFlowClient) ExecuteUserCommand(cmd *Command) (ResponseIf, error) {
|
||||
case "show_current_model":
|
||||
return c.ShowCurrentModel(cmd)
|
||||
// ContextEngine commands
|
||||
case "context_list":
|
||||
return c.ContextList(cmd)
|
||||
case "context_cat":
|
||||
return c.ContextCat(cmd)
|
||||
case "context_search":
|
||||
return c.ContextSearch(cmd)
|
||||
case "ce_ls":
|
||||
return c.CEList(cmd)
|
||||
case "ce_search":
|
||||
|
||||
@@ -73,7 +73,7 @@ func (c *RAGFlowClient) LoginUserInteractive(username, password string) error {
|
||||
if password == "" {
|
||||
fmt.Printf("password for %s: ", username)
|
||||
var err error
|
||||
password, err = readPassword()
|
||||
password, err = ReadPassword()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read password: %w", err)
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func (c *RAGFlowClient) LoginUser(cmd *Command) error {
|
||||
if !ok {
|
||||
// Get password from user input (hidden)
|
||||
fmt.Printf("password for %s: ", email)
|
||||
password, err = readPassword()
|
||||
password, err = ReadPassword()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read password: %w", err)
|
||||
}
|
||||
@@ -374,9 +374,9 @@ func (c *RAGFlowClient) ShowModel(cmd *Command) (ResponseIf, error) {
|
||||
}
|
||||
|
||||
// readPassword reads password from terminal without echoing
|
||||
func readPassword() (string, error) {
|
||||
func ReadPassword() (string, error) {
|
||||
if !term.IsTerminal(int(os.Stdin.Fd())) {
|
||||
return readPasswordFallback()
|
||||
return ReadPasswordFallback()
|
||||
}
|
||||
|
||||
fmt.Print("Password: ")
|
||||
@@ -391,7 +391,7 @@ func readPassword() (string, error) {
|
||||
}
|
||||
|
||||
// readPasswordFallback reads password as plain text (fallback mode)
|
||||
func readPasswordFallback() (string, error) {
|
||||
func ReadPasswordFallback() (string, error) {
|
||||
fmt.Print("Password (will be visible): ")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
password, err := reader.ReadString('\n')
|
||||
|
||||
135
internal/cli/context_command.go
Normal file
135
internal/cli/context_command.go
Normal file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// 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"
|
||||
)
|
||||
|
||||
func (c *RAGFlowClient) ContextList(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")
|
||||
}
|
||||
|
||||
var path string
|
||||
var ok bool
|
||||
if cmd.Params["path"] != nil {
|
||||
path, ok = cmd.Params["path"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("fail to convert 'path' to string")
|
||||
}
|
||||
}
|
||||
|
||||
if path == "" {
|
||||
path = "."
|
||||
}
|
||||
|
||||
var parameter string
|
||||
if cmd.Params["parameter"] != nil {
|
||||
parameter, ok = cmd.Params["parameter"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("fail to convert 'parameter' to string")
|
||||
}
|
||||
}
|
||||
|
||||
if parameter == "" {
|
||||
fmt.Printf("ls %s\n", path)
|
||||
} else {
|
||||
fmt.Printf("ls %s -%s\n", path, parameter)
|
||||
}
|
||||
|
||||
// Convert to response
|
||||
var response ContextListResponse
|
||||
response.OutputFormat = c.OutputFormat
|
||||
response.Code = 0
|
||||
response.Data = nil
|
||||
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
func (c *RAGFlowClient) ContextCat(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")
|
||||
}
|
||||
|
||||
path, ok := cmd.Params["filename"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("fail to convert 'filename' to string")
|
||||
}
|
||||
|
||||
fmt.Printf("cat %s\n", path)
|
||||
|
||||
// Convert to response
|
||||
var response ContextListResponse
|
||||
response.OutputFormat = c.OutputFormat
|
||||
response.Code = 0
|
||||
response.Data = nil
|
||||
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
func (c *RAGFlowClient) ContextSearch(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")
|
||||
}
|
||||
|
||||
path, ok := cmd.Params["path"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("fail to convert 'path' to string")
|
||||
}
|
||||
|
||||
query, ok := cmd.Params["query"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("fail to convert 'parameter' to float64")
|
||||
}
|
||||
|
||||
number := 10
|
||||
if cmd.Params["number"] != nil {
|
||||
number, ok = cmd.Params["number"].(int)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("fail to convert 'number' to int")
|
||||
}
|
||||
}
|
||||
|
||||
threshold := 0.0
|
||||
if cmd.Params["threshold"] != nil {
|
||||
threshold, ok = cmd.Params["threshold"].(float64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("fail to convert 'threshold' to float64")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("search query: %s, path: %s, threshold: %f, number: %d\n", query, path, threshold, number)
|
||||
|
||||
// Convert to response
|
||||
var response ContextSearchResponse
|
||||
response.OutputFormat = c.OutputFormat
|
||||
response.Code = 0
|
||||
response.Total = 0
|
||||
response.Data = nil
|
||||
|
||||
return &response, nil
|
||||
}
|
||||
@@ -72,6 +72,12 @@ func (l *Lexer) NextToken() Token {
|
||||
case ',':
|
||||
tok = newToken(TokenComma, l.ch)
|
||||
l.readChar()
|
||||
case '/':
|
||||
tok = newToken(TokenSlash, l.ch)
|
||||
l.readChar()
|
||||
case '-':
|
||||
tok = newToken(TokenDash, l.ch)
|
||||
l.readChar()
|
||||
case '\'':
|
||||
tok.Type = TokenQuotedString
|
||||
tok.Value = l.readQuotedString('\'')
|
||||
@@ -93,10 +99,10 @@ func (l *Lexer) NextToken() Token {
|
||||
tok.Type = TokenNumber
|
||||
tok.Value = l.readNumber()
|
||||
return tok
|
||||
} else {
|
||||
tok = newToken(TokenIllegal, l.ch)
|
||||
l.readChar()
|
||||
}
|
||||
|
||||
tok = newToken(TokenIllegal, l.ch)
|
||||
l.readChar()
|
||||
}
|
||||
|
||||
return tok
|
||||
@@ -257,6 +263,10 @@ func (l *Lexer) lookupIdent(ident string) Token {
|
||||
return Token{Type: TokenChat, Value: ident}
|
||||
case "THINK":
|
||||
return Token{Type: TokenThink, Value: ident}
|
||||
case "LS":
|
||||
return Token{Type: TokenLS, Value: ident}
|
||||
case "CAT":
|
||||
return Token{Type: TokenCat, Value: ident}
|
||||
case "FILES":
|
||||
return Token{Type: TokenFiles, Value: ident}
|
||||
case "AS":
|
||||
|
||||
@@ -18,6 +18,7 @@ package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -56,12 +57,11 @@ func (p *Parser) Parse(adminCommand bool) (*Command, error) {
|
||||
}
|
||||
|
||||
// Check for ContextEngine commands (ls, cat, search)
|
||||
if p.curToken.Type == TokenIdentifier && isCECommand(p.curToken.Value) {
|
||||
return p.parseCECommand()
|
||||
}
|
||||
//if p.curToken.Type == TokenIdentifier && isCECommand(p.curToken.Value) {
|
||||
// return p.parseCECommand()
|
||||
//}
|
||||
|
||||
// Parse SQL-like command
|
||||
return p.parseSQLCommand(adminCommand)
|
||||
return p.parseCommand(adminCommand)
|
||||
}
|
||||
|
||||
func (p *Parser) parseMetaCommand() (*Command, error) {
|
||||
@@ -194,6 +194,10 @@ func (p *Parser) parseUserCommand() (*Command, error) {
|
||||
return p.parseChatCommand()
|
||||
case TokenThink:
|
||||
return p.parseThinkCommand()
|
||||
case TokenLS:
|
||||
return p.parseContextListCommand()
|
||||
case TokenCat:
|
||||
return p.parseContextCatCommand()
|
||||
case TokenUse:
|
||||
return p.parseUseCommand()
|
||||
case TokenUpdate:
|
||||
@@ -205,7 +209,7 @@ func (p *Parser) parseUserCommand() (*Command, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseSQLCommand(adminCommand bool) (*Command, error) {
|
||||
func (p *Parser) parseCommand(adminCommand bool) (*Command, error) {
|
||||
if p.curToken.Type != TokenIdentifier && !isKeyword(p.curToken.Type) {
|
||||
return nil, fmt.Errorf("expected command, got %s", p.curToken.Value)
|
||||
}
|
||||
@@ -272,6 +276,18 @@ func (p *Parser) parseNumber() (int, error) {
|
||||
return strconv.Atoi(p.curToken.Value)
|
||||
}
|
||||
|
||||
func (p *Parser) parseFloat() (float64, error) {
|
||||
if p.curToken.Type != TokenNumber {
|
||||
return math.NaN(), fmt.Errorf("expected number, got %s", p.curToken.Value)
|
||||
}
|
||||
result, err := strconv.ParseFloat(p.curToken.Value, 64)
|
||||
if err != nil {
|
||||
return math.NaN(), err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func tokenTypeToString(t int) string {
|
||||
// Simplified for error messages
|
||||
return fmt.Sprintf("token(%d)", t)
|
||||
|
||||
@@ -30,7 +30,7 @@ type CommonResponse struct {
|
||||
Data []map[string]interface{} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *CommonResponse) Type() string {
|
||||
@@ -42,12 +42,12 @@ func (r *CommonResponse) TimeCost() float64 {
|
||||
}
|
||||
|
||||
func (r *CommonResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
r.OutputFormat = format
|
||||
}
|
||||
|
||||
func (r *CommonResponse) PrintOut() {
|
||||
if r.Code == 0 {
|
||||
PrintTableSimpleByFormat(r.Data, r.outputFormat)
|
||||
PrintTableSimpleByFormat(r.Data, r.OutputFormat)
|
||||
} else {
|
||||
fmt.Println("ERROR")
|
||||
fmt.Printf("%d, %s\n", r.Code, r.Message)
|
||||
@@ -59,7 +59,7 @@ type CommonDataResponse struct {
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *CommonDataResponse) Type() string {
|
||||
@@ -71,14 +71,14 @@ func (r *CommonDataResponse) TimeCost() float64 {
|
||||
}
|
||||
|
||||
func (r *CommonDataResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
r.OutputFormat = format
|
||||
}
|
||||
|
||||
func (r *CommonDataResponse) PrintOut() {
|
||||
if r.Code == 0 {
|
||||
table := make([]map[string]interface{}, 0)
|
||||
table = append(table, r.Data)
|
||||
PrintTableSimpleByFormat(table, r.outputFormat)
|
||||
PrintTableSimpleByFormat(table, r.OutputFormat)
|
||||
} else {
|
||||
fmt.Println("ERROR")
|
||||
fmt.Printf("%d, %s\n", r.Code, r.Message)
|
||||
@@ -89,7 +89,7 @@ type SimpleResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *SimpleResponse) Type() string {
|
||||
@@ -101,7 +101,7 @@ func (r *SimpleResponse) TimeCost() float64 {
|
||||
}
|
||||
|
||||
func (r *SimpleResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
r.OutputFormat = format
|
||||
}
|
||||
|
||||
func (r *SimpleResponse) PrintOut() {
|
||||
@@ -117,7 +117,7 @@ type MessageResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *MessageResponse) Type() string {
|
||||
@@ -129,7 +129,7 @@ func (r *MessageResponse) TimeCost() float64 {
|
||||
}
|
||||
|
||||
func (r *MessageResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
r.OutputFormat = format
|
||||
}
|
||||
|
||||
func (r *MessageResponse) PrintOut() {
|
||||
@@ -145,7 +145,7 @@ type StreamMessageResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *StreamMessageResponse) Type() string {
|
||||
@@ -157,7 +157,7 @@ func (r *StreamMessageResponse) TimeCost() float64 {
|
||||
}
|
||||
|
||||
func (r *StreamMessageResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
r.OutputFormat = format
|
||||
}
|
||||
|
||||
func (r *StreamMessageResponse) PrintOut() {
|
||||
@@ -171,7 +171,7 @@ type RegisterResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *RegisterResponse) Type() string {
|
||||
@@ -183,7 +183,7 @@ func (r *RegisterResponse) TimeCost() float64 {
|
||||
}
|
||||
|
||||
func (r *RegisterResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
r.OutputFormat = format
|
||||
}
|
||||
|
||||
func (r *RegisterResponse) PrintOut() {
|
||||
@@ -201,7 +201,7 @@ type BenchmarkResponse struct {
|
||||
SuccessCount int `json:"success_count"`
|
||||
FailureCount int `json:"failure_count"`
|
||||
Concurrency int
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *BenchmarkResponse) Type() string {
|
||||
@@ -209,7 +209,7 @@ func (r *BenchmarkResponse) Type() string {
|
||||
}
|
||||
|
||||
func (r *BenchmarkResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
r.OutputFormat = format
|
||||
}
|
||||
|
||||
func (r *BenchmarkResponse) PrintOut() {
|
||||
@@ -239,7 +239,7 @@ type KeyValueResponse struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"data"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *KeyValueResponse) Type() string {
|
||||
@@ -251,7 +251,7 @@ func (r *KeyValueResponse) TimeCost() float64 {
|
||||
}
|
||||
|
||||
func (r *KeyValueResponse) SetOutputFormat(format OutputFormat) {
|
||||
r.outputFormat = format
|
||||
r.OutputFormat = format
|
||||
}
|
||||
|
||||
func (r *KeyValueResponse) PrintOut() {
|
||||
@@ -262,7 +262,7 @@ func (r *KeyValueResponse) PrintOut() {
|
||||
"key": r.Key,
|
||||
"value": r.Value,
|
||||
})
|
||||
PrintTableSimpleByFormat(table, r.outputFormat)
|
||||
PrintTableSimpleByFormat(table, r.OutputFormat)
|
||||
} else {
|
||||
fmt.Println("ERROR")
|
||||
fmt.Printf("%d\n", r.Code)
|
||||
@@ -271,44 +271,44 @@ func (r *KeyValueResponse) PrintOut() {
|
||||
|
||||
// ==================== ContextEngine Commands ====================
|
||||
|
||||
// CEListResponse represents the response for ls command
|
||||
type CEListResponse struct {
|
||||
// ContextListResponse represents the response for ls command
|
||||
type ContextListResponse struct {
|
||||
Code int `json:"code"`
|
||||
Data []map[string]interface{} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *CEListResponse) Type() string { return "ce_ls" }
|
||||
func (r *CEListResponse) TimeCost() float64 { return r.Duration }
|
||||
func (r *CEListResponse) SetOutputFormat(format OutputFormat) { r.outputFormat = format }
|
||||
func (r *CEListResponse) PrintOut() {
|
||||
func (r *ContextListResponse) Type() string { return "ce_ls" }
|
||||
func (r *ContextListResponse) TimeCost() float64 { return r.Duration }
|
||||
func (r *ContextListResponse) SetOutputFormat(format OutputFormat) { r.OutputFormat = format }
|
||||
func (r *ContextListResponse) PrintOut() {
|
||||
if r.Code == 0 {
|
||||
PrintTableSimpleByFormat(r.Data, r.outputFormat)
|
||||
PrintTableSimpleByFormat(r.Data, r.OutputFormat)
|
||||
} else {
|
||||
fmt.Println("ERROR")
|
||||
fmt.Printf("%d, %s\n", r.Code, r.Message)
|
||||
}
|
||||
}
|
||||
|
||||
// CESearchResponse represents the response for search command
|
||||
type CESearchResponse struct {
|
||||
// ContextSearchResponse represents the response for search command
|
||||
type ContextSearchResponse struct {
|
||||
Code int `json:"code"`
|
||||
Data []map[string]interface{} `json:"data"`
|
||||
Total int `json:"total"`
|
||||
Message string `json:"message"`
|
||||
Duration float64
|
||||
outputFormat OutputFormat
|
||||
OutputFormat OutputFormat
|
||||
}
|
||||
|
||||
func (r *CESearchResponse) Type() string { return "ce_search" }
|
||||
func (r *CESearchResponse) TimeCost() float64 { return r.Duration }
|
||||
func (r *CESearchResponse) SetOutputFormat(format OutputFormat) { r.outputFormat = format }
|
||||
func (r *CESearchResponse) PrintOut() {
|
||||
func (r *ContextSearchResponse) Type() string { return "ce_search" }
|
||||
func (r *ContextSearchResponse) TimeCost() float64 { return r.Duration }
|
||||
func (r *ContextSearchResponse) SetOutputFormat(format OutputFormat) { r.OutputFormat = format }
|
||||
func (r *ContextSearchResponse) PrintOut() {
|
||||
if r.Code == 0 {
|
||||
fmt.Printf("Found %d results:\n", r.Total)
|
||||
PrintTableSimpleByFormat(r.Data, r.outputFormat)
|
||||
PrintTableSimpleByFormat(r.Data, r.OutputFormat)
|
||||
} else {
|
||||
fmt.Println("ERROR")
|
||||
fmt.Printf("%d, %s\n", r.Code, r.Message)
|
||||
|
||||
@@ -112,6 +112,8 @@ const (
|
||||
TokenEnable
|
||||
TokenUse
|
||||
TokenThink
|
||||
TokenLS
|
||||
TokenCat
|
||||
TokenInsert
|
||||
TokenFile
|
||||
TokenMetadata
|
||||
@@ -129,7 +131,9 @@ const (
|
||||
// Special
|
||||
TokenSemicolon
|
||||
TokenComma
|
||||
TokenSlash
|
||||
TokenEOF
|
||||
TokenDash
|
||||
TokenIllegal
|
||||
)
|
||||
|
||||
|
||||
@@ -1346,8 +1346,8 @@ func (c *RAGFlowClient) CEList(cmd *Command) (ResponseIf, error) {
|
||||
}
|
||||
|
||||
// Convert to response
|
||||
var response CEListResponse
|
||||
response.outputFormat = c.OutputFormat
|
||||
var response ContextListResponse
|
||||
response.OutputFormat = c.OutputFormat
|
||||
response.Code = 0
|
||||
response.Data = ce.FormatNodes(result.Nodes, string(c.OutputFormat))
|
||||
|
||||
@@ -1385,8 +1385,8 @@ func (c *RAGFlowClient) CESearch(cmd *Command) (ResponseIf, error) {
|
||||
}
|
||||
|
||||
// Convert to response
|
||||
var response CESearchResponse
|
||||
response.outputFormat = c.OutputFormat
|
||||
var response ContextSearchResponse
|
||||
response.OutputFormat = c.OutputFormat
|
||||
response.Code = 0
|
||||
response.Total = result.Total
|
||||
response.Data = ce.FormatNodes(result.Nodes, string(c.OutputFormat))
|
||||
|
||||
@@ -1863,30 +1863,88 @@ func (p *Parser) parseSearchCommand() (*Command, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenOn {
|
||||
return nil, fmt.Errorf("expected ON")
|
||||
}
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenDatasets {
|
||||
return nil, fmt.Errorf("expected DATASETS")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
datasets, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.curToken.Type == TokenOn {
|
||||
p.nextToken() // skip on
|
||||
|
||||
cmd := NewCommand("search_on_datasets")
|
||||
cmd.Params["question"] = question
|
||||
cmd.Params["datasets"] = datasets
|
||||
|
||||
p.nextToken()
|
||||
// Semicolon is optional for UNSET TOKEN
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
if p.curToken.Type != TokenDatasets {
|
||||
return nil, fmt.Errorf("expected DATASETS")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
datasets, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := NewCommand("search_on_datasets")
|
||||
cmd.Params["question"] = question
|
||||
cmd.Params["datasets"] = datasets
|
||||
|
||||
p.nextToken()
|
||||
// Semicolon is optional for UNSET TOKEN
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
cmd := NewCommand("context_search")
|
||||
|
||||
cmd.Params["query"] = question
|
||||
|
||||
if p.curToken.Type == TokenEOF {
|
||||
cmd.Params["path"] = "."
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
for p.curToken.Type != TokenEOF {
|
||||
if p.curToken.Type == TokenDash {
|
||||
p.nextToken() // skip dash
|
||||
if p.curToken.Type != TokenIdentifier {
|
||||
return nil, fmt.Errorf("expect identifier")
|
||||
}
|
||||
|
||||
if strings.ToLower(p.curToken.Value) == "n" {
|
||||
p.nextToken()
|
||||
var err error
|
||||
if p.curToken.Type != TokenNumber {
|
||||
return nil, fmt.Errorf("expect number")
|
||||
}
|
||||
cmd.Params["number"], err = p.parseNumber()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.ToLower(p.curToken.Value) == "t" {
|
||||
p.nextToken()
|
||||
var err error
|
||||
if p.curToken.Type != TokenNumber {
|
||||
return nil, fmt.Errorf("expect number")
|
||||
}
|
||||
cmd.Params["threshold"], err = p.parseFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.nextToken()
|
||||
continue
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknow parameter: %s", p.curToken.Value)
|
||||
} else if p.curToken.Type == TokenIdentifier {
|
||||
if cmd.Params["path"] == nil {
|
||||
cmd.Params["path"] = p.curToken.Value
|
||||
} else {
|
||||
cmd.Params["path"] = fmt.Sprintf("%s %s", cmd.Params["path"], p.curToken.Value)
|
||||
}
|
||||
p.nextToken() // skip path
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("syntax error")
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user