app_builder_client_test.go•31.9 kB
// Copyright (c) 2024 Baidu, Inc. 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 appbuilder
import (
"bytes"
"encoding/json"
"fmt"
"os"
"strings"
"testing"
)
func TestNewAppBuilderClientError(t *testing.T) {
t.Parallel() // 并发运行
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
// NewAppBuilderClient测试1
appID := "aa8af334-df27-4855-b3d1-0d249c61fc08"
_, err = NewAppBuilderClient("", config)
if err == nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
}
// NewAppBuilderClient测试2
_, err = NewAppBuilderClient(appID, nil)
if err == nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
}
// GetSdkConfig测试
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
client.GetSdkConfig()
// GetClient测试
client.GetClient()
var GatewayURL = config.GatewayURLV2
// CreateConversation 测试1 ServiceURLV2 错误
client.sdkConfig.GatewayURLV2 = "://invalid-url"
_, err = client.CreateConversation()
if err == nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Errorf("expected ServiceURLV2 error, got %v", err)
}
// CreateConversation 测试2 Do 错误
client.sdkConfig.GatewayURLV2 = "http://192.0.2.1"
_, err = client.CreateConversation()
if err == nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Errorf("expected Bad Request error, got %v", err)
}
// CreateConversation 测试3 错误的 HTTP 响应
client.sdkConfig.GatewayURLV2 = GatewayURL
client.client = &MockHTTPClient{}
_, err = client.CreateConversation()
if err == nil {
t.Fatalf("expected 400 error, got nil")
}
// CreateConversation 测试 4: 模拟读取 body 时发生错误
client.sdkConfig.GatewayURLV2 = GatewayURL
client.client = &FaultyHTTPClient{}
_, err = client.CreateConversation()
if err == nil {
t.Fatalf("expected read error, got nil")
}
// CreateConversation 测试 5: json.Unmarshal错误
client.sdkConfig.GatewayURLV2 = GatewayURL
client.client = &InvalidJSONHTTPClient{}
_, err = client.CreateConversation()
if err == nil {
t.Fatalf("expected JSON unmarshal error, got nil")
}
// CreateConversation 测试 6: 缺少 id 字段
client.client = &MissingIDHTTPClient{}
client.CreateConversation()
// 测试1 ServiceURLV2 错误
config.GatewayURLV2 = "://invalid-url"
_, err = GetAppList(GetAppListRequest{
Limit: 10,
}, config)
if err == nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Errorf("expected ServiceURLV2 error, got %v", err)
}
// 测试2 Do 错误
config.GatewayURLV2 = "http://192.0.2.1"
_, err = GetAppList(GetAppListRequest{
Limit: 10,
}, config)
if err == nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Errorf("expected Bad Request error, got %v", err)
}
// 测试3 错误的 HTTP 响应
config.GatewayURLV2 = GatewayURL
config.HTTPClient = &MockHTTPClient{}
_, err = GetAppList(GetAppListRequest{
Limit: 10,
}, config)
if err == nil {
t.Fatalf("expected 400 error, got nil")
}
// 测试 4: 模拟读取 body 时发生错误
config.GatewayURLV2 = GatewayURL
config.HTTPClient = &FaultyHTTPClient{}
_, err = GetAppList(GetAppListRequest{
Limit: 10,
}, config)
if err == nil {
t.Fatalf("expected read error, got nil")
}
// 测试 5: json.Unmarshal错误
config.GatewayURLV2 = GatewayURL
config.HTTPClient = &InvalidJSONHTTPClient{}
_, err = GetAppList(GetAppListRequest{
Limit: 10,
}, config)
if err == nil {
t.Fatalf("expected JSON unmarshal error, got nil")
}
}
func TestClientUploadLocalFile(t *testing.T) {
t.Parallel() // 并发运行
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
var GatewayURL = config.GatewayURLV2
appID := "aa8af334-df27-4855-b3d1-0d249c61fc08"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
// 测试 UploadLocalFile 1: 文件打开错误
_, err = client.UploadLocalFile("validConversationID", "invalidFilePath")
if err == nil || !strings.Contains(err.Error(), "no such file or directory") {
t.Errorf("expected file open error, got %v", err)
}
// 测试 UploadLocalFile 2: t.client.Do 错误
client.sdkConfig.GatewayURLV2 = "http://192.0.2.1"
_, err = client.UploadLocalFile("5678987", "./files/test.pdf")
if err == nil {
t.Errorf("expected client error, got nil")
}
// 测试 UploadLocalFile 3: 无效的ServiceURLV2
client.sdkConfig.GatewayURLV2 = "://invalid-url"
_, err = client.UploadLocalFile("12345", "./files/test.pdf")
if err == nil || !strings.Contains(err.Error(), "missing protocol scheme") {
t.Errorf("expected ServiceURLV2 error, got %v", err)
}
// 测试 UploadLocalFile 4: 错误的 HTTP 响应
client.client = &MockHTTPClient{}
client.sdkConfig.GatewayURLV2 = GatewayURL
_, err = client.UploadLocalFile("21", "./files/test.pdf")
if err == nil {
t.Fatalf("expected 400 error, got nil")
}
// 测试 UploadLocalFile 5: 模拟读取 body 时发生错误
client.client = &FaultyHTTPClient{}
client.sdkConfig.GatewayURLV2 = GatewayURL
_, err = client.UploadLocalFile("22", "./files/test.pdf")
if err == nil {
t.Fatalf("expected read error, got nil")
}
// 测试 UploadLocalFile 6: json.Unmarshal错误
client.client = &InvalidJSONHTTPClient{}
client.sdkConfig.GatewayURLV2 = GatewayURL
_, err = client.UploadLocalFile("11", "./files/test.pdf")
if err == nil {
t.Fatalf("expected JSON unmarshal error, got nil")
}
// 测试 UploadLocalFile 7: 缺少 id 字段
client.client = &MissingIDHTTPClient{}
client.sdkConfig.GatewayURLV2 = GatewayURL
_, err = client.UploadLocalFile("23", "./files/test.pdf")
if err == nil {
t.Fatalf("expected missing conversation_id error, got nil")
}
}
func TestClientRun(t *testing.T) {
t.Parallel() // 并发运行
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
var GatewayURL = config.GatewayURLV2
appID := "aa8af334-df27-4855-b3d1-0d249c61fc08"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
// 测试1 conversationID ==0
_, err = client.Run("", "描述简历中的候选人情况", nil, true)
if err == nil {
t.Errorf("expected conversationID mustn't be empty, got %v", err)
}
// 测试2 ServiceURLV2 error 无效的ServiceURLV2
client.sdkConfig.GatewayURLV2 = "://invalid-url"
_, err = client.Run("12", "描述简历中的候选人情况", nil, true)
if err == nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Errorf("expected ServiceURLV2 error, got %v", err)
}
// 测试3 t.client.Do 错误
client.sdkConfig.GatewayURLV2 = "http://192.0.2.1"
_, err = client.Run("123", "描述简历中的候选人情况", nil, true)
if err == nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Errorf("expected Bad Request error, got %v", err)
}
// 测试4 错误的 HTTP 响应
client.client = &MockHTTPClient{}
client.sdkConfig.GatewayURLV2 = GatewayURL
_, err = client.Run("1234", "描述简历中的候选人情况", nil, true)
if err == nil {
t.Fatalf("expected 400 error, got nil")
}
}
func TestClientRunWithToolCallError(t *testing.T) {
t.Parallel() // 并发运行
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
var GatewayURL = config.GatewayURLV2
appID := "aa8af334-df27-4855-b3d1-0d249c61fc08"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
jsonStr := `
{
"type": "function",
"function": {
"name": "get_cur_whether",
"description": "这是一个获得指定地点天气的工具",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "省,市名,例如:河北省"
},
"unit": {
"type": "string",
"enum": ["摄氏度", "华氏度"]
}
},
"required": ["location"]
}
}
}`
var tool Tool
err = json.Unmarshal([]byte(jsonStr), &tool)
if err != nil {
fmt.Println("unmarshal tool error:", err)
}
// 测试1 conversationID ==0
client.RunWithToolCall(AppBuilderClientRunRequest{
AppID: appID,
Query: "今天北京的天气怎么样?",
ConversationID: "",
Stream: false,
Tools: []Tool{tool},
})
// 测试4 非流式
client.RunWithToolCall(AppBuilderClientRunRequest{
AppID: appID,
Query: "今天北京的天气怎么样?",
ConversationID: "111111",
Stream: false,
Tools: []Tool{tool},
})
// 测试2 ServiceURLV2 error 无效的ServiceURLV2
client.sdkConfig.GatewayURLV2 = "://invalid-url"
client.RunWithToolCall(AppBuilderClientRunRequest{
AppID: appID,
Query: "今天北京的天气怎么样?",
ConversationID: "111111111",
Stream: false,
Tools: []Tool{tool},
})
// 测试3 t.client.Do 错误
client.sdkConfig.GatewayURLV2 = "http://192.0.2.1"
client.RunWithToolCall(AppBuilderClientRunRequest{
AppID: appID,
Query: "今天北京的天气怎么样?",
ConversationID: "222222",
Stream: false,
Tools: []Tool{tool},
})
// 测试4 错误的 HTTP 响应
client.client = &MockHTTPClient{}
client.sdkConfig.GatewayURLV2 = GatewayURL
client.RunWithToolCall(AppBuilderClientRunRequest{
AppID: appID,
Query: "今天北京的天气怎么样?",
ConversationID: "33333",
Stream: false,
Tools: []Tool{tool},
})
}
func TestDescribeApp(t *testing.T) {
var logBuffer bytes.Buffer
os.Setenv("APPBUILDER_LOGLEVEL", "DEBUG")
os.Setenv("APPBUILDER_LOGFILE", "")
log := func(format string, args ...any) {
fmt.Fprintf(&logBuffer, format+"\n", args...)
}
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
app, err := DescribeApp("b2a972c5-e082-46e5-b313-acbf51792422", config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("describe app failed: %v", err)
}
log("Get App Name: %s", app.Name)
chatflowApp, err := DescribeApp("4403205e-fb83-4fac-96d8-943bdb63796f", config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("describe app failed: %v", err)
}
log("Get App Name: %s", chatflowApp.Name)
}
func TestNewAppBuilderClient(t *testing.T) {
var logBuffer bytes.Buffer
// 设置环境变量
os.Setenv("APPBUILDER_LOGLEVEL", "DEBUG")
os.Setenv("APPBUILDER_LOGFILE", "")
// 定义一个日志函数,将日志写入缓冲区
log := func(format string, args ...any) {
fmt.Fprintf(&logBuffer, format+"\n", args...)
}
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
apps, err := GetAppList(GetAppListRequest{
Limit: 10,
}, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("get apps failed: %v", err)
}
log("Number of apps: %d", len(apps))
maxKeys := 10
apps2, err := DescribeApps(DescribeAppsRequest{MaxKeys: &maxKeys}, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("describe apps failed: %v", err)
}
log("Number of apps: %d", len(apps2.Data))
appID := "fb64d96b-f828-4385-ba1d-835298d635a9"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
conversationID, err := client.CreateConversation()
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("create conversation failed: %v", err)
}
_, err = client.UploadLocalFile(conversationID, "./files/test.pdf")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("upload local file failed: %v", err)
}
i, err := client.Run(conversationID, "描述简历中的候选人情况", nil, true)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
totalAnswer := ""
// test follow up queries
for answer, err := i.Next(); err == nil; answer, err = i.Next() {
totalAnswer += answer.Answer
for _, ev := range answer.Events {
if ev.ContentType == JsonContentType {
detail := ev.Detail.(JsonDetail)
folllowUpQueries := detail.Json.FollowUpQueries
fmt.Println(folllowUpQueries)
if len(folllowUpQueries[0]) == 0 {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatal("follow up queries is empty")
}
}
evJSON, _ := json.Marshal(ev)
log(string(evJSON))
}
}
log("----------------answer-------------------")
log(totalAnswer)
// 测试4 非流式
client.Run(conversationID, "描述简历中的候选人情况", nil, false)
// 如果测试失败,则输出缓冲区中的日志
if t.Failed() {
fmt.Println(logBuffer.String())
} else { // else 紧跟在右大括号后面
// 测试通过,打印文件名和测试函数名
t.Logf("%s========== OK: %s ==========%s", "\033[32m", t.Name(), "\033[0m")
}
}
func TestAppBuilderClientRunWithToolCall(t *testing.T) {
var logBuffer bytes.Buffer
os.Setenv("APPBUILDER_LOGLEVEL", "DEBUG")
os.Setenv("APPBUILDER_LOGFILE", "")
log := func(format string, args ...any) {
fmt.Fprintf(&logBuffer, format+"\n", args...)
}
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
appID := "aa8af334-df27-4855-b3d1-0d249c61fc08"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AgentBuidler instance failed")
}
conversationID, err := client.CreateConversation()
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("create conversation failed: %v", err)
}
jsonStr := `
{
"type": "function",
"function": {
"name": "get_cur_whether",
"description": "这是一个获得指定地点天气的工具",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "省,市名,例如:河北省"
},
"unit": {
"type": "string",
"enum": ["摄氏度", "华氏度"]
}
},
"required": ["location"]
}
}
}`
var tool Tool
err = json.Unmarshal([]byte(jsonStr), &tool)
if err != nil {
fmt.Println("unmarshal tool error:", err)
}
i, err := client.RunWithToolCall(AppBuilderClientRunRequest{
AppID: appID,
Query: "今天北京的天气怎么样?",
ConversationID: conversationID,
Stream: false,
Tools: []Tool{tool},
})
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
totalAnswer := ""
toolCallID := ""
for answer, err := i.Next(); err == nil; answer, err = i.Next() {
totalAnswer += answer.Answer
lastEvent := answer.Events[len(answer.Events)-1]
toolCallID = lastEvent.ToolCalls[len(lastEvent.ToolCalls)-1].ID
}
i2, err := client.RunWithToolCall(AppBuilderClientRunRequest{
ConversationID: conversationID,
AppID: appID,
ToolOutputs: []ToolOutput{
{
ToolCallID: toolCallID,
Output: "北京今天35",
},
},
})
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
for answer, err := i2.Next(); err == nil; answer, err = i2.Next() {
totalAnswer += answer.Answer
for _, ev := range answer.Events {
evJSON, _ := json.Marshal(ev)
log(string(evJSON))
}
}
log("----------------answer-------------------")
log(totalAnswer)
// 如果测试失败,则输出缓冲区中的日志
if t.Failed() {
fmt.Printf("%s========== FAIL: %s ==========%s\n", "\033[31m", t.Name(), "\033[0m")
fmt.Println(logBuffer.String())
} else { // else 紧跟在右大括号后面
// 测试通过,打印文件名和测试函数名
t.Logf("%s========== OK: %s ==========%s", "\033[32m", t.Name(), "\033[0m")
}
}
func TestAppBuilderClientRunToolChoice(t *testing.T) {
var logBuffer bytes.Buffer
os.Setenv("APPBUILDER_LOGLEVEL", "DEBUG")
os.Setenv("APPBUILDER_LOGFILE", "")
log := func(format string, args ...any) {
fmt.Fprintf(&logBuffer, format+"\n", args...)
}
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
appID := "aa8af334-df27-4855-b3d1-0d249c61fc08"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AgentBuidler instance failed")
}
conversationID, err := client.CreateConversation()
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("create conversation failed: %v", err)
}
input := make(map[string]any)
input["city"] = "北京"
end_user_id := "go_user_id_0"
i, err := client.Run(AppBuilderClientRunRequest{
ConversationID: conversationID,
AppID: appID,
Query: "你能干什么",
EndUserID: &end_user_id,
Stream: false,
ToolChoice: &ToolChoice{
Type: "function",
Function: ToolChoiceFunction{
Name: "WeatherQuery",
Input: input,
},
},
})
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
for answer, err := i.Next(); err == nil; answer, err = i.Next() {
for _, ev := range answer.Events {
evJSON, _ := json.Marshal(ev)
log(string(evJSON))
}
}
// 如果测试失败,则输出缓冲区中的日志
if t.Failed() {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
fmt.Println(logBuffer.String())
} else { // else 紧跟在右大括号后面
// 测试通过,打印文件名和测试函数名
t.Logf("%s========== OK: %s ==========%s", "\033[32m", t.Name(), "\033[0m")
}
}
func TestAppBuilderClientRunChatflow(t *testing.T) {
var logBuffer bytes.Buffer
os.Setenv("APPBUILDER_LOGLEVEL", "DEBUG")
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
appID := "4403205e-fb83-4fac-96d8-943bdb63796f"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AgentBuidler instance failed")
}
conversationID, err := client.CreateConversation()
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("create conversation failed: %v", err)
}
i, err := client.Run(AppBuilderClientRunRequest{
ConversationID: conversationID,
AppID: appID,
Query: "查天气",
Stream: true,
})
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
var interruptId string
interruptStack := make([]string, 0)
for answer, err := i.Next(); err == nil; answer, err = i.Next() {
for _, ev := range answer.Events {
if ev.ContentType == PublishMessageContentType {
detail := ev.Detail.(PublishMessageDetail)
message := detail.Message
fmt.Println(message)
break
}
if ev.ContentType == ChatflowInterruptContentType {
deatil := ev.Detail.(ChatflowInterruptDetail)
interruptId = deatil.InterruptEventID
interruptStack = append(interruptStack, interruptId)
break
}
}
}
if len(interruptId) == 0 {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("interrupt id is empty")
}
interruptId = ""
i2, err := client.Run(AppBuilderClientRunRequest{
ConversationID: conversationID,
AppID: appID,
Query: "我先查个航班动态",
Stream: true,
Action: NewResumeAction(interruptStack[len(interruptStack)-1]),
})
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
interruptStack = interruptStack[:len(interruptStack)-1]
for answer, err := i2.Next(); err == nil; answer, err = i2.Next() {
for _, ev := range answer.Events {
if ev.ContentType == PublishMessageContentType {
detail := ev.Detail.(PublishMessageDetail)
message := detail.Message
fmt.Println(message)
break
}
if ev.ContentType == ChatflowInterruptContentType {
deatil := ev.Detail.(ChatflowInterruptDetail)
interruptId = deatil.InterruptEventID
interruptStack = append(interruptStack, interruptId)
break
}
}
}
if len(interruptId) == 0 {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("interrupt id is empty")
}
interruptId = ""
i3, err := client.Run(AppBuilderClientRunRequest{
ConversationID: conversationID,
AppID: appID,
Query: "CA1234",
Stream: true,
Action: NewResumeAction(interruptStack[len(interruptStack)-1]),
})
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
interruptStack = interruptStack[:len(interruptStack)-1]
for answer, err := i3.Next(); err == nil; answer, err = i3.Next() {
for _, ev := range answer.Events {
if ev.ContentType == TextContentType {
detail := ev.Detail.(TextDetail)
text := detail.Text
fmt.Println(text)
break
}
if ev.ContentType == ChatflowInterruptContentType {
deatil := ev.Detail.(ChatflowInterruptDetail)
interruptId = deatil.InterruptEventID
interruptStack = append(interruptStack, interruptId)
break
}
}
}
i4, err := client.Run(AppBuilderClientRunRequest{
ConversationID: conversationID,
AppID: appID,
Query: "北京的",
Stream: true,
Action: NewResumeAction(interruptStack[len(interruptStack)-1]),
})
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
for answer, err := i4.Next(); err == nil; answer, err = i4.Next() {
for _, ev := range answer.Events {
if ev.ContentType == TextContentType {
detail := ev.Detail.(TextDetail)
text := detail.Text
fmt.Println(text)
break
}
}
}
// 如果测试失败,则输出缓冲区中的日志
if t.Failed() {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
fmt.Println(logBuffer.String())
} else { // else 紧跟在右大括号后面
// 测试通过,打印文件名和测试函数名
t.Logf("%s========== OK: %s ==========%s", "\033[32m", t.Name(), "\033[0m")
}
}
func TestAppbuilderClientFeedback(t *testing.T) {
var logBuffer bytes.Buffer
// 设置环境变量
os.Setenv("APPBUILDER_LOGLEVEL", "DEBUG")
os.Setenv("APPBUILDER_LOGFILE", "")
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
appID := "fb64d96b-f828-4385-ba1d-835298d635a9"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
conversationID, err := client.CreateConversation()
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("create conversation failed: %v", err)
}
_, err = client.UploadLocalFile(conversationID, "./files/test.pdf")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("upload local file failed: %v", err)
}
i, err := client.Run(conversationID, "描述简历中的候选人情况", nil, false)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("run failed:%v", err)
}
var messageID string
for answer, err := i.Next(); err == nil; answer, err = i.Next() {
if answer.MessageID != "" {
messageID = answer.MessageID
break
}
}
_, err = client.Feedback(AppBuilderClientFeedbackRequest{
ConversationID: conversationID,
MessageID: messageID,
Type: "downvote",
Flag: []string{"没有帮助"},
Reason: "测试",
})
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("upvote failed:%v", err)
}
// 如果测试失败,则输出缓冲区中的日志
if t.Failed() {
fmt.Println(logBuffer.String())
} else { // else 紧跟在右大括号后面
// 测试通过,打印文件名和测试函数名
t.Logf("%s========== OK: %s ==========%s", "\033[32m", t.Name(), "\033[0m")
}
}
func TestAppBuilderClientUploadFile(t *testing.T) {
var logBuffer bytes.Buffer
// 设置环境变量
os.Setenv("APPBUILDER_LOGLEVEL", "DEBUG")
os.Setenv("APPBUILDER_LOGFILE", "")
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
appID := "fb64d96b-f828-4385-ba1d-835298d635a9"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
conversationID, err := client.CreateConversation()
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("create conversation failed: %v", err)
}
req := AppBuilderClientUploadFileRequest{
ConversationID: conversationID,
FilePath: "./files/test.pdf",
}
_, err = client.UploadFile(&req)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("upload local file failed: %v", err)
}
req = AppBuilderClientUploadFileRequest{
ConversationID: conversationID,
FileURL: "https://bj.bcebos.com/v1/appbuilder/animal_recognize_test.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-01-24T12%3A19%3A16Z%2F-1%2Fhost%2F411bad53034fa8f9c6edbe5c4909d76ecf6fad6862cf937c03f8c5260d51c6ae",
}
_, err = client.UploadFile(&req)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("upload url file failed: %v", err)
}
// 如果测试失败,则输出缓冲区中的日志
if t.Failed() {
fmt.Println(logBuffer.String())
} else { // else 紧跟在右大括号后面
// 测试通过,打印文件名和测试函数名
t.Logf("%s========== OK: %s ==========%s", "\033[32m", t.Name(), "\033[0m")
}
}
func TestAppBuilderClientRunParameters(t *testing.T) {
t.Parallel() // 并发运行
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
appID := "2313e282-baa6-4db6-92dd-a21e99cfd59e"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
conversationID, err := client.CreateConversation()
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("create conversation failed: %v", err)
}
res, err := client.Run(AppBuilderClientRunRequest{
AppID: appID,
Query: "国庆长假",
Stream: false,
ConversationID: conversationID,
Parameters: map[string]any{
"city": "上海",
},
})
if err != nil {
t.Errorf("run err: %v", err)
}
for answer, err := res.Next(); err == nil; answer, err = res.Next() {
t.Log(answer.Answer)
}
}
func TestAppBuilderClientRunCustomMetadata(t *testing.T) {
t.Parallel() // 并发运行
// 测试逻辑
config, err := NewSDKConfig("", "")
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new http client config failed: %v", err)
}
appID := "a3654cd9-378a-4b46-a33b-2259ca3b304e"
client, err := NewAppBuilderClient(appID, config)
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("new AppBuilderClient instance failed")
}
conversationID, err := client.CreateConversation()
if err != nil {
t.Logf("%s========== FAIL: %s ==========%s", "\033[31m", t.Name(), "\033[0m")
t.Fatalf("create conversation failed: %v", err)
}
res, err := client.Run(AppBuilderClientRunRequest{
AppID: appID,
Query: "我要回老家相亲",
Stream: false,
ConversationID: conversationID,
CustomMetadata: &CustomMetadata{
OverrideRoleInstruction: `# 角色任务\n" +
"作为高情商大师,你的主要任务是根据提问,做出最佳的建议。\n" +
"\n" +
"# 工具能力\n" +
"\n" +
"无工具集提供\n" +
"\n" +
"# 要求与限制\n" +
"\n" +
"1. 输出内容的风格为幽默\n" +
"2.输出的字数限制为100字以内"`,
},
})
if err != nil {
t.Errorf("run err: %v", err)
}
for answer, err := res.Next(); err == nil; answer, err = res.Next() {
t.Log(answer.Answer)
}
}