-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathclient.go
138 lines (115 loc) · 3.25 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
134
135
136
137
138
package openairt
import (
"context"
"net/http"
"net/url"
)
const (
GPT4oRealtimePreview = "gpt-4o-realtime-preview"
GPT4oRealtimePreview20241001 = "gpt-4o-realtime-preview-2024-10-01"
GPT4oRealtimePreview20241217 = "gpt-4o-realtime-preview-2024-12-17"
GPT4oMiniRealtimePreview = "gpt-4o-mini-realtime-preview"
GPT4oMiniRealtimePreview20241217 = "gpt-4o-mini-realtime-preview-2024-12-17"
)
// Client is OpenAI Realtime API client.
type Client struct {
config ClientConfig
}
// NewClient creates new OpenAI Realtime API client.
func NewClient(authToken string) *Client {
config := DefaultConfig(authToken)
return NewClientWithConfig(config)
}
// NewClientWithConfig creates new OpenAI Realtime API client for specified config.
func NewClientWithConfig(config ClientConfig) *Client {
return &Client{
config: config,
}
}
func (c *Client) getURL(model string) string {
query := url.Values{}
if c.config.APIType == APITypeAzure {
query.Set("api-version", c.config.APIVersion)
query.Set("deployment", model)
} else {
query.Set("model", model)
}
return c.config.BaseURL + "?" + query.Encode()
}
func (c *Client) getHeaders() http.Header {
headers := http.Header{}
if c.config.APIType == APITypeAzure {
headers.Set("api-key", c.config.authToken)
} else {
headers.Set("Authorization", "Bearer "+c.config.authToken)
headers.Set("OpenAI-Beta", "realtime=v1")
}
return headers
}
type connectOption struct {
model string
dialer WebSocketDialer
logger Logger
}
type ConnectOption func(*connectOption)
// WithModel sets the model to use for the connection.
func WithModel(model string) ConnectOption {
return func(opts *connectOption) {
opts.model = model
}
}
// WithDialer sets the dialer for the connection.
func WithDialer(dialer WebSocketDialer) ConnectOption {
return func(opts *connectOption) {
opts.dialer = dialer
}
}
// WithLogger sets the logger for the connection.
func WithLogger(logger Logger) ConnectOption {
return func(opts *connectOption) {
opts.logger = logger
}
}
// Connect connects to the OpenAI Realtime API.
func (c *Client) Connect(ctx context.Context, opts ...ConnectOption) (*Conn, error) {
connectOpts := connectOption{
model: GPT4oRealtimePreview,
logger: NopLogger{},
}
for _, opt := range opts {
opt(&connectOpts)
}
if connectOpts.dialer == nil {
connectOpts.dialer = DefaultDialer()
}
// default headers
headers := c.getHeaders()
// get url by model
url := c.getURL(connectOpts.model)
// dial
conn, err := connectOpts.dialer.Dial(ctx, url, headers)
if err != nil {
return nil, err
}
return &Conn{conn: conn, logger: connectOpts.logger}, nil
}
func (c *Client) getAPIHeaders() http.Header {
headers := http.Header{}
if c.config.APIType == APITypeAzure {
headers.Set("api-key", c.config.authToken)
} else {
headers.Set("Authorization", "Bearer "+c.config.authToken)
}
headers.Set("Content-Type", "application/json")
return headers
}
func (c *Client) CreateSession(ctx context.Context, req *CreateSessionRequest) (*CreateSessionResponse, error) {
return HTTPDo[CreateSessionRequest, CreateSessionResponse](
ctx,
c.config.APIBaseURL+"/realtime/sessions",
req,
WithClient(c.config.HTTPClient),
WithMethod(http.MethodPost),
WithHeaders(c.getAPIHeaders()),
)
}