Files
ragflow/internal/entity/models/deepseek_test.go
Haruko386 ff3d566a4f fix[go]: support retrieval kb in agent chat (#16944)
### Summary

As title
- [x] fix tool & component `Retrieval KB`
- [x] fix agent cannot use  `Retrieval KB` in agent chat

#### Main cause

Model provider do not set up:
```Go
if chatModelConfig.Tools != nil {
    reqBody["tools"] = chatModelConfig.Tools
}
```

#### Working Now
<img width="3774" height="2128" alt="image"
src="https://github.com/user-attachments/assets/400a349d-0211-43e5-a7ec-7a014acf77a6"
/>

```
 ____________________________________
< This PR takes me all day to do it. >
 ------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ                                                                                                                                                                                                    
```
2026-07-15 21:44:28 +08:00

162 lines
4.4 KiB
Go

package models
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func newDeepSeekForTest(baseURL string) *DeepSeekModel {
return NewDeepSeekModel(
map[string]string{"default": baseURL},
URLSuffix{
Chat: "chat/completions",
Models: "models",
},
)
}
func TestDeepSeekChatWithMessagesSupportsToolCalls(t *testing.T) {
var requestBody map[string]interface{}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/chat/completions" {
t.Errorf("path=%s, want /chat/completions", r.URL.Path)
}
if got := r.Header.Get("Authorization"); got != "Bearer test-key" {
t.Errorf("Authorization=%q, want Bearer test-key", got)
}
if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil {
t.Errorf("decode request: %v", err)
http.Error(w, "bad request", http.StatusBadRequest)
return
}
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"choices": []map[string]interface{}{
{
"message": map[string]interface{}{
"role": "assistant",
"content": nil,
"tool_calls": []map[string]interface{}{
{
"id": "call-1",
"type": "function",
"function": map[string]interface{}{
"name": "search_my_dateset",
"arguments": `{"query":"marigold"}`,
},
},
},
},
},
},
"usage": map[string]interface{}{
"prompt_tokens": 1,
"completion_tokens": 2,
"total_tokens": 3,
},
})
}))
defer srv.Close()
apiKey := "test-key"
toolChoice := "auto"
resp, err := newDeepSeekForTest(srv.URL).ChatWithMessages(
"deepseek-chat",
[]Message{
{Role: "user", Content: "what is marigold"},
},
&APIConfig{ApiKey: &apiKey},
&ChatConfig{
Tools: []map[string]interface{}{
{
"type": "function",
"function": map[string]interface{}{
"name": "search_my_dateset",
"description": "Search datasets.",
},
},
},
ToolChoice: &toolChoice,
},
)
if err != nil {
t.Fatalf("ChatWithMessages: %v", err)
}
if requestBody["tool_choice"] != "auto" {
t.Fatalf("tool_choice=%#v, want auto", requestBody["tool_choice"])
}
if _, ok := requestBody["tools"].([]interface{}); !ok {
t.Fatalf("tools missing or wrong type: %#v", requestBody["tools"])
}
if resp.Answer == nil || *resp.Answer != "" {
t.Fatalf("Answer=%#v, want empty string for tool-call response", resp.Answer)
}
if len(resp.ToolCalls) != 1 {
t.Fatalf("ToolCalls len=%d, want 1", len(resp.ToolCalls))
}
fn, _ := resp.ToolCalls[0]["function"].(map[string]interface{})
if fn["name"] != "search_my_dateset" {
t.Fatalf("tool call function=%#v, want search_my_dateset", fn)
}
if resp.Usage == nil || resp.Usage.TotalTokens != 3 {
t.Fatalf("Usage=%#v, want total tokens 3", resp.Usage)
}
}
func TestDeepSeekChatWithMessagesForwardsToolHistory(t *testing.T) {
var requestBody map[string]interface{}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil {
t.Errorf("decode request: %v", err)
http.Error(w, "bad request", http.StatusBadRequest)
return
}
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"choices": []map[string]interface{}{
{"message": map[string]interface{}{"role": "assistant", "content": "answer"}},
},
})
}))
defer srv.Close()
apiKey := "test-key"
_, err := newDeepSeekForTest(srv.URL).ChatWithMessages(
"deepseek-chat",
[]Message{
{
Role: "assistant",
Content: nil,
ToolCalls: []map[string]interface{}{
{
"id": "call-1",
"type": "function",
"function": map[string]interface{}{
"name": "search_my_dateset",
"arguments": `{"query":"marigold"}`,
},
},
},
},
{Role: "tool", ToolCallID: "call-1", Content: `{"formalized_content":"marigold"}`},
},
&APIConfig{ApiKey: &apiKey},
nil,
)
if err != nil {
t.Fatalf("ChatWithMessages: %v", err)
}
messages, ok := requestBody["messages"].([]interface{})
if !ok || len(messages) != 2 {
t.Fatalf("messages=%#v, want 2 messages", requestBody["messages"])
}
assistant, _ := messages[0].(map[string]interface{})
if _, ok := assistant["tool_calls"].([]interface{}); !ok {
t.Fatalf("assistant tool_calls missing: %#v", assistant)
}
toolMsg, _ := messages[1].(map[string]interface{})
if toolMsg["tool_call_id"] != "call-1" {
t.Fatalf("tool_call_id=%#v, want call-1", toolMsg["tool_call_id"])
}
}