forked from sashabaranov/go-openai
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfiles.go
144 lines (119 loc) · 3.04 KB
/
files.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package gogpt
import (
"bytes"
"context"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"os"
"strings"
)
type FileRequest struct {
FileName string `json:"file"`
FilePath string `json:"-"`
Purpose string `json:"purpose"`
}
// File struct represents an OpenAPI file
type File struct {
Bytes int `json:"bytes"`
CreatedAt int `json:"created_at"`
ID string `json:"id"`
FileName string `json:"filename"`
Object string `json:"object"`
Owner string `json:"owner"`
Purpose string `json:"purpose"`
}
// FilesList is a list of files that belong to the user or organization
type FilesList struct {
Files []File `json:"data"`
}
// isUrl is a helper function that determines whether the given FilePath
// is a remote URL or a local file path
func isURL(path string) bool {
_, err := url.ParseRequestURI(path)
if err != nil {
return false
}
u, err := url.Parse(path)
if err != nil || u.Scheme == "" || u.Host == "" {
return false
}
return true
}
// CreateFile uploads a jsonl file to GPT3
// FilePath can be either a local file path or a URL
func (c *Client) CreateFile(ctx context.Context, request FileRequest) (file File, err error) {
var b bytes.Buffer
w := multipart.NewWriter(&b)
var fw, pw io.Writer
pw, err = w.CreateFormField("purpose")
if err != nil {
return
}
_, err = io.Copy(pw, strings.NewReader(request.Purpose))
if err != nil {
return
}
fw, err = w.CreateFormFile("file", request.FileName)
if err != nil {
return
}
var fileData io.ReadCloser
if isURL(request.FilePath) {
var remoteFile *http.Response
remoteFile, err = http.Get(request.FilePath)
if err != nil {
return
}
defer remoteFile.Body.Close()
// Check server response
if remoteFile.StatusCode != http.StatusOK {
err = fmt.Errorf("error, status code: %d, message: failed to fetch file", remoteFile.StatusCode)
return
}
fileData = remoteFile.Body
} else {
fileData, err = os.Open(request.FilePath)
if err != nil {
return
}
}
_, err = io.Copy(fw, fileData)
if err != nil {
return
}
w.Close()
req, err := http.NewRequest("POST", c.fullURL("/files"), &b)
if err != nil {
return
}
req = req.WithContext(ctx)
req.Header.Set("Content-Type", w.FormDataContentType())
err = c.sendRequest(req, &file)
return
}
// ListFiles Lists the currently available files,
// and provides basic information about each file such as the file name and purpose.
func (c *Client) ListFiles(ctx context.Context) (files FilesList, err error) {
req, err := http.NewRequest("GET", c.fullURL("/files"), nil)
if err != nil {
return
}
req = req.WithContext(ctx)
err = c.sendRequest(req, &files)
return
}
// GetFile Retrieves a file instance, providing basic information about the file
// such as the file name and purpose.
func (c *Client) GetFile(ctx context.Context, fileID string) (file File, err error) {
urlSuffix := fmt.Sprintf("/files/%s", fileID)
req, err := http.NewRequest("GET", c.fullURL(urlSuffix), nil)
if err != nil {
return
}
req = req.WithContext(ctx)
err = c.sendRequest(req, &file)
return
}