mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-14 08:58:27 +08:00
Go: add stream / think chat (#14242)
### What problem does this PR solve? 1. Supports stream and non-stream chat 2. Supports think and non-think chat 3. List supported models from DeepSeek service. (This command can be used to verify the API validity) ### 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:
@@ -1436,83 +1436,106 @@ func (c *RAGFlowClient) ChatToModel(cmd *Command) (ResponseIf, error) {
|
||||
}
|
||||
|
||||
message := cmd.Params["message"].(string)
|
||||
reasoning := cmd.Params["reasoning"].(bool)
|
||||
thinking := cmd.Params["thinking"].(bool)
|
||||
stream := cmd.Params["stream"].(bool)
|
||||
|
||||
url := fmt.Sprintf("/providers/%s/instances/%s/models/%s", providerName, instanceName, modelName)
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"message": message,
|
||||
"stream": true, // use stream API
|
||||
"reasoning": reasoning,
|
||||
"message": message,
|
||||
"stream": stream, // use stream API
|
||||
"thinking": thinking,
|
||||
}
|
||||
|
||||
// Call stream http api
|
||||
reader, duration, err := c.HTTPClient.RequestStream("POST", url, true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to chat model: %w", err)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
// Parse SSE and output to console
|
||||
scanner := bufio.NewScanner(reader)
|
||||
var fullMessage strings.Builder
|
||||
|
||||
reasoningPrint := true
|
||||
messagePrint := true
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "data:") {
|
||||
data := strings.TrimPrefix(line, "data:")
|
||||
data = strings.TrimSpace(data)
|
||||
|
||||
if strings.HasPrefix(data, "[REASONING]") {
|
||||
data = strings.TrimPrefix(data, "[REASONING]")
|
||||
if reasoningPrint {
|
||||
fmt.Print("Thinking: ")
|
||||
reasoningPrint = false
|
||||
} else {
|
||||
fmt.Print(data)
|
||||
}
|
||||
os.Stdout.Sync()
|
||||
}
|
||||
if strings.HasPrefix(data, "[MESSAGE]") {
|
||||
data = strings.TrimPrefix(data, "[MESSAGE]")
|
||||
if messagePrint {
|
||||
if reasoning {
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Print("Answer: ")
|
||||
messagePrint = false
|
||||
} else {
|
||||
fmt.Print(data)
|
||||
os.Stdout.Sync()
|
||||
fullMessage.WriteString(data)
|
||||
}
|
||||
}
|
||||
} else if strings.HasPrefix(line, "event:error") {
|
||||
// error event
|
||||
if scanner.Scan() {
|
||||
errData := strings.TrimPrefix(scanner.Text(), "data:")
|
||||
errData = strings.TrimSpace(errData)
|
||||
return nil, fmt.Errorf("chat error: %s", errData)
|
||||
}
|
||||
// If there's an error, return a generic error
|
||||
return nil, fmt.Errorf("chat error: received error event from server")
|
||||
if stream {
|
||||
// Call stream http api
|
||||
reader, duration, err := c.HTTPClient.RequestStream("POST", url, true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to chat model: %w", err)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
// Parse SSE and output to console
|
||||
scanner := bufio.NewScanner(reader)
|
||||
var fullMessage strings.Builder
|
||||
|
||||
reasoningPrint := true
|
||||
messagePrint := true
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "data:") {
|
||||
data := strings.TrimPrefix(line, "data:")
|
||||
data = strings.TrimSpace(data)
|
||||
|
||||
if strings.HasPrefix(data, "[REASONING]") {
|
||||
data = strings.TrimPrefix(data, "[REASONING]")
|
||||
if reasoningPrint {
|
||||
fmt.Print("Thinking: ")
|
||||
reasoningPrint = false
|
||||
} else {
|
||||
fmt.Print(data)
|
||||
}
|
||||
os.Stdout.Sync()
|
||||
}
|
||||
if strings.HasPrefix(data, "[MESSAGE]") {
|
||||
data = strings.TrimPrefix(data, "[MESSAGE]")
|
||||
if messagePrint {
|
||||
if thinking {
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Print("Answer: ")
|
||||
messagePrint = false
|
||||
} else {
|
||||
fmt.Print(data)
|
||||
os.Stdout.Sync()
|
||||
fullMessage.WriteString(data)
|
||||
}
|
||||
}
|
||||
} else if strings.HasPrefix(line, "event:error") {
|
||||
// error event
|
||||
if scanner.Scan() {
|
||||
errData := strings.TrimPrefix(scanner.Text(), "data:")
|
||||
errData = strings.TrimSpace(errData)
|
||||
return nil, fmt.Errorf("chat error: %s", errData)
|
||||
}
|
||||
// If there's an error, return a generic error
|
||||
return nil, fmt.Errorf("chat error: received error event from server")
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error reading stream: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
result := &StreamMessageResponse{
|
||||
Code: 0,
|
||||
Message: fullMessage.String(),
|
||||
Duration: duration,
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error reading stream: %w", err)
|
||||
resp, err := c.HTTPClient.Request("POST", url, true, "web", nil, payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list instance models: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
result := &StreamMessageResponse{
|
||||
Code: 0,
|
||||
Message: fullMessage.String(),
|
||||
Duration: duration,
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to list instance models: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
return result, nil
|
||||
|
||||
var result NonStreamResponse
|
||||
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
|
||||
}
|
||||
|
||||
// UseModel sets the current model for chat
|
||||
|
||||
Reference in New Issue
Block a user