├── .github └── workflows │ └── release.yml ├── .gitignore ├── .goreleaser.yaml ├── LICENSE ├── README.md ├── api-audio-to-text.go ├── api-chat-messages-stop.go ├── api-chat-messages.go ├── api-completion-messages-stop.go ├── api-completion-messages.go ├── api-conversations.go ├── api-file-upload.go ├── api-messages-feedacks.go ├── api-messages-suggested.go ├── api-messages.go ├── api-meta.go ├── api-parameters.go ├── api-text-to-audio.go ├── api.go ├── client.go ├── cmd └── main.go ├── console-datasets-file-upload.go ├── console-datasets-init.go ├── console-datasets.go ├── console-user-login.go ├── console-workspaces-models.go ├── const.go ├── fn-api.go ├── fn-console.go ├── fn.go └── go.mod /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Go Releaser 2 | 3 | on: 4 | push: 5 | tags: ["*"] 6 | 7 | env: 8 | GO_VERSION: "1.21" 9 | 10 | permissions: 11 | contents: write 12 | 13 | jobs: 14 | goreleaser: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Set up Go 23 | uses: actions/setup-go@v5 24 | with: 25 | go-version: ${{ env.GO_VERSION }} 26 | 27 | - name: Run GoReleaser 28 | uses: goreleaser/goreleaser-action@v5 29 | with: 30 | distribution: goreleaser 31 | version: latest 32 | args: release --clean 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | testfile-for-dify-database.txt 2 | tobedone 3 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | project_name: queue 2 | 3 | builds: 4 | - # If true, skip the build. 5 | # Useful for library projects. 6 | # Default is false 7 | skip: true 8 | 9 | changelog: 10 | # Set it to true if you wish to skip the changelog generation. 11 | # This may result in an empty release notes on GitHub/GitLab/Gitea. 12 | skip: false 13 | 14 | # Changelog generation implementation to use. 15 | # 16 | # Valid options are: 17 | # - `git`: uses `git log`; 18 | # - `github`: uses the compare GitHub API, appending the author login to the changelog. 19 | # - `gitlab`: uses the compare GitLab API, appending the author name and email to the changelog. 20 | # - `github-native`: uses the GitHub release notes generation API, disables the groups feature. 21 | # 22 | # Defaults to `git`. 23 | use: git 24 | 25 | # Sorts the changelog by the commit's messages. 26 | # Could either be asc, desc or empty 27 | # Default is empty 28 | sort: asc 29 | 30 | # Group commits messages by given regex and title. 31 | # Order value defines the order of the groups. 32 | # Proving no regex means all commits will be grouped under the default group. 33 | # Groups are disabled when using github-native, as it already groups things by itself. 34 | # 35 | # Default is no groups. 36 | groups: 37 | - title: Features 38 | regexp: "^.*feat[(\\w)]*:+.*$" 39 | order: 0 40 | - title: "Bug fixes" 41 | regexp: "^.*fix[(\\w)]*:+.*$" 42 | order: 1 43 | - title: "Enhancements" 44 | regexp: "^.*chore[(\\w)]*:+.*$" 45 | order: 2 46 | - title: Others 47 | order: 999 48 | 49 | filters: 50 | # Commit messages matching the regexp listed here will be removed from 51 | # the changelog 52 | # Default is empty 53 | exclude: 54 | - "^docs" 55 | - "CICD" 56 | - typo -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Su Yang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dify Go SDK 2 | 3 | Golang SDK for [langgenius/dify](https://github.com/langgenius/dify) . 4 | 5 | ## Quick Start 6 | 7 | ```bash 8 | go get github.com/soulteary/dify-go-sdk 9 | ``` 10 | 11 | Create a Dify client that can invoke various capabilities. 12 | 13 | ```go 14 | APIKey := "your_dify_api_key" 15 | APIHost := "http://your-host/v1" 16 | 17 | client, err := dify.CreateDifyClient(dify.DifyClientConfig{Key: APIKey, Host: APIHost}) 18 | if err != nil { 19 | log.Fatalf("failed to create DifyClient: %v\n", err) 20 | return 21 | } 22 | ``` 23 | 24 | see [example](./cmd/main.go). 25 | 26 | ## Dify Client Config 27 | 28 | ```go 29 | type DifyClientConfig struct { 30 | Key string // API Key 31 | Host string // API Host 32 | Timeout int // Client Request Timeout 33 | SkipTLS bool // Skip TLS Certs Verify (self-sign certs) 34 | User string // AppId, for analytics 35 | } 36 | ``` 37 | 38 | ## API: `/completion-messages` 39 | 40 | The most commonly used interface, used to call the model to generate content. 41 | 42 | - CompletionMessages 43 | - CompletionMessagesStreaming 44 | 45 | ```go 46 | payload, err := dify.PrepareCompletionPayload(map[string]interface{}{"query": "hey"}) 47 | if err != nil { 48 | log.Fatalf("failed to prepare payload: %v\n", err) 49 | return 50 | } 51 | 52 | // normal response 53 | completionMessagesResponse, err := client.CompletionMessages(payload, "", nil) 54 | if err != nil { 55 | log.Fatalf("failed to get completion messages: %v\n", err) 56 | return 57 | } 58 | fmt.Println(completionMessagesResponse) 59 | fmt.Println() 60 | 61 | // streaming response 62 | completionMessagesStreamingResponse, err := client.CompletionMessagesStreaming(payload, "", nil) 63 | if err != nil { 64 | log.Fatalf("failed to get completion messages: %v\n", err) 65 | return 66 | } 67 | fmt.Println(completionMessagesStreamingResponse) 68 | fmt.Println() 69 | ``` 70 | 71 | ## API: `/files/upload` 72 | 73 | Upload files to Dify. 74 | 75 | - FileUpload 76 | 77 | ```go 78 | fileUploadResponse, err := client.FileUpload("./README.md", "readme.md") 79 | if err != nil { 80 | log.Fatalf("failed to upload file: %v\n", err) 81 | return 82 | } 83 | fmt.Println(fileUploadResponse) 84 | fmt.Println() 85 | ``` 86 | 87 | ## API: `/completion-messages/:task_id/stop` 88 | 89 | Interface for interrupting streaming output. 90 | 91 | - CompletionMessagesStop 92 | 93 | ```go 94 | completionMessagesStopResponse, err := client.CompletionMessagesStop("0d2bd315-d4de-476f-ad5e-faaa00d571ea") 95 | if err != nil { 96 | log.Fatalf("failed to stop completion messages: %v\n", err) 97 | return 98 | } 99 | fmt.Println(completionMessagesStopResponse) 100 | fmt.Println() 101 | ``` 102 | 103 | ## API: `/messages/:message_id/feedbacks` 104 | 105 | Perform f on the interface output results. 106 | 107 | - MessagesFeedbacks 108 | 109 | ```go 110 | messagesFeedbacksResponse, err := client.MessagesFeedbacks(messageID, "like") 111 | if err != nil { 112 | log.Fatalf("failed to get messages feedbacks: %v\n", err) 113 | return 114 | } 115 | fmt.Println(messagesFeedbacksResponse) 116 | fmt.Println() 117 | ``` 118 | 119 | ## API: `/parameters` 120 | 121 | Get Dify parameters. 122 | 123 | - GetParameters 124 | 125 | ```go 126 | parametersResponse, err := client.GetParameters() 127 | if err != nil { 128 | log.Fatalf("failed to get parameters: %v\n", err) 129 | return 130 | } 131 | fmt.Println(parametersResponse) 132 | fmt.Println() 133 | ``` 134 | 135 | ## API: `/text-to-audio` 136 | 137 | text to audio. 138 | 139 | - TextToAudio 140 | - TextToAudioStreaming 141 | 142 | ```go 143 | textToAudioResponse, err := client.TextToAudio("hello world") 144 | if err != nil { 145 | log.Fatalf("failed to get text to audio: %v\n", err) 146 | return 147 | } 148 | fmt.Println(textToAudioResponse) 149 | fmt.Println() 150 | 151 | textToAudioStreamingResponse, err := client.TextToAudioStreaming("hello world") 152 | if err != nil { 153 | log.Fatalf("failed to get text to audio streaming: %v\n", err) 154 | return 155 | } 156 | fmt.Println(textToAudioStreamingResponse) 157 | fmt.Println() 158 | ``` 159 | -------------------------------------------------------------------------------- /api-audio-to-text.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "mime/multipart" 9 | "net/http" 10 | "os" 11 | "path/filepath" 12 | ) 13 | 14 | type AudioToTextResponse struct { 15 | Text string `json:"text"` 16 | } 17 | 18 | func (dc *DifyClient) AudioToText(filePath string) (result AudioToTextResponse, err error) { 19 | payload := &bytes.Buffer{} 20 | writer := multipart.NewWriter(payload) 21 | 22 | fw, err := writer.CreateFormFile("file", filepath.Base(filePath)) 23 | if err != nil { 24 | return result, fmt.Errorf("error creating form file: %v", err) 25 | } 26 | 27 | fd, err := os.Open(filePath) 28 | if err != nil { 29 | return result, fmt.Errorf("error opening file: %v", err) 30 | } 31 | defer fd.Close() 32 | 33 | _, err = io.Copy(fw, fd) 34 | if err != nil { 35 | return result, fmt.Errorf("error copying file: %v", err) 36 | } 37 | 38 | err = writer.Close() 39 | if err != nil { 40 | return result, fmt.Errorf("error closing writer: %v", err) 41 | } 42 | 43 | req, err := http.NewRequest("POST", dc.GetAPI(API_AUDIO_TO_TEXT), payload) 44 | if err != nil { 45 | return result, fmt.Errorf("error creating request: %v", err) 46 | } 47 | 48 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.Key)) 49 | req.Header.Set("Content-Type", writer.FormDataContentType()) 50 | 51 | resp, err := dc.Client.Do(req) 52 | if err != nil { 53 | return result, fmt.Errorf("error sending request: %v", err) 54 | } 55 | defer resp.Body.Close() 56 | 57 | if resp.StatusCode != 200 { 58 | return result, fmt.Errorf("status code: %d", resp.StatusCode) 59 | } 60 | 61 | body, err := io.ReadAll(resp.Body) 62 | if err != nil { 63 | return result, fmt.Errorf("could not read the body: %v", err) 64 | } 65 | 66 | err = json.Unmarshal(body, &result) 67 | if err != nil { 68 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 69 | } 70 | 71 | return result, nil 72 | } 73 | -------------------------------------------------------------------------------- /api-chat-messages-stop.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type ChatMessagesStopResponse struct { 9 | Result string `json:"result"` 10 | } 11 | 12 | func (dc *DifyClient) ChatMessagesStop(task_id string) (result ChatMessagesStopResponse, err error) { 13 | if task_id == "" { 14 | return result, fmt.Errorf("task_id is required") 15 | } 16 | 17 | payload := map[string]string{ 18 | "user": dc.User, 19 | } 20 | 21 | api := dc.GetAPI(API_CHAT_MESSAGES_STOP) 22 | api = UpdateAPIParam(api, API_PARAM_TASK_ID, task_id) 23 | 24 | code, body, err := SendPostRequestToAPI(dc, api, payload) 25 | 26 | err = CommonRiskForSendRequest(code, err) 27 | if err != nil { 28 | return result, err 29 | } 30 | 31 | err = json.Unmarshal(body, &result) 32 | if err != nil { 33 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 34 | } 35 | return result, nil 36 | } 37 | -------------------------------------------------------------------------------- /api-chat-messages.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type ChatMessagesPayload struct { 9 | Inputs any `json:"inputs"` 10 | Query string `json:"query"` 11 | ResponseMode string `json:"response_mode"` 12 | ConversationID string `json:"conversation_id,omitempty"` 13 | User string `json:"user"` 14 | Files []ChatMessagesPayloadFile `json:"files,omitempty"` 15 | } 16 | 17 | type ChatMessagesPayloadFile struct { 18 | Type string `json:"type"` 19 | TransferMethod string `json:"transfer_method"` 20 | URL string `json:"url,omitempty"` 21 | UploadFileID string `json:"upload_file_id,omitempty"` 22 | } 23 | 24 | type ChatMessagesResponse struct { 25 | Event string `json:"event"` 26 | MessageID string `json:"message_id"` 27 | ConversationID string `json:"conversation_id"` 28 | Mode string `json:"mode"` 29 | Answer string `json:"answer"` 30 | Metadata any `json:"metadata"` 31 | CreatedAt int `json:"created_at"` 32 | } 33 | 34 | func PrepareChatPayload(payload map[string]interface{}) (string, error) { 35 | jsonData, err := json.Marshal(payload) 36 | if err != nil { 37 | return "", err 38 | } 39 | return string(jsonData), nil 40 | } 41 | 42 | func (dc *DifyClient) ChatMessages(inputs string, conversation_id string, files []any) (result ChatMessagesResponse, err error) { 43 | var payload ChatMessagesPayload 44 | 45 | if len(inputs) == 0 { 46 | return result, fmt.Errorf("inputs is required") 47 | } else { 48 | var tryDecode map[string]interface{} 49 | err := json.Unmarshal([]byte(inputs), &tryDecode) 50 | if err != nil { 51 | return result, fmt.Errorf("inputs should be a valid JSON string") 52 | } 53 | payload.Inputs = tryDecode 54 | } 55 | 56 | payload.ResponseMode = RESPONSE_MODE_BLOCKING 57 | payload.User = dc.User 58 | 59 | if conversation_id != "" { 60 | payload.ConversationID = conversation_id 61 | } 62 | 63 | if len(files) > 0 { 64 | // TODO TBD 65 | return result, fmt.Errorf("files are not supported") 66 | } 67 | 68 | api := dc.GetAPI(API_CHAT_MESSAGES) 69 | 70 | code, body, err := SendPostRequestToAPI(dc, api, payload) 71 | 72 | err = CommonRiskForSendRequest(code, err) 73 | if err != nil { 74 | return result, err 75 | } 76 | 77 | err = json.Unmarshal(body, &result) 78 | if err != nil { 79 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 80 | } 81 | return result, nil 82 | } 83 | 84 | func (dc *DifyClient) ChatMessagesStreaming(inputs string, conversation_id string, files []any) (result string, err error) { 85 | var payload ChatMessagesPayload 86 | 87 | if len(inputs) == 0 { 88 | return "", fmt.Errorf("inputs is required") 89 | } else { 90 | var tryDecode map[string]interface{} 91 | err := json.Unmarshal([]byte(inputs), &tryDecode) 92 | if err != nil { 93 | return "", fmt.Errorf("inputs should be a valid JSON string") 94 | } 95 | payload.Inputs = tryDecode 96 | } 97 | 98 | payload.ResponseMode = RESPONSE_MODE_STREAMING 99 | payload.User = dc.User 100 | 101 | if conversation_id != "" { 102 | payload.ConversationID = conversation_id 103 | } 104 | 105 | if len(files) > 0 { 106 | // TODO TBD 107 | return "", fmt.Errorf("files are not supported") 108 | } 109 | 110 | api := dc.GetAPI(API_CHAT_MESSAGES) 111 | 112 | code, body, err := SendPostRequestToAPI(dc, api, payload) 113 | 114 | err = CommonRiskForSendRequest(code, err) 115 | if err != nil { 116 | return result, err 117 | } 118 | 119 | // if !strings.Contains(resp.Header.Get("Content-Type"), "text/event-stream") { 120 | // return "", fmt.Errorf("response is not a streaming response") 121 | // } 122 | 123 | return string(body), nil 124 | } 125 | -------------------------------------------------------------------------------- /api-completion-messages-stop.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type CompletionMessagesStopResponse struct { 9 | Result string `json:"result"` 10 | } 11 | 12 | func (dc *DifyClient) CompletionMessagesStop(task_id string) (result CompletionMessagesStopResponse, err error) { 13 | if task_id == "" { 14 | return result, fmt.Errorf("task_id is required") 15 | } 16 | 17 | payload := map[string]string{ 18 | "user": dc.User, 19 | } 20 | 21 | api := dc.GetAPI(API_COMPLETION_MESSAGES_STOP) 22 | api = UpdateAPIParam(api, API_PARAM_TASK_ID, task_id) 23 | 24 | code, body, err := SendPostRequestToAPI(dc, api, payload) 25 | 26 | err = CommonRiskForSendRequest(code, err) 27 | if err != nil { 28 | return result, err 29 | } 30 | 31 | err = json.Unmarshal(body, &result) 32 | if err != nil { 33 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 34 | } 35 | return result, nil 36 | } 37 | -------------------------------------------------------------------------------- /api-completion-messages.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type CompletionMessagesPayload struct { 9 | Inputs any `json:"inputs"` 10 | ResponseMode string `json:"response_mode,omitempty"` 11 | User string `json:"user"` 12 | ConversationID string `json:"conversation_id,omitempty"` 13 | } 14 | 15 | type CompletionMessagesResponse struct { 16 | Event string `json:"event"` 17 | TaskID string `json:"task_id"` 18 | ID string `json:"id"` 19 | MessageID string `json:"message_id"` 20 | Mode string `json:"mode"` 21 | Answer string `json:"answer"` 22 | Metadata any `json:"metadata"` 23 | CreatedAt int `json:"created_at"` 24 | } 25 | 26 | func PrepareCompletionPayload(payload map[string]interface{}) (string, error) { 27 | jsonData, err := json.Marshal(payload) 28 | if err != nil { 29 | return "", err 30 | } 31 | return string(jsonData), nil 32 | } 33 | 34 | func (dc *DifyClient) CompletionMessages(inputs string, conversation_id string, files []any) (result CompletionMessagesResponse, err error) { 35 | var payload CompletionMessagesPayload 36 | 37 | if len(inputs) == 0 { 38 | return result, fmt.Errorf("inputs is required") 39 | } else { 40 | var tryDecode map[string]interface{} 41 | err := json.Unmarshal([]byte(inputs), &tryDecode) 42 | if err != nil { 43 | return result, fmt.Errorf("inputs should be a valid JSON string") 44 | } 45 | payload.Inputs = tryDecode 46 | } 47 | 48 | payload.ResponseMode = RESPONSE_MODE_BLOCKING 49 | payload.User = dc.User 50 | 51 | if conversation_id != "" { 52 | payload.ConversationID = conversation_id 53 | } 54 | 55 | if len(files) > 0 { 56 | // TODO TBD 57 | return result, fmt.Errorf("files are not supported") 58 | } 59 | 60 | api := dc.GetAPI(API_COMPLETION_MESSAGES) 61 | code, body, err := SendPostRequestToAPI(dc, api, payload) 62 | 63 | err = CommonRiskForSendRequest(code, err) 64 | if err != nil { 65 | return result, err 66 | } 67 | 68 | err = json.Unmarshal(body, &result) 69 | if err != nil { 70 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 71 | } 72 | return result, nil 73 | } 74 | 75 | func (dc *DifyClient) CompletionMessagesStreaming(inputs string, conversation_id string, files []any) (result string, err error) { 76 | var payload CompletionMessagesPayload 77 | 78 | if len(inputs) == 0 { 79 | return "", fmt.Errorf("inputs is required") 80 | } else { 81 | var tryDecode map[string]interface{} 82 | err := json.Unmarshal([]byte(inputs), &tryDecode) 83 | if err != nil { 84 | return "", fmt.Errorf("inputs should be a valid JSON string") 85 | } 86 | payload.Inputs = tryDecode 87 | } 88 | 89 | payload.ResponseMode = RESPONSE_MODE_STREAMING 90 | payload.User = dc.User 91 | 92 | if conversation_id != "" { 93 | payload.ConversationID = conversation_id 94 | } 95 | 96 | if len(files) > 0 { 97 | // TODO TBD 98 | return "", fmt.Errorf("files are not supported") 99 | } 100 | 101 | api := dc.GetAPI(API_COMPLETION_MESSAGES) 102 | code, body, err := SendPostRequestToAPI(dc, api, payload) 103 | 104 | err = CommonRiskForSendRequest(code, err) 105 | if err != nil { 106 | return result, err 107 | } 108 | 109 | // if !strings.Contains(resp.Header.Get("Content-Type"), "text/event-stream") { 110 | // return "", fmt.Errorf("response is not a streaming response") 111 | // } 112 | 113 | return string(body), nil 114 | } 115 | -------------------------------------------------------------------------------- /api-conversations.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "net/http" 9 | ) 10 | 11 | type ConversationsResponse struct { 12 | Limit int `json:"limit"` 13 | HasMore bool `json:"has_more"` 14 | Data []struct { 15 | ID string `json:"id"` 16 | Name string `json:"name,omitempty"` 17 | Inputs struct { 18 | Book string `json:"book"` 19 | MyName string `json:"myName"` 20 | } `json:"inputs,omitempty"` 21 | Status string `json:"status,omitempty"` 22 | CreatedAt int `json:"created_at,omitempty"` 23 | } `json:"data"` 24 | } 25 | 26 | func (dc *DifyClient) Conversations(last_id string, limit int) (result ConversationsResponse, err error) { 27 | payloadLimit := "" 28 | if limit <= 0 { 29 | limit = 20 30 | } 31 | payloadLimit = fmt.Sprintf("%d", limit) 32 | 33 | payloadBody := map[string]string{ 34 | "user": dc.User, 35 | "last_id": last_id, 36 | "limit": payloadLimit, 37 | } 38 | 39 | api := dc.GetAPI(API_CONVERSATIONS) 40 | 41 | code, body, err := SendPostRequestToAPI(dc, api, payloadBody) 42 | 43 | err = CommonRiskForSendRequest(code, err) 44 | if err != nil { 45 | return result, err 46 | } 47 | 48 | err = json.Unmarshal(body, &result) 49 | if err != nil { 50 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 51 | } 52 | return result, nil 53 | } 54 | 55 | type DeleteConversationsResponse struct { 56 | Result string `json:"result"` 57 | } 58 | 59 | func (dc *DifyClient) DeleteConversation(conversation_id string) (result DeleteConversationsResponse, err error) { 60 | if conversation_id == "" { 61 | return result, fmt.Errorf("conversation_id is required") 62 | } 63 | 64 | payloadBody := map[string]string{ 65 | "user": dc.User, 66 | } 67 | 68 | api := dc.GetAPI(API_CONVERSATIONS_DELETE) 69 | api = UpdateAPIParam(api, API_PARAM_CONVERSATION_ID, conversation_id) 70 | 71 | buf, err := json.Marshal(payloadBody) 72 | if err != nil { 73 | return result, err 74 | } 75 | req, err := http.NewRequest("DELETE", api, bytes.NewBuffer(buf)) 76 | if err != nil { 77 | return result, fmt.Errorf("could not create a new request: %v", err) 78 | } 79 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.Key)) 80 | req.Header.Set("Content-Type", "application/json") 81 | 82 | resp, err := dc.Client.Do(req) 83 | if err != nil { 84 | return result, err 85 | } 86 | defer resp.Body.Close() 87 | 88 | if resp.StatusCode != 200 { 89 | bodyText, err := io.ReadAll(resp.Body) 90 | if err != nil { 91 | return result, fmt.Errorf("status code: %d, could not read the body", resp.StatusCode) 92 | } 93 | return result, fmt.Errorf("status code: %d, %s", resp.StatusCode, bodyText) 94 | } 95 | 96 | bodyText, err := io.ReadAll(resp.Body) 97 | if err != nil { 98 | return result, err 99 | } 100 | 101 | err = json.Unmarshal(bodyText, &result) 102 | if err != nil { 103 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 104 | } 105 | return result, nil 106 | } 107 | 108 | type RenameConversationsResponse struct { 109 | Result string `json:"result"` 110 | } 111 | 112 | func (dc *DifyClient) RenameConversation(conversation_id string) (result RenameConversationsResponse, err error) { 113 | if conversation_id == "" { 114 | return result, fmt.Errorf("conversation_id is required") 115 | } 116 | 117 | payload := map[string]string{ 118 | "user": dc.User, 119 | } 120 | 121 | api := dc.GetAPI(API_CONVERSATIONS_RENAME) 122 | api = UpdateAPIParam(api, API_PARAM_CONVERSATION_ID, conversation_id) 123 | 124 | code, body, err := SendPostRequestToAPI(dc, api, payload) 125 | 126 | err = CommonRiskForSendRequest(code, err) 127 | if err != nil { 128 | return result, err 129 | } 130 | 131 | err = json.Unmarshal(body, &result) 132 | if err != nil { 133 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 134 | } 135 | return result, nil 136 | } 137 | -------------------------------------------------------------------------------- /api-file-upload.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "mime/multipart" 9 | "net/http" 10 | "os" 11 | ) 12 | 13 | type FileUploadResponse struct { 14 | ID string `json:"id"` 15 | Name string `json:"name"` 16 | Size int `json:"size"` 17 | Extension string `json:"extension"` 18 | MimeType string `json:"mime_type"` 19 | CreatedBy string `json:"created_by"` 20 | CreatedAt int `json:"created_at"` 21 | } 22 | 23 | func (dc *DifyClient) FileUpload(filePath string, fileName string) (result FileUploadResponse, err error) { 24 | file, err := os.Open(filePath) 25 | if err != nil { 26 | return result, fmt.Errorf("error opening file: %v", err) 27 | } 28 | defer file.Close() 29 | 30 | body := &bytes.Buffer{} 31 | writer := multipart.NewWriter(body) 32 | 33 | part, err := writer.CreateFormFile("file", fileName) 34 | if err != nil { 35 | return result, fmt.Errorf("error creating form file: %v", err) 36 | } 37 | _, err = io.Copy(part, file) 38 | if err != nil { 39 | return result, fmt.Errorf("error copying file: %v", err) 40 | } 41 | 42 | _ = writer.WriteField("user", dc.User) 43 | err = writer.Close() 44 | if err != nil { 45 | return result, fmt.Errorf("error closing writer: %v", err) 46 | } 47 | 48 | req, err := http.NewRequest("POST", dc.GetAPI(API_FILE_UPLOAD), body) 49 | if err != nil { 50 | return result, fmt.Errorf("error creating request: %v", err) 51 | } 52 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.Key)) 53 | req.Header.Set("Content-Type", writer.FormDataContentType()) 54 | 55 | client := &http.Client{} 56 | resp, err := client.Do(req) 57 | if err != nil { 58 | return result, fmt.Errorf("error sending request: %v", err) 59 | } 60 | defer resp.Body.Close() 61 | 62 | if resp.StatusCode != 201 { 63 | return result, fmt.Errorf("status code: %d, create file failed", resp.StatusCode) 64 | } 65 | 66 | bodyText, err := io.ReadAll(resp.Body) 67 | if err != nil { 68 | return result, fmt.Errorf("could not read the body: %v", err) 69 | } 70 | 71 | err = json.Unmarshal(bodyText, &result) 72 | if err != nil { 73 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 74 | } 75 | return result, nil 76 | } 77 | -------------------------------------------------------------------------------- /api-messages-feedacks.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type MessagesFeedbacksResponse struct { 9 | Result string `json:"result"` 10 | } 11 | 12 | func (dc *DifyClient) MessagesFeedbacks(message_id string, rating string) (result MessagesFeedbacksResponse, err error) { 13 | if message_id == "" { 14 | return result, fmt.Errorf("message_id is required") 15 | } 16 | 17 | payload := map[string]string{ 18 | "user": dc.User, 19 | "rating": rating, 20 | } 21 | 22 | api := dc.GetAPI(API_MESSAGES_FEEDBACKS) 23 | api = UpdateAPIParam(api, API_PARAM_MESSAGE_ID, message_id) 24 | 25 | code, body, err := SendPostRequestToAPI(dc, api, payload) 26 | 27 | err = CommonRiskForSendRequest(code, err) 28 | 29 | if err != nil { 30 | return result, err 31 | } 32 | 33 | err = json.Unmarshal(body, &result) 34 | if err != nil { 35 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 36 | } 37 | return result, nil 38 | } 39 | -------------------------------------------------------------------------------- /api-messages-suggested.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type MessagesSuggestedResponse struct { 9 | Result string `json:"result"` 10 | Data []string `json:"data"` 11 | } 12 | 13 | func (dc *DifyClient) MessagesSuggested(message_id string) (result MessagesSuggestedResponse, err error) { 14 | if message_id == "" { 15 | return result, fmt.Errorf("message_id is required") 16 | } 17 | 18 | payload := map[string]string{ 19 | "user": dc.User, 20 | } 21 | 22 | api := dc.GetAPI(API_MESSAGES_SUGGESTED) 23 | api = UpdateAPIParam(api, API_PARAM_MESSAGE_ID, message_id) 24 | 25 | code, body, err := SendPostRequestToAPI(dc, api, payload) 26 | 27 | err = CommonRiskForSendRequest(code, err) 28 | if err != nil { 29 | return result, err 30 | } 31 | 32 | err = json.Unmarshal(body, &result) 33 | if err != nil { 34 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 35 | } 36 | return result, nil 37 | } 38 | -------------------------------------------------------------------------------- /api-messages.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type MessagesResponse struct { 9 | Limit int `json:"limit"` 10 | HasMore bool `json:"has_more"` 11 | Data []struct { 12 | ID string `json:"id"` 13 | ConversationID string `json:"conversation_id"` 14 | Inputs struct { 15 | Name string `json:"name"` 16 | } `json:"inputs"` 17 | Query string `json:"query"` 18 | Answer string `json:"answer"` 19 | MessageFiles []any `json:"message_files"` 20 | Feedback any `json:"feedback"` 21 | RetrieverResources []struct { 22 | Position int `json:"position"` 23 | DatasetID string `json:"dataset_id"` 24 | DatasetName string `json:"dataset_name"` 25 | DocumentID string `json:"document_id"` 26 | DocumentName string `json:"document_name"` 27 | SegmentID string `json:"segment_id"` 28 | Score float64 `json:"score"` 29 | Content string `json:"content"` 30 | } `json:"retriever_resources"` 31 | AgentThoughts []any `json:"agent_thoughts"` 32 | CreatedAt int `json:"created_at"` 33 | } `json:"data"` 34 | } 35 | 36 | func (dc *DifyClient) Messages(conversation_id string) (result MessagesResponse, err error) { 37 | if conversation_id == "" { 38 | return result, fmt.Errorf("conversation_id is required") 39 | } 40 | 41 | payloadBody := map[string]string{ 42 | "user": dc.User, 43 | "conversation_id": conversation_id, 44 | } 45 | 46 | api := dc.GetAPI(API_MESSAGES) 47 | 48 | code, body, err := SendPostRequestToAPI(dc, api, payloadBody) 49 | 50 | err = CommonRiskForSendRequest(code, err) 51 | if err != nil { 52 | return result, err 53 | } 54 | 55 | err = json.Unmarshal(body, &result) 56 | if err != nil { 57 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 58 | } 59 | return result, nil 60 | } 61 | -------------------------------------------------------------------------------- /api-meta.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type GetMetaResponse struct { 9 | ToolIcons struct { 10 | Dalle2 string `json:"dalle2"` 11 | APITool struct { 12 | Background string `json:"background"` 13 | Content string `json:"content"` 14 | } `json:"api_tool"` 15 | } `json:"tool_icons"` 16 | } 17 | 18 | func (dc *DifyClient) GetMeta() (result GetMetaResponse, err error) { 19 | api := dc.GetAPI(API_META) 20 | code, body, err := SendGetRequestToAPI(dc, api) 21 | 22 | err = CommonRiskForSendRequest(code, err) 23 | if err != nil { 24 | return result, err 25 | } 26 | 27 | err = json.Unmarshal(body, &result) 28 | if err != nil { 29 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 30 | } 31 | return result, nil 32 | } 33 | -------------------------------------------------------------------------------- /api-parameters.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type GetParametersResponse struct { 9 | OpeningStatement string `json:"opening_statement"` 10 | SuggestedQuestions []any `json:"suggested_questions"` 11 | SuggestedQuestionsAfterAnswer struct { 12 | Enabled bool `json:"enabled"` 13 | } `json:"suggested_questions_after_answer"` 14 | SpeechToText struct { 15 | Enabled bool `json:"enabled"` 16 | } `json:"speech_to_text"` 17 | TextToSpeech struct { 18 | Enabled bool `json:"enabled"` 19 | Voice string `json:"voice"` 20 | Language string `json:"language"` 21 | } `json:"text_to_speech"` 22 | RetrieverResource struct { 23 | Enabled bool `json:"enabled"` 24 | } `json:"retriever_resource"` 25 | AnnotationReply struct { 26 | Enabled bool `json:"enabled"` 27 | } `json:"annotation_reply"` 28 | MoreLikeThis struct { 29 | Enabled bool `json:"enabled"` 30 | } `json:"more_like_this"` 31 | UserInputForm []struct { 32 | Paragraph struct { 33 | Label string `json:"label"` 34 | Variable string `json:"variable"` 35 | Required bool `json:"required"` 36 | Default string `json:"default"` 37 | } `json:"paragraph"` 38 | } `json:"user_input_form"` 39 | SensitiveWordAvoidance struct { 40 | Enabled bool `json:"enabled"` 41 | Type string `json:"type"` 42 | Configs []any `json:"configs"` 43 | } `json:"sensitive_word_avoidance"` 44 | FileUpload struct { 45 | Image struct { 46 | Enabled bool `json:"enabled"` 47 | NumberLimits int `json:"number_limits"` 48 | Detail string `json:"detail"` 49 | TransferMethods []string `json:"transfer_methods"` 50 | } `json:"image"` 51 | } `json:"file_upload"` 52 | SystemParameters struct { 53 | ImageFileSizeLimit string `json:"image_file_size_limit"` 54 | } `json:"system_parameters"` 55 | } 56 | 57 | func (dc *DifyClient) GetParameters() (result GetParametersResponse, err error) { 58 | api := dc.GetAPI(API_PARAMETERS) 59 | code, body, err := SendGetRequestToAPI(dc, api) 60 | 61 | err = CommonRiskForSendRequest(code, err) 62 | if err != nil { 63 | return result, err 64 | } 65 | 66 | err = json.Unmarshal(body, &result) 67 | if err != nil { 68 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 69 | } 70 | return result, nil 71 | } 72 | -------------------------------------------------------------------------------- /api-text-to-audio.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "mime/multipart" 8 | "net/http" 9 | ) 10 | 11 | func (dc *DifyClient) TextToAudio(text string) (result any, err error) { 12 | payload := &bytes.Buffer{} 13 | writer := multipart.NewWriter(payload) 14 | _ = writer.WriteField("text", text) 15 | _ = writer.WriteField("user", dc.User) 16 | _ = writer.WriteField("streaming", "false") 17 | err = writer.Close() 18 | if err != nil { 19 | return result, fmt.Errorf("error closing writer: %v", err) 20 | } 21 | 22 | req, err := http.NewRequest("POST", dc.GetAPI(API_TEXT_TO_AUDIO), payload) 23 | if err != nil { 24 | return result, fmt.Errorf("error creating request: %v", err) 25 | } 26 | 27 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.Key)) 28 | req.Header.Set("Content-Type", writer.FormDataContentType()) 29 | 30 | resp, err := dc.Client.Do(req) 31 | if err != nil { 32 | return result, fmt.Errorf("error sending request: %v", err) 33 | } 34 | defer resp.Body.Close() 35 | 36 | if resp.StatusCode != 200 { 37 | return result, fmt.Errorf("status code: %d", resp.StatusCode) 38 | } 39 | 40 | body, err := io.ReadAll(resp.Body) 41 | if err != nil { 42 | return result, fmt.Errorf("could not read the body: %v", err) 43 | } 44 | return body, nil 45 | } 46 | 47 | func (dc *DifyClient) TextToAudioStreaming(text string) (result any, err error) { 48 | payload := &bytes.Buffer{} 49 | writer := multipart.NewWriter(payload) 50 | _ = writer.WriteField("text", text) 51 | _ = writer.WriteField("user", dc.User) 52 | _ = writer.WriteField("streaming", "true") 53 | err = writer.Close() 54 | if err != nil { 55 | return result, fmt.Errorf("error closing writer: %v", err) 56 | } 57 | 58 | req, err := http.NewRequest("POST", dc.GetAPI(API_TEXT_TO_AUDIO), payload) 59 | if err != nil { 60 | return result, fmt.Errorf("error creating request: %v", err) 61 | } 62 | 63 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.Key)) 64 | req.Header.Set("Content-Type", writer.FormDataContentType()) 65 | 66 | resp, err := dc.Client.Do(req) 67 | if err != nil { 68 | return result, fmt.Errorf("error sending request: %v", err) 69 | } 70 | defer resp.Body.Close() 71 | 72 | if resp.StatusCode != 200 { 73 | return result, fmt.Errorf("status code: %d", resp.StatusCode) 74 | } 75 | 76 | body, err := io.ReadAll(resp.Body) 77 | if err != nil { 78 | return result, fmt.Errorf("could not read the body: %v", err) 79 | } 80 | return body, nil 81 | } 82 | -------------------------------------------------------------------------------- /api.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import "strings" 4 | 5 | const ( 6 | API_COMPLETION_MESSAGES = "/completion-messages" 7 | API_COMPLETION_MESSAGES_STOP = "/completion-messages/:task_id/stop" 8 | 9 | API_CHAT_MESSAGES = "/chat-messages" 10 | API_CHAT_MESSAGES_STOP = "/chat-messages/:task_id/stop" 11 | 12 | API_MESSAGES = "/messages" 13 | API_MESSAGES_SUGGESTED = "/messages/:message_id/suggested" 14 | API_MESSAGES_FEEDBACKS = "/messages/:message_id/feedbacks" 15 | 16 | API_CONVERSATIONS = "/conversations" 17 | API_CONVERSATIONS_DELETE = "/conversations/:conversation_id" 18 | API_CONVERSATIONS_RENAME = "/conversations/:conversation_id/name" 19 | 20 | API_FILE_UPLOAD = "/files/upload" 21 | API_PARAMETERS = "/parameters" 22 | API_META = "/meta" 23 | 24 | API_AUDIO_TO_TEXT = "/audio-to-text" 25 | API_TEXT_TO_AUDIO = "/text-to-audio" 26 | 27 | API_PARAM_TASK_ID = ":task_id" 28 | API_PARAM_MESSAGE_ID = ":message_id" 29 | API_PARAM_CONVERSATION_ID = ":conversation_id" 30 | 31 | CONSOLE_API_FILE_UPLOAD = "/files/upload?source=datasets" 32 | CONSOLE_API_LOGIN = "/login" 33 | 34 | CONSOLE_API_PARAM_DATASETS_ID = ":datasets_id" 35 | 36 | CONSOLE_API_DATASETS_CREATE = "/datasets" 37 | CONSOLE_API_DATASETS_LIST = "/datasets" 38 | CONSOLE_API_DATASETS_DELETE = "/datasets/:datasets_id" 39 | CONSOLE_API_DATASETS_INIT = "/datasets/init" 40 | CONSOLE_API_DATASETS_INIT_STATUS = "/datasets/:datasets_id/indexing-status" 41 | 42 | CONSOLE_API_WORKSPACES_RERANK_MODEL = "/workspaces/current/models/model-types/rerank" 43 | CONSOLE_API_CURRENT_WORKSPACE_RERANK_MODEL = "/workspaces/current/default-model?model_type=rerank" 44 | ) 45 | 46 | func (dc *DifyClient) GetAPI(api string) string { 47 | return dc.Host + api 48 | } 49 | 50 | func (dc *DifyClient) GetConsoleAPI(api string) string { 51 | return dc.ConsoleHost + api 52 | } 53 | 54 | func UpdateAPIParam(api, key, value string) string { 55 | return strings.ReplaceAll(api, key, value) 56 | } 57 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "net/http" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type DifyClientConfig struct { 12 | Key string 13 | Host string 14 | ConsoleHost string 15 | Timeout int 16 | SkipTLS bool 17 | User string 18 | } 19 | 20 | type DifyClient struct { 21 | Key string 22 | Host string 23 | ConsoleHost string 24 | ConsoleToken string 25 | Timeout time.Duration 26 | SkipTLS bool 27 | Client *http.Client 28 | User string 29 | } 30 | 31 | func CreateDifyClient(config DifyClientConfig) (*DifyClient, error) { 32 | key := strings.TrimSpace(config.Key) 33 | if key == "" { 34 | return nil, fmt.Errorf("dify API Key is required") 35 | } 36 | 37 | host := strings.TrimSpace(config.Host) 38 | if host == "" { 39 | return nil, fmt.Errorf("dify Host is required") 40 | } 41 | 42 | consoleURL := strings.TrimSpace(config.ConsoleHost) 43 | if consoleURL == "" { 44 | consoleURL = strings.ReplaceAll(host, "/v1", "/console/api") 45 | fmt.Println("Console URL is not provided, use default value", consoleURL) 46 | } 47 | 48 | timeout := 0 * time.Second 49 | if config.Timeout <= 0 { 50 | if config.Timeout < 0 { 51 | fmt.Println("Timeout should be a positive number, reset to default value: 10s") 52 | } 53 | timeout = DEFAULT_TIMEOUT * time.Second 54 | } 55 | 56 | skipTLS := false 57 | if config.SkipTLS { 58 | skipTLS = true 59 | } 60 | 61 | config.User = strings.TrimSpace(config.User) 62 | if config.User == "" { 63 | config.User = DEFAULT_USER 64 | } 65 | 66 | var client *http.Client 67 | 68 | if skipTLS { 69 | client = &http.Client{Transport: &http.Transport{ 70 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 71 | }} 72 | } else { 73 | client = &http.Client{} 74 | } 75 | 76 | if timeout > 0 { 77 | client.Timeout = timeout 78 | } 79 | 80 | return &DifyClient{ 81 | Key: key, 82 | Host: host, 83 | ConsoleHost: consoleURL, 84 | Timeout: timeout, 85 | SkipTLS: skipTLS, 86 | Client: client, 87 | User: config.User, 88 | }, nil 89 | } 90 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | dify "github.com/soulteary/dify-go-sdk" 9 | ) 10 | 11 | func main() { 12 | APIKey := os.Getenv("DIFY_API_KEY") 13 | if APIKey == "" { 14 | fmt.Println("DIFY_API_KEY is required") 15 | return 16 | } 17 | 18 | APIHost := os.Getenv("DIFY_API_HOST") 19 | if APIHost == "" { 20 | fmt.Println("DIFY_API_HOST is required") 21 | return 22 | } 23 | 24 | ConsoleHost := os.Getenv("DIFY_CONSOLE_HOST") 25 | 26 | client, err := dify.CreateDifyClient(dify.DifyClientConfig{Key: APIKey, Host: APIHost, ConsoleHost: ConsoleHost}) 27 | if err != nil { 28 | log.Fatalf("failed to create DifyClient: %v\n", err) 29 | return 30 | } 31 | 32 | metas, err := client.GetMeta() 33 | if err != nil { 34 | log.Fatalf("failed to get meta: %v\n", err) 35 | return 36 | } 37 | fmt.Println(metas) 38 | 39 | parametersResponse, err := client.GetParameters() 40 | if err != nil { 41 | log.Fatalf("failed to get parameters: %v\n", err) 42 | return 43 | } 44 | fmt.Println(parametersResponse) 45 | 46 | msgID := CompletionMessages(client) 47 | FileUpload(client) 48 | CompletionMessagesStop(client) 49 | MessagesFeedbacks(client, msgID) 50 | // TextToAudio(client) 51 | 52 | CONSOLE_USER := os.Getenv("DIFY_CONSOLE_USER") 53 | CONSOLE_PASS := os.Getenv("DIFY_CONSOLE_PASS") 54 | if CONSOLE_USER != "" && CONSOLE_PASS != "" { 55 | log.Println("Get Console Token") 56 | token := GetUserToken(client, CONSOLE_USER, CONSOLE_PASS) 57 | if token == "" { 58 | log.Fatalf("failed to get console token\n") 59 | } 60 | client.ConsoleToken = token 61 | 62 | // Create datasets 63 | var datasetsID string 64 | log.Println("Create datasets") 65 | createResult, err := client.CreateDatasets("test datasets") 66 | if err != nil { 67 | log.Fatalf("failed to create datasets: %v\n", err) 68 | return 69 | } 70 | datasetsID = createResult.ID 71 | log.Println(createResult) 72 | 73 | // List datasets 74 | log.Println("List datasets") 75 | ListResult, err := client.ListDatasets(1, 30) 76 | if err != nil { 77 | log.Fatalf("failed to list datasets: %v\n", err) 78 | return 79 | } 80 | if len(ListResult.Data) == 0 { 81 | log.Fatalf("no datasets found\n") 82 | return 83 | } 84 | for _, dataset := range ListResult.Data { 85 | if dataset.ID == datasetsID { 86 | // Delete datasets 87 | log.Println("Delete datasets") 88 | result, err := client.DeleteDatasets(datasetsID) 89 | if err != nil { 90 | log.Fatalf("failed to delete datasets: %v\n", err) 91 | return 92 | } 93 | log.Println(result) 94 | } 95 | } 96 | 97 | // Get the list of rerank models 98 | log.Println("List rerank models") 99 | reRankModels, err := client.ListWorkspacesRerankModels() 100 | if err != nil { 101 | log.Println("failed to list rerank models:", err) 102 | } else { 103 | log.Println(reRankModels) 104 | } 105 | 106 | log.Println("Upload file to datasets") 107 | err = os.WriteFile("testfile-for-dify-database.txt", []byte("test file for dify database"), 0644) 108 | if err != nil { 109 | log.Fatalf("failed to create file: %v\n", err) 110 | return 111 | } 112 | result, err := client.DatasetsFileUpload("testfile-for-dify-database.txt", "testfile-for-dify-database.txt") 113 | if err != nil { 114 | log.Fatalf("failed to upload file to datasets: %v\n", err) 115 | return 116 | } 117 | fileID := result.ID 118 | log.Println(result) 119 | 120 | initResult, err := client.InitDatasetsByUploadFile([]string{fileID}) 121 | if err != nil { 122 | log.Fatalf("failed to init datasets by upload file: %v\n", err) 123 | return 124 | } 125 | log.Println(initResult) 126 | 127 | initStatus, err := client.InitDatasetsIndexingStatus(initResult.Dataset.ID) 128 | if err != nil { 129 | log.Fatalf("failed to get init datasets indexing status: %v\n", err) 130 | return 131 | } 132 | log.Println(initStatus) 133 | } 134 | } 135 | 136 | func CompletionMessages(client *dify.DifyClient) (messageID string) { 137 | payload, err := dify.PrepareCompletionPayload(map[string]interface{}{"query": "hey"}) 138 | if err != nil { 139 | log.Fatalf("failed to prepare payload: %v\n", err) 140 | return 141 | } 142 | 143 | // normal response 144 | completionMessagesResponse, err := client.CompletionMessages(payload, "", nil) 145 | if err != nil { 146 | log.Fatalf("failed to get completion messages: %v\n", err) 147 | return 148 | } 149 | fmt.Println(completionMessagesResponse) 150 | fmt.Println() 151 | 152 | // streaming response 153 | completionMessagesStreamingResponse, err := client.CompletionMessagesStreaming(payload, "", nil) 154 | if err != nil { 155 | log.Fatalf("failed to get completion messages: %v\n", err) 156 | return 157 | } 158 | fmt.Println(completionMessagesStreamingResponse) 159 | fmt.Println() 160 | 161 | return completionMessagesResponse.MessageID 162 | } 163 | 164 | func FileUpload(client *dify.DifyClient) { 165 | fileUploadResponse, err := client.FileUpload("./README.md", "readme.md") 166 | if err != nil { 167 | log.Fatalf("failed to upload file: %v\n", err) 168 | return 169 | } 170 | fmt.Println(fileUploadResponse) 171 | fmt.Println() 172 | } 173 | 174 | func CompletionMessagesStop(client *dify.DifyClient) { 175 | completionMessagesStopResponse, err := client.CompletionMessagesStop("0d2bd315-d4de-476f-ad5e-faaa00d571ea") 176 | if err != nil { 177 | log.Fatalf("failed to stop completion messages: %v\n", err) 178 | return 179 | } 180 | fmt.Println(completionMessagesStopResponse) 181 | fmt.Println() 182 | } 183 | 184 | func MessagesFeedbacks(client *dify.DifyClient, messageID string) { 185 | messagesFeedbacksResponse, err := client.MessagesFeedbacks(messageID, "like") 186 | if err != nil { 187 | log.Fatalf("failed to get messages feedbacks: %v\n", err) 188 | return 189 | } 190 | fmt.Println(messagesFeedbacksResponse) 191 | fmt.Println() 192 | } 193 | 194 | func TextToAudio(client *dify.DifyClient) { 195 | textToAudioResponse, err := client.TextToAudio("hello world") 196 | if err != nil { 197 | log.Fatalf("failed to get text to audio: %v\n", err) 198 | return 199 | } 200 | fmt.Println(textToAudioResponse) 201 | fmt.Println() 202 | 203 | textToAudioStreamingResponse, err := client.TextToAudioStreaming("hello world") 204 | if err != nil { 205 | log.Fatalf("failed to get text to audio streaming: %v\n", err) 206 | return 207 | } 208 | fmt.Println(textToAudioStreamingResponse) 209 | fmt.Println() 210 | } 211 | 212 | func GetUserToken(client *dify.DifyClient, email, password string) string { 213 | result, err := client.UserLogin(email, password) 214 | if err != nil { 215 | log.Fatalf("failed to login: %v\n", err) 216 | return "" 217 | } 218 | return result.Data 219 | } 220 | -------------------------------------------------------------------------------- /console-datasets-file-upload.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "mime/multipart" 9 | "net/http" 10 | "os" 11 | ) 12 | 13 | func (dc *DifyClient) DatasetsFileUpload(filePath string, fileName string) (result FileUploadResponse, err error) { 14 | file, err := os.Open(filePath) 15 | if err != nil { 16 | return result, fmt.Errorf("error opening file: %v", err) 17 | } 18 | defer file.Close() 19 | 20 | body := &bytes.Buffer{} 21 | writer := multipart.NewWriter(body) 22 | 23 | part, err := writer.CreateFormFile("file", fileName) 24 | if err != nil { 25 | return result, fmt.Errorf("error creating form file: %v", err) 26 | } 27 | _, err = io.Copy(part, file) 28 | if err != nil { 29 | return result, fmt.Errorf("error copying file: %v", err) 30 | } 31 | 32 | _ = writer.WriteField("user", dc.User) 33 | err = writer.Close() 34 | if err != nil { 35 | return result, fmt.Errorf("error closing writer: %v", err) 36 | } 37 | 38 | req, err := http.NewRequest("POST", dc.GetConsoleAPI(CONSOLE_API_FILE_UPLOAD), body) 39 | if err != nil { 40 | return result, fmt.Errorf("error creating request: %v", err) 41 | } 42 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.ConsoleToken)) 43 | req.Header.Set("Content-Type", writer.FormDataContentType()) 44 | 45 | client := &http.Client{} 46 | resp, err := client.Do(req) 47 | if err != nil { 48 | return result, fmt.Errorf("error sending request: %v", err) 49 | } 50 | defer resp.Body.Close() 51 | 52 | if resp.StatusCode != 201 { 53 | return result, fmt.Errorf("status code: %d, create file failed", resp.StatusCode) 54 | } 55 | 56 | bodyText, err := io.ReadAll(resp.Body) 57 | if err != nil { 58 | return result, fmt.Errorf("could not read the body: %v", err) 59 | } 60 | 61 | err = json.Unmarshal(bodyText, &result) 62 | if err != nil { 63 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 64 | } 65 | return result, nil 66 | } 67 | -------------------------------------------------------------------------------- /console-datasets-init.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type InitDatasetsPayload struct { 9 | DataSource InitDatasetsPayloadDataSource `json:"data_source"` 10 | IndexingTechnique string `json:"indexing_technique"` 11 | ProcessRule InitDatasetsPayloadProcessRule `json:"process_rule"` 12 | DocForm string `json:"doc_form"` 13 | DocLanguage string `json:"doc_language"` 14 | RetrievalModel InitDatasetsPayloadRetrievalModel `json:"retrieval_model"` 15 | } 16 | 17 | type InitDatasetsPayloadDataSource struct { 18 | Type string `json:"type"` 19 | InfoList InitDatasetsPayloadDataSourceInfoList `json:"info_list"` 20 | } 21 | 22 | type InitDatasetsPayloadDataSourceInfoList struct { 23 | DataSourceType string `json:"data_source_type"` 24 | FileInfoList InitDatasetsPayloadDataSourceFileInfoList `json:"file_info_list"` 25 | } 26 | 27 | type InitDatasetsPayloadDataSourceFileInfoList struct { 28 | FileIds []string `json:"file_ids"` 29 | } 30 | 31 | type InitDatasetsResponse struct { 32 | Dataset InitDatasetsResponseDataset `json:"dataset"` 33 | Documents []InitDatasetsResponseDatasetDocument `json:"documents"` 34 | Batch string `json:"batch"` 35 | } 36 | 37 | type InitDatasetsPayloadProcessRule struct { 38 | Rules struct { 39 | } `json:"rules"` 40 | Mode string `json:"mode"` 41 | } 42 | 43 | type InitDatasetsPayloadRetrievalModel struct { 44 | SearchMethod string `json:"search_method"` 45 | RerankingEnable bool `json:"reranking_enable"` 46 | RerankingModel InitDatasetsPayloadRerankingModel `json:"reranking_model"` 47 | TopK int `json:"top_k"` 48 | ScoreThresholdEnabled bool `json:"score_threshold_enabled"` 49 | ScoreThreshold float64 `json:"score_threshold"` 50 | } 51 | 52 | type InitDatasetsPayloadRerankingModel struct { 53 | RerankingProviderName string `json:"reranking_provider_name"` 54 | RerankingModelName string `json:"reranking_model_name"` 55 | } 56 | 57 | type InitDatasetsResponseDataset struct { 58 | ID string `json:"id"` 59 | Name string `json:"name"` 60 | Description string `json:"description"` 61 | Permission string `json:"permission"` 62 | DataSourceType string `json:"data_source_type"` 63 | IndexingTechnique string `json:"indexing_technique"` 64 | CreatedBy string `json:"created_by"` 65 | CreatedAt int `json:"created_at"` 66 | } 67 | 68 | type InitDatasetsResponseDatasetDocument struct { 69 | ID string `json:"id"` 70 | Position int `json:"position"` 71 | DataSourceType string `json:"data_source_type"` 72 | DataSourceInfo struct { 73 | UploadFileID string `json:"upload_file_id"` 74 | } `json:"data_source_info"` 75 | DatasetProcessRuleID string `json:"dataset_process_rule_id"` 76 | Name string `json:"name"` 77 | CreatedFrom string `json:"created_from"` 78 | CreatedBy string `json:"created_by"` 79 | CreatedAt int `json:"created_at"` 80 | Tokens int `json:"tokens"` 81 | IndexingStatus string `json:"indexing_status"` 82 | Error any `json:"error"` 83 | Enabled bool `json:"enabled"` 84 | DisabledAt any `json:"disabled_at"` 85 | DisabledBy any `json:"disabled_by"` 86 | Archived bool `json:"archived"` 87 | DisplayStatus string `json:"display_status"` 88 | WordCount int `json:"word_count"` 89 | HitCount int `json:"hit_count"` 90 | DocForm string `json:"doc_form"` 91 | } 92 | 93 | func (dc *DifyClient) InitDatasetsByUploadFile(datasets_ids []string) (result InitDatasetsResponse, err error) { 94 | payload := &InitDatasetsPayload{ 95 | DocForm: "text_model", 96 | DocLanguage: "Chinese", 97 | IndexingTechnique: "high_quality", 98 | ProcessRule: InitDatasetsPayloadProcessRule{ 99 | Mode: "automatic", 100 | }, 101 | RetrievalModel: InitDatasetsPayloadRetrievalModel{ 102 | RerankingEnable: false, 103 | RerankingModel: InitDatasetsPayloadRerankingModel{ 104 | RerankingProviderName: "", 105 | RerankingModelName: "", 106 | }, 107 | ScoreThresholdEnabled: false, 108 | ScoreThreshold: 0.5, 109 | SearchMethod: "semantic_search", 110 | TopK: 3, 111 | }, 112 | DataSource: InitDatasetsPayloadDataSource{ 113 | Type: "upload_file", 114 | InfoList: InitDatasetsPayloadDataSourceInfoList{ 115 | DataSourceType: "upload_file", 116 | FileInfoList: InitDatasetsPayloadDataSourceFileInfoList{ 117 | FileIds: datasets_ids, 118 | }, 119 | }, 120 | }, 121 | } 122 | 123 | api := dc.GetConsoleAPI(CONSOLE_API_DATASETS_INIT) 124 | 125 | code, body, err := SendPostRequestToConsole(dc, api, payload) 126 | 127 | err = CommonRiskForSendRequest(code, err) 128 | if err != nil { 129 | fmt.Println("error: ", string(body)) 130 | return result, err 131 | } 132 | 133 | err = json.Unmarshal(body, &result) 134 | if err != nil { 135 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 136 | } 137 | return result, nil 138 | } 139 | 140 | type InitDatasetsIndexingStatusResponse struct { 141 | Data []InitDatasetsIndexingStatusData `json:"data"` 142 | } 143 | 144 | type InitDatasetsIndexingStatusData struct { 145 | ID string `json:"id"` 146 | IndexingStatus string `json:"indexing_status"` 147 | ProcessingStartedAt int `json:"processing_started_at"` 148 | ParsingCompletedAt any `json:"parsing_completed_at"` 149 | CleaningCompletedAt any `json:"cleaning_completed_at"` 150 | SplittingCompletedAt any `json:"splitting_completed_at"` 151 | CompletedAt any `json:"completed_at"` 152 | PausedAt any `json:"paused_at"` 153 | Error any `json:"error"` 154 | StoppedAt any `json:"stopped_at"` 155 | CompletedSegments int `json:"completed_segments"` 156 | TotalSegments int `json:"total_segments"` 157 | } 158 | 159 | func (dc *DifyClient) InitDatasetsIndexingStatus(datasets_id string) (result InitDatasetsIndexingStatusResponse, err error) { 160 | api := dc.GetConsoleAPI(CONSOLE_API_DATASETS_INIT_STATUS) 161 | api = UpdateAPIParam(api, CONSOLE_API_PARAM_DATASETS_ID, datasets_id) 162 | 163 | code, body, err := SendGetRequestToConsole(dc, api) 164 | 165 | err = CommonRiskForSendRequest(code, err) 166 | if err != nil { 167 | return result, err 168 | } 169 | 170 | err = json.Unmarshal(body, &result) 171 | if err != nil { 172 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 173 | } 174 | return result, nil 175 | } 176 | -------------------------------------------------------------------------------- /console-datasets.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | ) 9 | 10 | func (dc *DifyClient) DeleteDatasets(datasets_id string) (ok bool, err error) { 11 | if datasets_id == "" { 12 | return false, fmt.Errorf("datasets_id is required") 13 | } 14 | 15 | api := dc.GetConsoleAPI(CONSOLE_API_DATASETS_DELETE) 16 | api = UpdateAPIParam(api, CONSOLE_API_PARAM_DATASETS_ID, datasets_id) 17 | 18 | req, err := http.NewRequest("DELETE", api, nil) 19 | if err != nil { 20 | return false, fmt.Errorf("could not create a new request: %v", err) 21 | } 22 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.ConsoleToken)) 23 | req.Header.Set("Content-Type", "application/json") 24 | 25 | resp, err := dc.Client.Do(req) 26 | if err != nil { 27 | return false, err 28 | } 29 | defer resp.Body.Close() 30 | 31 | if resp.StatusCode != 204 { 32 | bodyText, err := io.ReadAll(resp.Body) 33 | if err != nil { 34 | return false, fmt.Errorf("status code: %d, could not read the body", resp.StatusCode) 35 | } 36 | return false, fmt.Errorf("status code: %d, %s", resp.StatusCode, bodyText) 37 | } 38 | 39 | return true, nil 40 | } 41 | 42 | type CreateDatasetsPayload struct { 43 | Name string `json:"name"` 44 | } 45 | 46 | type CreateDatasetsResponse struct { 47 | ID string `json:"id"` 48 | Name string `json:"name"` 49 | Description any `json:"description"` 50 | Provider string `json:"provider"` 51 | Permission string `json:"permission"` 52 | DataSourceType any `json:"data_source_type"` 53 | IndexingTechnique any `json:"indexing_technique"` 54 | AppCount int `json:"app_count"` 55 | DocumentCount int `json:"document_count"` 56 | WordCount int `json:"word_count"` 57 | CreatedBy string `json:"created_by"` 58 | CreatedAt int `json:"created_at"` 59 | UpdatedBy string `json:"updated_by"` 60 | UpdatedAt int `json:"updated_at"` 61 | EmbeddingModel any `json:"embedding_model"` 62 | EmbeddingModelProvider any `json:"embedding_model_provider"` 63 | EmbeddingAvailable any `json:"embedding_available"` 64 | RetrievalModelDict struct { 65 | SearchMethod string `json:"search_method"` 66 | RerankingEnable bool `json:"reranking_enable"` 67 | RerankingModel struct { 68 | RerankingProviderName string `json:"reranking_provider_name"` 69 | RerankingModelName string `json:"reranking_model_name"` 70 | } `json:"reranking_model"` 71 | TopK int `json:"top_k"` 72 | ScoreThresholdEnabled bool `json:"score_threshold_enabled"` 73 | ScoreThreshold any `json:"score_threshold"` 74 | } `json:"retrieval_model_dict"` 75 | Tags []any `json:"tags"` 76 | } 77 | 78 | func (dc *DifyClient) CreateDatasets(datasets_name string) (result CreateDatasetsResponse, err error) { 79 | payload := &CreateDatasetsPayload{ 80 | Name: datasets_name, 81 | } 82 | 83 | api := dc.GetConsoleAPI(CONSOLE_API_DATASETS_CREATE) 84 | 85 | code, body, err := SendPostRequestToConsole(dc, api, payload) 86 | 87 | err = CommonRiskForSendRequestWithCode(code, err, http.StatusCreated) 88 | if err != nil { 89 | return result, err 90 | } 91 | 92 | err = json.Unmarshal(body, &result) 93 | if err != nil { 94 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 95 | } 96 | return result, nil 97 | } 98 | 99 | type ListDatasetsResponse struct { 100 | Page int `json:"page"` 101 | Limit int `json:"limit"` 102 | Total int `json:"total"` 103 | HasMore bool `json:"has_more"` 104 | Data []ListDatasetsItem `json:"data"` 105 | } 106 | 107 | type ListDatasetsItem struct { 108 | ID string `json:"id"` 109 | Name string `json:"name"` 110 | Description string `json:"description"` 111 | Mode string `json:"mode"` 112 | Icon string `json:"icon"` 113 | IconBackground string `json:"icon_background"` 114 | ModelConfig ListDatasetsModelConfig `json:"model_config"` 115 | CreatedAt int `json:"created_at"` 116 | Tags []any `json:"tags"` 117 | } 118 | 119 | type ListDatasetsModelConfig struct { 120 | Model ListDatasetsModelConfigDetail `json:"model"` 121 | PrePrompt string `json:"pre_prompt"` 122 | } 123 | 124 | type ListDatasetsModelConfigDetail struct { 125 | Provider string `json:"provider"` 126 | Name string `json:"name"` 127 | Mode string `json:"mode"` 128 | CompletionParams struct { 129 | } `json:"completion_params"` 130 | } 131 | 132 | func (dc *DifyClient) ListDatasets(page int, limit int) (result ListDatasetsResponse, err error) { 133 | if page < 1 { 134 | return result, fmt.Errorf("page should be greater than 0") 135 | } 136 | if limit < 1 { 137 | return result, fmt.Errorf("limit should be greater than 0") 138 | } 139 | 140 | api := dc.GetConsoleAPI(CONSOLE_API_DATASETS_LIST) 141 | api = fmt.Sprintf("%s?page=%d&limit=%d", api, page, limit) 142 | 143 | code, body, err := SendGetRequestToConsole(dc, api) 144 | 145 | err = CommonRiskForSendRequest(code, err) 146 | if err != nil { 147 | return result, err 148 | } 149 | 150 | err = json.Unmarshal(body, &result) 151 | if err != nil { 152 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 153 | } 154 | return result, nil 155 | } 156 | -------------------------------------------------------------------------------- /console-user-login.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type UserLoginParams struct { 9 | Email string `json:"email"` 10 | Password string `json:"password"` 11 | RememberMe bool `json:"remember_me"` 12 | } 13 | 14 | type UserLoginResponse struct { 15 | Result string `json:"result"` 16 | Data string `json:"data"` 17 | } 18 | 19 | func (dc *DifyClient) UserLogin(email string, password string) (result UserLoginResponse, err error) { 20 | var payload = UserLoginParams{ 21 | Email: email, 22 | Password: password, 23 | RememberMe: true, 24 | } 25 | 26 | api := dc.GetConsoleAPI(CONSOLE_API_LOGIN) 27 | 28 | code, body, err := SendPostRequestToConsole(dc, api, payload) 29 | 30 | err = CommonRiskForSendRequest(code, err) 31 | if err != nil { 32 | return result, err 33 | } 34 | 35 | err = json.Unmarshal(body, &result) 36 | if err != nil { 37 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 38 | } 39 | 40 | return result, nil 41 | } 42 | -------------------------------------------------------------------------------- /console-workspaces-models.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | // https://dify.lab.io/console/api/workspaces/current/models/model-types/rerank 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | ) 9 | 10 | type ListWorkspacesRerankModelsResponse struct { 11 | Data []ListWorkspacesRerankItem `json:"data"` 12 | } 13 | 14 | type ListWorkspacesRerankItem struct { 15 | Provider string `json:"provider"` 16 | Label struct { 17 | ZhHans string `json:"zh_Hans"` 18 | EnUS string `json:"en_US"` 19 | } `json:"label"` 20 | IconSmall struct { 21 | ZhHans string `json:"zh_Hans"` 22 | EnUS string `json:"en_US"` 23 | } `json:"icon_small"` 24 | IconLarge struct { 25 | ZhHans string `json:"zh_Hans"` 26 | EnUS string `json:"en_US"` 27 | } `json:"icon_large"` 28 | Status string `json:"status"` 29 | Models []ListWorkspacesRerankModel `json:"models"` 30 | } 31 | 32 | type ListWorkspacesRerankModel struct { 33 | Model string `json:"model"` 34 | Label struct { 35 | ZhHans string `json:"zh_Hans"` 36 | EnUS string `json:"en_US"` 37 | } `json:"label"` 38 | ModelType string `json:"model_type"` 39 | Features any `json:"features"` 40 | FetchFrom string `json:"fetch_from"` 41 | ModelProperties struct { 42 | ContextSize int `json:"context_size"` 43 | } `json:"model_properties"` 44 | Deprecated bool `json:"deprecated"` 45 | Status string `json:"status"` 46 | } 47 | 48 | func (dc *DifyClient) ListWorkspacesRerankModels() (result ListWorkspacesRerankModelsResponse, err error) { 49 | api := dc.GetConsoleAPI(CONSOLE_API_WORKSPACES_RERANK_MODEL) 50 | 51 | code, body, err := SendGetRequestToConsole(dc, api) 52 | 53 | err = CommonRiskForSendRequest(code, err) 54 | if err != nil { 55 | return result, err 56 | } 57 | 58 | err = json.Unmarshal(body, &result) 59 | if err != nil { 60 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 61 | } 62 | return result, nil 63 | } 64 | 65 | type GetCurrentWorkspaceRerankDefaultModelResponse struct { 66 | Data any `json:"data"` 67 | } 68 | 69 | func (dc *DifyClient) GetCurrentWorkspaceRerankDefaultModel() (result GetCurrentWorkspaceRerankDefaultModelResponse, err error) { 70 | api := dc.GetConsoleAPI(CONSOLE_API_CURRENT_WORKSPACE_RERANK_MODEL) 71 | 72 | code, body, err := SendGetRequestToConsole(dc, api) 73 | 74 | err = CommonRiskForSendRequest(code, err) 75 | if err != nil { 76 | return result, err 77 | } 78 | 79 | err = json.Unmarshal(body, &result) 80 | if err != nil { 81 | return result, fmt.Errorf("failed to unmarshal the response: %v", err) 82 | } 83 | return result, nil 84 | } 85 | -------------------------------------------------------------------------------- /const.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | const ( 4 | DEFAULT_TIMEOUT = 10 5 | DEFAULT_USER = "dify-go-sdk" 6 | 7 | RESPONSE_MODE_STREAMING = "streaming" 8 | RESPONSE_MODE_BLOCKING = "blocking" 9 | ) 10 | -------------------------------------------------------------------------------- /fn-api.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | func setAPIAuthorization(dc *DifyClient, req *http.Request) { 9 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.Key)) 10 | req.Header.Set("Content-Type", "application/json") 11 | } 12 | 13 | func SendGetRequestToAPI(dc *DifyClient, api string) (httpCode int, bodyText []byte, err error) { 14 | return SendGetRequest(false, dc, api) 15 | } 16 | 17 | func SendPostRequestToAPI(dc *DifyClient, api string, postBody interface{}) (httpCode int, bodyText []byte, err error) { 18 | return SendPostRequest(false, dc, api, postBody) 19 | } 20 | -------------------------------------------------------------------------------- /fn-console.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | func setConsoleAuthorization(dc *DifyClient, req *http.Request) { 9 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dc.ConsoleToken)) 10 | req.Header.Set("Content-Type", "application/json") 11 | } 12 | 13 | func SendGetRequestToConsole(dc *DifyClient, api string) (httpCode int, bodyText []byte, err error) { 14 | return SendGetRequest(true, dc, api) 15 | } 16 | 17 | func SendPostRequestToConsole(dc *DifyClient, api string, postBody interface{}) (httpCode int, bodyText []byte, err error) { 18 | return SendPostRequest(true, dc, api, postBody) 19 | } 20 | -------------------------------------------------------------------------------- /fn.go: -------------------------------------------------------------------------------- 1 | package dify 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "strings" 9 | ) 10 | 11 | func SendGetRequest(forConsole bool, dc *DifyClient, api string) (httpCode int, bodyText []byte, err error) { 12 | req, err := http.NewRequest("GET", api, nil) 13 | if err != nil { 14 | return -1, nil, err 15 | } 16 | 17 | if forConsole { 18 | setConsoleAuthorization(dc, req) 19 | } else { 20 | setAPIAuthorization(dc, req) 21 | } 22 | 23 | resp, err := dc.Client.Do(req) 24 | if err != nil { 25 | return -1, nil, err 26 | } 27 | defer resp.Body.Close() 28 | 29 | bodyText, err = io.ReadAll(resp.Body) 30 | return resp.StatusCode, bodyText, err 31 | } 32 | 33 | func SendPostRequest(forConsole bool, dc *DifyClient, api string, postBody interface{}) (httpCode int, bodyText []byte, err error) { 34 | var payload *strings.Reader 35 | if postBody != nil { 36 | buf, err := json.Marshal(postBody) 37 | if err != nil { 38 | return -1, nil, err 39 | } 40 | payload = strings.NewReader(string(buf)) 41 | } else { 42 | payload = nil 43 | } 44 | 45 | req, err := http.NewRequest("POST", api, payload) 46 | if err != nil { 47 | return -1, nil, err 48 | } 49 | 50 | if forConsole { 51 | setConsoleAuthorization(dc, req) 52 | } else { 53 | setAPIAuthorization(dc, req) 54 | } 55 | 56 | resp, err := dc.Client.Do(req) 57 | if err != nil { 58 | return -1, nil, err 59 | } 60 | defer resp.Body.Close() 61 | 62 | bodyText, err = io.ReadAll(resp.Body) 63 | return resp.StatusCode, bodyText, err 64 | } 65 | 66 | func CommonRiskForSendRequest(code int, err error) error { 67 | if err != nil { 68 | return err 69 | } 70 | 71 | if code != http.StatusOK { 72 | return fmt.Errorf("status code: %d", code) 73 | } 74 | 75 | return nil 76 | } 77 | 78 | func CommonRiskForSendRequestWithCode(code int, err error, targetCode int) error { 79 | if err != nil { 80 | return err 81 | } 82 | 83 | if code != targetCode { 84 | return fmt.Errorf("status code: %d", code) 85 | } 86 | 87 | return nil 88 | } 89 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/soulteary/dify-go-sdk 2 | 3 | go 1.18.0 4 | --------------------------------------------------------------------------------