Skip to main content
Glama

baidu-ai-search

Official
by baidubce
app_builder_client_test.go31.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) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/baidubce/app-builder'

If you have feedback or need assistance with the MCP directory API, please join our Discord server