mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-23 00:46:42 +08:00
refactor: encapsulate the code related to tools (#17101)
### Summary As title
This commit is contained in:
@@ -25,7 +25,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"ragflow/internal/common"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -65,25 +64,10 @@ func (b *BaiduModel) ChatWithMessages(modelName string, messages []Message, apiC
|
||||
}
|
||||
url := fmt.Sprintf("%s/%s", resolvedBaseURL, b.baseModel.URLSuffix.Chat)
|
||||
|
||||
// Convert messages to API format
|
||||
apiMessages := make([]map[string]any, len(messages))
|
||||
for i, msg := range messages {
|
||||
apiMessages[i] = map[string]any{
|
||||
"role": msg.Role,
|
||||
"content": msg.Content,
|
||||
}
|
||||
if msg.ToolCallID != "" {
|
||||
apiMessages[i]["tool_call_id"] = msg.ToolCallID
|
||||
}
|
||||
if len(msg.ToolCalls) > 0 {
|
||||
apiMessages[i]["tool_calls"] = msg.ToolCalls
|
||||
}
|
||||
}
|
||||
|
||||
// Build request body
|
||||
reqBody := map[string]interface{}{
|
||||
"model": modelName,
|
||||
"messages": apiMessages,
|
||||
"messages": buildChatMessages(messages),
|
||||
"stream": false,
|
||||
"temperature": 1,
|
||||
}
|
||||
@@ -264,25 +248,10 @@ func (b *BaiduModel) ChatStreamlyWithSender(modelName string, messages []Message
|
||||
}
|
||||
url := fmt.Sprintf("%s/%s", strings.TrimSuffix(resolvedBaseURL, "/"), b.baseModel.URLSuffix.Chat)
|
||||
|
||||
// Convert messages to API format
|
||||
apiMessages := make([]map[string]interface{}, len(messages))
|
||||
for i, msg := range messages {
|
||||
apiMessages[i] = map[string]interface{}{
|
||||
"role": msg.Role,
|
||||
"content": msg.Content,
|
||||
}
|
||||
if msg.ToolCallID != "" {
|
||||
apiMessages[i]["tool_call_id"] = msg.ToolCallID
|
||||
}
|
||||
if len(msg.ToolCalls) > 0 {
|
||||
apiMessages[i]["tool_calls"] = msg.ToolCalls
|
||||
}
|
||||
}
|
||||
|
||||
// Build request body with streaming enabled
|
||||
reqBody := map[string]interface{}{
|
||||
"model": modelName,
|
||||
"messages": apiMessages,
|
||||
"messages": buildChatMessages(messages),
|
||||
"stream": true,
|
||||
}
|
||||
|
||||
@@ -408,55 +377,7 @@ func (b *BaiduModel) ChatStreamlyWithSender(modelName string, messages []Message
|
||||
return nil
|
||||
}
|
||||
|
||||
if tcs, ok := delta["tool_calls"].([]interface{}); ok {
|
||||
for _, tc := range tcs {
|
||||
tcMap, ok := tc.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idxF, ok := tcMap["index"].(float64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idx := int(idxF)
|
||||
existing, hasExisting := accumulatedToolCalls[idx]
|
||||
if !hasExisting {
|
||||
accumulatedToolCalls[idx] = cloneMap(tcMap)
|
||||
continue
|
||||
}
|
||||
if id, ok := tcMap["id"].(string); ok && id != "" {
|
||||
if eid, ok := existing["id"].(string); ok {
|
||||
existing["id"] = eid + id
|
||||
} else {
|
||||
existing["id"] = id
|
||||
}
|
||||
}
|
||||
if typ, ok := tcMap["type"].(string); ok && typ != "" {
|
||||
existing["type"] = typ
|
||||
}
|
||||
if fn, ok := tcMap["function"].(map[string]interface{}); ok {
|
||||
ef, ok := existing["function"].(map[string]interface{})
|
||||
if !ok {
|
||||
ef = make(map[string]interface{})
|
||||
existing["function"] = ef
|
||||
}
|
||||
if name, ok := fn["name"].(string); ok && name != "" {
|
||||
if en, ok := ef["name"].(string); ok {
|
||||
ef["name"] = en + name
|
||||
} else {
|
||||
ef["name"] = name
|
||||
}
|
||||
}
|
||||
if args, ok := fn["arguments"].(string); ok && args != "" {
|
||||
if ea, ok := ef["arguments"].(string); ok {
|
||||
ef["arguments"] = ea + args
|
||||
} else {
|
||||
ef["arguments"] = args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
accumulateToolCallDeltas(delta, accumulatedToolCalls)
|
||||
|
||||
reasoningContent, ok := delta["reasoning_content"].(string)
|
||||
if ok && reasoningContent != "" {
|
||||
@@ -486,18 +407,7 @@ func (b *BaiduModel) ChatStreamlyWithSender(modelName string, messages []Message
|
||||
return fmt.Errorf("baidu: stream ended before [DONE] or finish_reason")
|
||||
}
|
||||
|
||||
if len(accumulatedToolCalls) > 0 && modelConfig != nil {
|
||||
indices := make([]int, 0, len(accumulatedToolCalls))
|
||||
for idx := range accumulatedToolCalls {
|
||||
indices = append(indices, idx)
|
||||
}
|
||||
sort.Ints(indices)
|
||||
tcs := make([]map[string]interface{}, 0, len(accumulatedToolCalls))
|
||||
for _, idx := range indices {
|
||||
tcs = append(tcs, accumulatedToolCalls[idx])
|
||||
}
|
||||
modelConfig.ToolCallsResult = &tcs
|
||||
}
|
||||
setSortedToolCallsResult(modelConfig, accumulatedToolCalls)
|
||||
|
||||
// Send [DONE] marker for OpenAI compatibility
|
||||
endOfStream := "[DONE]"
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -219,3 +220,106 @@ func ReadErrorBody(r io.Reader) string {
|
||||
b, _ := io.ReadAll(r)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// buildChatMessages converts internal messages to chat API payload items.
|
||||
func buildChatMessages(messages []Message) []map[string]any {
|
||||
apiMessages := make([]map[string]interface{}, len(messages))
|
||||
for i, msg := range messages {
|
||||
apiMsg := map[string]interface{}{
|
||||
"role": msg.Role,
|
||||
"content": msg.Content,
|
||||
}
|
||||
if msg.ToolCallID != "" {
|
||||
apiMsg["tool_call_id"] = msg.ToolCallID
|
||||
}
|
||||
if len(msg.ToolCalls) > 0 {
|
||||
apiMsg["tool_calls"] = msg.ToolCalls
|
||||
}
|
||||
apiMessages[i] = apiMsg
|
||||
}
|
||||
return apiMessages
|
||||
}
|
||||
|
||||
// setSortedToolCallsResult stores accumulated tool calls in index order.
|
||||
func setSortedToolCallsResult(chatConfig *ChatConfig, accumulatedToolCalls map[int]map[string]any) {
|
||||
if chatConfig == nil || len(accumulatedToolCalls) == 0 {
|
||||
return
|
||||
}
|
||||
indices := make([]int, 0, len(accumulatedToolCalls))
|
||||
for idx := range accumulatedToolCalls {
|
||||
indices = append(indices, idx)
|
||||
}
|
||||
sort.Ints(indices)
|
||||
toolCalls := make([]map[string]interface{}, 0, len(accumulatedToolCalls))
|
||||
for _, idx := range indices {
|
||||
toolCalls = append(toolCalls, accumulatedToolCalls[idx])
|
||||
}
|
||||
chatConfig.ToolCallsResult = &toolCalls
|
||||
}
|
||||
|
||||
// accumulateToolCallDeltas merges streaming tool-call deltas by index.
|
||||
func accumulateToolCallDeltas(delta map[string]interface{}, accumulatedToolCalls map[int]map[string]any) bool {
|
||||
toolCallDeltas, ok := delta["tool_calls"].([]interface{})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
for _, toolCallDelta := range toolCallDeltas {
|
||||
toolCall, ok := toolCallDelta.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idxF, ok := toolCall["index"].(float64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idx := int(idxF)
|
||||
existing, hasExisting := accumulatedToolCalls[idx]
|
||||
if !hasExisting {
|
||||
accumulatedToolCalls[idx] = cloneMap(toolCall)
|
||||
continue
|
||||
}
|
||||
appendStringField(existing, toolCall, "id")
|
||||
if typ, ok := toolCall["type"].(string); ok && typ != "" {
|
||||
existing["type"] = typ
|
||||
}
|
||||
mergeToolCallFunction(existing, toolCall)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// appendStringField appends a non-empty string field from src into dst.
|
||||
func appendStringField(dst, src map[string]interface{}, key string) {
|
||||
value, ok := src[key].(string)
|
||||
if !ok || value == "" {
|
||||
return
|
||||
}
|
||||
if existing, ok := dst[key].(string); ok {
|
||||
dst[key] = existing + value
|
||||
} else {
|
||||
dst[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// mergeToolCallFunction merges streamed function name and arguments.
|
||||
func mergeToolCallFunction(existing, delta map[string]interface{}) {
|
||||
fn, ok := delta["function"].(map[string]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
existingFn, ok := existing["function"].(map[string]interface{})
|
||||
if !ok {
|
||||
existingFn = make(map[string]interface{})
|
||||
existing["function"] = existingFn
|
||||
}
|
||||
appendStringField(existingFn, fn, "name")
|
||||
appendStringField(existingFn, fn, "arguments")
|
||||
}
|
||||
|
||||
// CloneMap returns a shallow copy of m.
|
||||
func cloneMap(m map[string]interface{}) map[string]interface{} {
|
||||
cp := make(map[string]interface{}, len(m))
|
||||
for k, v := range m {
|
||||
cp[k] = v
|
||||
}
|
||||
return cp
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"ragflow/internal/common"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -68,26 +67,10 @@ func (d *DeepSeekModel) ChatWithMessages(modelName string, messages []Message, a
|
||||
}
|
||||
url := fmt.Sprintf("%s/%s", resolvedBaseURL, d.baseModel.URLSuffix.Chat)
|
||||
|
||||
// Convert messages to the format expected by API
|
||||
apiMessages := make([]map[string]interface{}, len(messages))
|
||||
for i, msg := range messages {
|
||||
apiMsg := map[string]interface{}{
|
||||
"role": msg.Role,
|
||||
"content": msg.Content,
|
||||
}
|
||||
if msg.ToolCallID != "" {
|
||||
apiMsg["tool_call_id"] = msg.ToolCallID
|
||||
}
|
||||
if len(msg.ToolCalls) > 0 {
|
||||
apiMsg["tool_calls"] = msg.ToolCalls
|
||||
}
|
||||
apiMessages[i] = apiMsg
|
||||
}
|
||||
|
||||
// Build request body
|
||||
reqBody := map[string]interface{}{
|
||||
"model": modelName,
|
||||
"messages": apiMessages,
|
||||
"messages": buildChatMessages(messages),
|
||||
"stream": false,
|
||||
"temperature": 1,
|
||||
}
|
||||
@@ -266,26 +249,10 @@ func (d *DeepSeekModel) ChatStreamlyWithSender(modelName string, messages []Mess
|
||||
}
|
||||
url := fmt.Sprintf("%s/chat/completions", resolvedBaseURL)
|
||||
|
||||
// Convert messages to API format
|
||||
apiMessages := make([]map[string]interface{}, len(messages))
|
||||
for i, msg := range messages {
|
||||
apiMsg := map[string]interface{}{
|
||||
"role": msg.Role,
|
||||
"content": msg.Content,
|
||||
}
|
||||
if msg.ToolCallID != "" {
|
||||
apiMsg["tool_call_id"] = msg.ToolCallID
|
||||
}
|
||||
if len(msg.ToolCalls) > 0 {
|
||||
apiMsg["tool_calls"] = msg.ToolCalls
|
||||
}
|
||||
apiMessages[i] = apiMsg
|
||||
}
|
||||
|
||||
// Build request body with streaming enabled
|
||||
reqBody := map[string]interface{}{
|
||||
"model": modelName,
|
||||
"messages": apiMessages,
|
||||
"messages": buildChatMessages(messages),
|
||||
"stream": true,
|
||||
"temperature": 1,
|
||||
}
|
||||
@@ -411,34 +378,7 @@ func (d *DeepSeekModel) ChatStreamlyWithSender(modelName string, messages []Mess
|
||||
return nil
|
||||
}
|
||||
|
||||
if tcs, ok := delta["tool_calls"].([]interface{}); ok {
|
||||
for _, tc := range tcs {
|
||||
tcMap, ok := tc.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idxF, ok := tcMap["index"].(float64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idx := int(idxF)
|
||||
existing, hasExisting := accumulatedToolCalls[idx]
|
||||
if hasExisting {
|
||||
if fn, ok := tcMap["function"].(map[string]interface{}); ok {
|
||||
if args, ok := fn["arguments"].(string); ok {
|
||||
if ef, ok := existing["function"].(map[string]interface{}); ok {
|
||||
if ea, ok := ef["arguments"].(string); ok {
|
||||
ef["arguments"] = ea + args
|
||||
} else {
|
||||
ef["arguments"] = args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accumulatedToolCalls[idx] = cloneMap(tcMap)
|
||||
}
|
||||
}
|
||||
if accumulateToolCallDeltas(delta, accumulatedToolCalls) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -469,18 +409,7 @@ func (d *DeepSeekModel) ChatStreamlyWithSender(modelName string, messages []Mess
|
||||
return fmt.Errorf("deepseek: stream ended before [DONE] or finish_reason")
|
||||
}
|
||||
|
||||
if len(accumulatedToolCalls) > 0 && chatModelConfig != nil {
|
||||
indices := make([]int, 0, len(accumulatedToolCalls))
|
||||
for idx := range accumulatedToolCalls {
|
||||
indices = append(indices, idx)
|
||||
}
|
||||
sort.Ints(indices)
|
||||
tcs := make([]map[string]interface{}, 0, len(accumulatedToolCalls))
|
||||
for _, idx := range indices {
|
||||
tcs = append(tcs, accumulatedToolCalls[idx])
|
||||
}
|
||||
chatModelConfig.ToolCallsResult = &tcs
|
||||
}
|
||||
setSortedToolCallsResult(chatModelConfig, accumulatedToolCalls)
|
||||
|
||||
// Send [DONE] marker for OpenAI compatibility
|
||||
endOfStream := "[DONE]"
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"ragflow/internal/common"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -355,35 +354,7 @@ func (m *MinimaxModel) ChatStreamlyWithSender(modelName string, messages []Messa
|
||||
return nil
|
||||
}
|
||||
|
||||
if tcs, ok := delta["tool_calls"].([]interface{}); ok {
|
||||
for _, tc := range tcs {
|
||||
tcMap, ok := tc.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idxF, ok := tcMap["index"].(float64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idx := int(idxF)
|
||||
existing, hasExisting := accumulatedToolCalls[idx]
|
||||
if hasExisting {
|
||||
if fn, ok := tcMap["function"].(map[string]interface{}); ok {
|
||||
if args, ok := fn["arguments"].(string); ok {
|
||||
if ef, ok := existing["function"].(map[string]interface{}); ok {
|
||||
if ea, ok := ef["arguments"].(string); ok {
|
||||
ef["arguments"] = ea + args
|
||||
} else {
|
||||
ef["arguments"] = args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accumulatedToolCalls[idx] = cloneMap(tcMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
accumulateToolCallDeltas(delta, accumulatedToolCalls)
|
||||
|
||||
content, ok := delta["content"].(string)
|
||||
if ok && content != "" {
|
||||
@@ -413,18 +384,7 @@ func (m *MinimaxModel) ChatStreamlyWithSender(modelName string, messages []Messa
|
||||
return fmt.Errorf("minimax: stream ended before [DONE] or finish_reason")
|
||||
}
|
||||
|
||||
if len(accumulatedToolCalls) > 0 && modelConfig != nil {
|
||||
indices := make([]int, 0, len(accumulatedToolCalls))
|
||||
for idx := range accumulatedToolCalls {
|
||||
indices = append(indices, idx)
|
||||
}
|
||||
sort.Ints(indices)
|
||||
tcs := make([]map[string]interface{}, 0, len(accumulatedToolCalls))
|
||||
for _, idx := range indices {
|
||||
tcs = append(tcs, accumulatedToolCalls[idx])
|
||||
}
|
||||
modelConfig.ToolCallsResult = &tcs
|
||||
}
|
||||
setSortedToolCallsResult(modelConfig, accumulatedToolCalls)
|
||||
|
||||
// Send [DONE] marker for OpenAI compatibility
|
||||
endOfStream := "[DONE]"
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"ragflow/internal/common"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -366,35 +365,7 @@ func (m *MoonshotModel) ChatStreamlyWithSender(modelName string, messages []Mess
|
||||
return nil
|
||||
}
|
||||
|
||||
if tcs, ok := delta["tool_calls"].([]interface{}); ok {
|
||||
for _, tc := range tcs {
|
||||
tcMap, ok := tc.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idxF, ok := tcMap["index"].(float64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idx := int(idxF)
|
||||
existing, hasExisting := accumulatedToolCalls[idx]
|
||||
if hasExisting {
|
||||
if fn, ok := tcMap["function"].(map[string]interface{}); ok {
|
||||
if args, ok := fn["arguments"].(string); ok {
|
||||
if ef, ok := existing["function"].(map[string]interface{}); ok {
|
||||
if ea, ok := ef["arguments"].(string); ok {
|
||||
ef["arguments"] = ea + args
|
||||
} else {
|
||||
ef["arguments"] = args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accumulatedToolCalls[idx] = cloneMap(tcMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
accumulateToolCallDeltas(delta, accumulatedToolCalls)
|
||||
|
||||
reasoningContent, ok := delta["reasoning_content"].(string)
|
||||
if ok && reasoningContent != "" {
|
||||
@@ -424,18 +395,7 @@ func (m *MoonshotModel) ChatStreamlyWithSender(modelName string, messages []Mess
|
||||
return fmt.Errorf("moonshot: stream ended before [DONE] or finish_reason")
|
||||
}
|
||||
|
||||
if len(accumulatedToolCalls) > 0 && chatModelConfig != nil {
|
||||
indices := make([]int, 0, len(accumulatedToolCalls))
|
||||
for idx := range accumulatedToolCalls {
|
||||
indices = append(indices, idx)
|
||||
}
|
||||
sort.Ints(indices)
|
||||
tcs := make([]map[string]interface{}, 0, len(accumulatedToolCalls))
|
||||
for _, idx := range indices {
|
||||
tcs = append(tcs, accumulatedToolCalls[idx])
|
||||
}
|
||||
chatModelConfig.ToolCallsResult = &tcs
|
||||
}
|
||||
setSortedToolCallsResult(chatModelConfig, accumulatedToolCalls)
|
||||
|
||||
// Send [DONE] marker for OpenAI compatibility
|
||||
endOfStream := "[DONE]"
|
||||
|
||||
@@ -393,36 +393,7 @@ func (o *OpenAIModel) ChatStreamlyWithSender(modelName string, messages []Messag
|
||||
continue
|
||||
}
|
||||
|
||||
// Accumulate streaming tool_call deltas (mirrors Python's
|
||||
// async_chat_streamly_with_tools in rag/llm/chat_model.py:500-509).
|
||||
if tcs, ok := delta["tool_calls"].([]interface{}); ok {
|
||||
for _, tc := range tcs {
|
||||
if tcMap, ok := tc.(map[string]interface{}); ok {
|
||||
idxF, ok := tcMap["index"].(float64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idx := int(idxF)
|
||||
existing, hasExisting := accumulatedToolCalls[idx]
|
||||
if hasExisting {
|
||||
if fn, ok := tcMap["function"].(map[string]interface{}); ok {
|
||||
if args, ok := fn["arguments"].(string); ok {
|
||||
if ef, ok := existing["function"].(map[string]interface{}); ok {
|
||||
if ea, ok := ef["arguments"].(string); ok {
|
||||
ef["arguments"] = ea + args
|
||||
} else {
|
||||
ef["arguments"] = args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accumulatedToolCalls[idx] = cloneMap(tcMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
continue // tool_call deltas don't carry content
|
||||
}
|
||||
accumulateToolCallDeltas(delta, accumulatedToolCalls)
|
||||
|
||||
reasoningContent, ok := delta["reasoning_content"].(string)
|
||||
if ok && reasoningContent != "" {
|
||||
@@ -450,14 +421,7 @@ func (o *OpenAIModel) ChatStreamlyWithSender(modelName string, messages []Messag
|
||||
return fmt.Errorf("openai: stream ended before [DONE] or finish_reason")
|
||||
}
|
||||
|
||||
// Populate ToolCallsResult with accumulated streaming tool_calls.
|
||||
if len(accumulatedToolCalls) > 0 && chatModelConfig != nil {
|
||||
tcs := make([]map[string]interface{}, 0, len(accumulatedToolCalls))
|
||||
for _, tc := range accumulatedToolCalls {
|
||||
tcs = append(tcs, tc)
|
||||
}
|
||||
chatModelConfig.ToolCallsResult = &tcs
|
||||
}
|
||||
setSortedToolCallsResult(chatModelConfig, accumulatedToolCalls)
|
||||
|
||||
// Populate UsageResult with the authoritative usage from the stream.
|
||||
if streamUsage != nil && chatModelConfig != nil {
|
||||
@@ -1110,11 +1074,3 @@ func extractUsageFromMap(raw map[string]interface{}) (int, int, int) {
|
||||
}
|
||||
return pt, ct, tt
|
||||
}
|
||||
|
||||
func cloneMap(m map[string]interface{}) map[string]interface{} {
|
||||
cp := make(map[string]interface{}, len(m))
|
||||
for k, v := range m {
|
||||
cp[k] = v
|
||||
}
|
||||
return cp
|
||||
}
|
||||
|
||||
@@ -310,35 +310,7 @@ func (r *RAGconModel) ChatStreamlyWithSender(modelName string, messages []Messag
|
||||
continue
|
||||
}
|
||||
|
||||
if tcs, ok := delta["tool_calls"].([]interface{}); ok {
|
||||
for _, tc := range tcs {
|
||||
tcMap, ok := tc.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idxF, ok := tcMap["index"].(float64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idx := int(idxF)
|
||||
if existing, hasExisting := accumulatedToolCalls[idx]; hasExisting {
|
||||
if fn, ok := tcMap["function"].(map[string]interface{}); ok {
|
||||
if args, ok := fn["arguments"].(string); ok {
|
||||
if ef, ok := existing["function"].(map[string]interface{}); ok {
|
||||
if ea, ok := ef["arguments"].(string); ok {
|
||||
ef["arguments"] = ea + args
|
||||
} else {
|
||||
ef["arguments"] = args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accumulatedToolCalls[idx] = cloneMap(tcMap)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
accumulateToolCallDeltas(delta, accumulatedToolCalls)
|
||||
|
||||
if reasoningContent, ok := delta["reasoning_content"].(string); ok && reasoningContent != "" {
|
||||
if err := sender(nil, &reasoningContent); err != nil {
|
||||
@@ -361,13 +333,7 @@ func (r *RAGconModel) ChatStreamlyWithSender(modelName string, messages []Messag
|
||||
return fmt.Errorf("ragcon: stream ended before [DONE] or finish_reason")
|
||||
}
|
||||
|
||||
if len(accumulatedToolCalls) > 0 && chatModelConfig != nil {
|
||||
tcs := make([]map[string]interface{}, 0, len(accumulatedToolCalls))
|
||||
for _, tc := range accumulatedToolCalls {
|
||||
tcs = append(tcs, tc)
|
||||
}
|
||||
chatModelConfig.ToolCallsResult = &tcs
|
||||
}
|
||||
setSortedToolCallsResult(chatModelConfig, accumulatedToolCalls)
|
||||
if streamUsage != nil && chatModelConfig != nil {
|
||||
chatModelConfig.UsageResult = streamUsage
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"ragflow/internal/common"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -356,51 +355,8 @@ func (x *XiaomiModel) ChatStreamlyWithSender(modelName string, messages []Messag
|
||||
return nil
|
||||
}
|
||||
|
||||
if tcs, ok := delta["tool_calls"].([]interface{}); ok {
|
||||
for _, tc := range tcs {
|
||||
tcMap, ok := tc.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idxF, ok := tcMap["index"].(float64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
idx := int(idxF)
|
||||
existing, hasExisting := accumulatedToolCalls[idx]
|
||||
if hasExisting {
|
||||
if id, ok := tcMap["id"].(string); ok && id != "" {
|
||||
existing["id"] = id
|
||||
}
|
||||
if typ, ok := tcMap["type"].(string); ok && typ != "" {
|
||||
existing["type"] = typ
|
||||
}
|
||||
if fn, ok := tcMap["function"].(map[string]interface{}); ok {
|
||||
ef, ok := existing["function"].(map[string]interface{})
|
||||
if !ok {
|
||||
ef = make(map[string]interface{})
|
||||
existing["function"] = ef
|
||||
}
|
||||
if name, ok := fn["name"].(string); ok && name != "" {
|
||||
if en, ok := ef["name"].(string); ok {
|
||||
ef["name"] = en + name
|
||||
} else {
|
||||
ef["name"] = name
|
||||
}
|
||||
}
|
||||
if args, ok := fn["arguments"].(string); ok {
|
||||
if ea, ok := ef["arguments"].(string); ok {
|
||||
ef["arguments"] = ea + args
|
||||
} else {
|
||||
ef["arguments"] = args
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accumulatedToolCalls[idx] = cloneMap(tcMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
accumulateToolCallDeltas(delta, accumulatedToolCalls)
|
||||
|
||||
reasoningContent, ok := delta["reasoning_content"].(string)
|
||||
if ok && reasoningContent != "" {
|
||||
if err = sender(nil, &reasoningContent); err != nil {
|
||||
@@ -420,18 +376,7 @@ func (x *XiaomiModel) ChatStreamlyWithSender(modelName string, messages []Messag
|
||||
return fmt.Errorf("failed to scan response body: %w", err)
|
||||
}
|
||||
|
||||
if len(accumulatedToolCalls) > 0 && modelConfig != nil {
|
||||
indices := make([]int, 0, len(accumulatedToolCalls))
|
||||
for idx := range accumulatedToolCalls {
|
||||
indices = append(indices, idx)
|
||||
}
|
||||
sort.Ints(indices)
|
||||
tcs := make([]map[string]interface{}, 0, len(accumulatedToolCalls))
|
||||
for _, idx := range indices {
|
||||
tcs = append(tcs, accumulatedToolCalls[idx])
|
||||
}
|
||||
modelConfig.ToolCallsResult = &tcs
|
||||
}
|
||||
setSortedToolCallsResult(modelConfig, accumulatedToolCalls)
|
||||
|
||||
// Send [DONE] marker for OpenAI compatibility
|
||||
endOfStream := "[DONE]"
|
||||
|
||||
Reference in New Issue
Block a user