-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclient.go
133 lines (119 loc) · 3.55 KB
/
client.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
package anthropic
import (
"bufio"
"bytes"
"encoding/json"
"errors"
"io"
"net/http"
"os"
)
type ClientOptions struct {
ApiKey string
BaseUrl string
}
type Client struct {
apiKey string
baseUrl string
cli *http.Client
}
const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com/v1"
var (
ANTHROPIC_BASE_URL = getEnv("ANTHROPIC_BASE_URL", DEFAULT_ANTHROPIC_BASE_URL)
ANTHROPIC_API_KEY = getEnv("ANTHROPIC_API_KEY", "")
)
func getEnv(key, defaultValue string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return defaultValue
}
func NewClient(opts ...ClientOptions) *Client {
for _, opt := range opts {
if opt.ApiKey != "" {
ANTHROPIC_API_KEY = opt.ApiKey
}
if opt.BaseUrl != "" {
ANTHROPIC_BASE_URL = opt.BaseUrl
}
}
if ANTHROPIC_API_KEY == "" {
panic("`ANTHROPIC_API_KEY` is required")
}
return &Client{
apiKey: ANTHROPIC_API_KEY,
baseUrl: ANTHROPIC_BASE_URL,
cli: &http.Client{},
}
}
func (c *Client) CreateMessages(mr MessagesRequest) (*MessagesResponse, error) {
reqData, err := json.Marshal(&mr)
if err != nil {
return &MessagesResponse{}, errors.New("[Marshal MessagesRequest] " + err.Error())
}
req, err := http.NewRequest("POST", c.baseUrl+"/messages", bytes.NewBuffer(reqData))
if err != nil {
return &MessagesResponse{}, errors.New("[HTTP New Request] " + err.Error())
}
req.Header.Set("X-API-KEY", c.apiKey)
req.Header.Set("Anthropic-Version", "2023-06-01")
req.Header.Set("Content-Type", "application/json")
resp, err := c.cli.Do(req)
if err != nil {
return &MessagesResponse{}, errors.New("[HTTP Do Request] " + err.Error())
}
defer resp.Body.Close()
respData, _ := io.ReadAll(resp.Body)
// handle error
if resp.StatusCode != http.StatusOK {
var errMessages MessagesResponseError
err = json.Unmarshal(respData, &errMessages)
if err != nil {
return &MessagesResponse{}, errors.New("[Unmarshal MessagesResponseError] " + err.Error())
}
return &MessagesResponse{}, errors.New("[Anthropic Error] " + errMessages.Error.Message)
}
var messages MessagesResponse
err = json.Unmarshal(respData, &messages)
if err != nil {
return &MessagesResponse{}, errors.New("[Unmarshal MessagesResponse] " + err.Error())
}
return &messages, nil
}
func (c *Client) CreateMessagesStream(mr MessagesRequest) (*MessagesStream, error) {
mr.Stream = true
reqData, err := json.Marshal(&mr)
if err != nil {
return &MessagesStream{}, errors.New("[Marshal MessagesRequest] " + err.Error())
}
req, err := http.NewRequest("POST", c.baseUrl+"/messages", bytes.NewBuffer(reqData))
if err != nil {
return &MessagesStream{}, errors.New("[HTTP New Request] " + err.Error())
}
req.Header.Set("X-API-KEY", c.apiKey)
req.Header.Set("Anthropic-Version", "2023-06-01")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "text/event-stream")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cache-Control", "no-cache")
resp, err := c.cli.Do(req)
if err != nil {
return &MessagesStream{}, errors.New("[HTTP Do Request] " + err.Error())
}
// handle error
if resp.StatusCode != http.StatusOK {
respData, _ := io.ReadAll(resp.Body)
var errMessages MessagesResponseError
err = json.Unmarshal(respData, &errMessages)
if err != nil {
return &MessagesStream{}, errors.New("[Unmarshal MessagesResponseError] " + err.Error())
}
return &MessagesStream{}, errors.New("[Anthropic Error] " + errMessages.Error.Message)
}
return &MessagesStream{
MessagesStreamReader: &MessagesStreamReader{
reader: bufio.NewReader(resp.Body),
response: resp,
},
}, nil
}