Skip to content

Commit 61ba5f3

Browse files
authored
move request_builder into internal pkg (#304) (#329)
* move request_builder into internal pkg (#304) * add some test for internal.RequestBuilder * add a test for openai.GetEngine
1 parent 62eb4be commit 61ba5f3

16 files changed

+273
-208
lines changed

chat.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (c *Client) CreateChatCompletion(
7777
return
7878
}
7979

80-
req, err := c.requestBuilder.build(ctx, http.MethodPost, c.fullURL(urlSuffix, request.Model), request)
80+
req, err := c.requestBuilder.Build(ctx, http.MethodPost, c.fullURL(urlSuffix, request.Model), request)
8181
if err != nil {
8282
return
8383
}

client.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
type Client struct {
1616
config ClientConfig
1717

18-
requestBuilder requestBuilder
18+
requestBuilder utils.RequestBuilder
1919
createFormBuilder func(io.Writer) utils.FormBuilder
2020
}
2121

@@ -29,7 +29,7 @@ func NewClient(authToken string) *Client {
2929
func NewClientWithConfig(config ClientConfig) *Client {
3030
return &Client{
3131
config: config,
32-
requestBuilder: newRequestBuilder(),
32+
requestBuilder: utils.NewRequestBuilder(),
3333
createFormBuilder: func(body io.Writer) utils.FormBuilder {
3434
return utils.NewFormBuilder(body)
3535
},
@@ -135,7 +135,7 @@ func (c *Client) newStreamRequest(
135135
urlSuffix string,
136136
body any,
137137
model string) (*http.Request, error) {
138-
req, err := c.requestBuilder.build(ctx, method, c.fullURL(urlSuffix, model), body)
138+
req, err := c.requestBuilder.Build(ctx, method, c.fullURL(urlSuffix, model), body)
139139
if err != nil {
140140
return nil, err
141141
}

client_test.go

+149
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,24 @@ package openai //nolint:testpackage // testing private field
22

33
import (
44
"bytes"
5+
"context"
56
"errors"
67
"fmt"
78
"io"
89
"net/http"
910
"testing"
11+
12+
"github.com/sashabaranov/go-openai/internal/test"
1013
)
1114

15+
var errTestRequestBuilderFailed = errors.New("test request builder failed")
16+
17+
type failingRequestBuilder struct{}
18+
19+
func (*failingRequestBuilder) Build(_ context.Context, _, _ string, _ any) (*http.Request, error) {
20+
return nil, errTestRequestBuilderFailed
21+
}
22+
1223
func TestClient(t *testing.T) {
1324
const mockToken = "mock token"
1425
client := NewClient(mockToken)
@@ -145,3 +156,141 @@ func TestHandleErrorResp(t *testing.T) {
145156
})
146157
}
147158
}
159+
160+
func TestClientReturnsRequestBuilderErrors(t *testing.T) {
161+
var err error
162+
ts := test.NewTestServer().OpenAITestServer()
163+
ts.Start()
164+
defer ts.Close()
165+
166+
config := DefaultConfig(test.GetTestToken())
167+
config.BaseURL = ts.URL + "/v1"
168+
client := NewClientWithConfig(config)
169+
client.requestBuilder = &failingRequestBuilder{}
170+
171+
ctx := context.Background()
172+
173+
_, err = client.CreateCompletion(ctx, CompletionRequest{Prompt: "testing"})
174+
if !errors.Is(err, errTestRequestBuilderFailed) {
175+
t.Fatalf("Did not return error when request builder failed: %v", err)
176+
}
177+
178+
_, err = client.CreateChatCompletion(ctx, ChatCompletionRequest{Model: GPT3Dot5Turbo})
179+
if !errors.Is(err, errTestRequestBuilderFailed) {
180+
t.Fatalf("Did not return error when request builder failed: %v", err)
181+
}
182+
183+
_, err = client.CreateChatCompletionStream(ctx, ChatCompletionRequest{Model: GPT3Dot5Turbo})
184+
if !errors.Is(err, errTestRequestBuilderFailed) {
185+
t.Fatalf("Did not return error when request builder failed: %v", err)
186+
}
187+
188+
_, err = client.CreateFineTune(ctx, FineTuneRequest{})
189+
if !errors.Is(err, errTestRequestBuilderFailed) {
190+
t.Fatalf("Did not return error when request builder failed: %v", err)
191+
}
192+
193+
_, err = client.ListFineTunes(ctx)
194+
if !errors.Is(err, errTestRequestBuilderFailed) {
195+
t.Fatalf("Did not return error when request builder failed: %v", err)
196+
}
197+
198+
_, err = client.CancelFineTune(ctx, "")
199+
if !errors.Is(err, errTestRequestBuilderFailed) {
200+
t.Fatalf("Did not return error when request builder failed: %v", err)
201+
}
202+
203+
_, err = client.GetFineTune(ctx, "")
204+
if !errors.Is(err, errTestRequestBuilderFailed) {
205+
t.Fatalf("Did not return error when request builder failed: %v", err)
206+
}
207+
208+
_, err = client.DeleteFineTune(ctx, "")
209+
if !errors.Is(err, errTestRequestBuilderFailed) {
210+
t.Fatalf("Did not return error when request builder failed: %v", err)
211+
}
212+
213+
_, err = client.ListFineTuneEvents(ctx, "")
214+
if !errors.Is(err, errTestRequestBuilderFailed) {
215+
t.Fatalf("Did not return error when request builder failed: %v", err)
216+
}
217+
218+
_, err = client.Moderations(ctx, ModerationRequest{})
219+
if !errors.Is(err, errTestRequestBuilderFailed) {
220+
t.Fatalf("Did not return error when request builder failed: %v", err)
221+
}
222+
223+
_, err = client.Edits(ctx, EditsRequest{})
224+
if !errors.Is(err, errTestRequestBuilderFailed) {
225+
t.Fatalf("Did not return error when request builder failed: %v", err)
226+
}
227+
228+
_, err = client.CreateEmbeddings(ctx, EmbeddingRequest{})
229+
if !errors.Is(err, errTestRequestBuilderFailed) {
230+
t.Fatalf("Did not return error when request builder failed: %v", err)
231+
}
232+
233+
_, err = client.CreateImage(ctx, ImageRequest{})
234+
if !errors.Is(err, errTestRequestBuilderFailed) {
235+
t.Fatalf("Did not return error when request builder failed: %v", err)
236+
}
237+
238+
err = client.DeleteFile(ctx, "")
239+
if !errors.Is(err, errTestRequestBuilderFailed) {
240+
t.Fatalf("Did not return error when request builder failed: %v", err)
241+
}
242+
243+
_, err = client.GetFile(ctx, "")
244+
if !errors.Is(err, errTestRequestBuilderFailed) {
245+
t.Fatalf("Did not return error when request builder failed: %v", err)
246+
}
247+
248+
_, err = client.ListFiles(ctx)
249+
if !errors.Is(err, errTestRequestBuilderFailed) {
250+
t.Fatalf("Did not return error when request builder failed: %v", err)
251+
}
252+
253+
_, err = client.ListEngines(ctx)
254+
if !errors.Is(err, errTestRequestBuilderFailed) {
255+
t.Fatalf("Did not return error when request builder failed: %v", err)
256+
}
257+
258+
_, err = client.GetEngine(ctx, "")
259+
if !errors.Is(err, errTestRequestBuilderFailed) {
260+
t.Fatalf("Did not return error when request builder failed: %v", err)
261+
}
262+
263+
_, err = client.ListModels(ctx)
264+
if !errors.Is(err, errTestRequestBuilderFailed) {
265+
t.Fatalf("Did not return error when request builder failed: %v", err)
266+
}
267+
268+
_, err = client.CreateCompletionStream(ctx, CompletionRequest{Prompt: ""})
269+
if !errors.Is(err, errTestRequestBuilderFailed) {
270+
t.Fatalf("Did not return error when request builder failed: %v", err)
271+
}
272+
}
273+
274+
func TestClientReturnsRequestBuilderErrorsAddtion(t *testing.T) {
275+
var err error
276+
ts := test.NewTestServer().OpenAITestServer()
277+
ts.Start()
278+
defer ts.Close()
279+
280+
config := DefaultConfig(test.GetTestToken())
281+
config.BaseURL = ts.URL + "/v1"
282+
client := NewClientWithConfig(config)
283+
client.requestBuilder = &failingRequestBuilder{}
284+
285+
ctx := context.Background()
286+
287+
_, err = client.CreateCompletion(ctx, CompletionRequest{Prompt: 1})
288+
if !errors.Is(err, ErrCompletionRequestPromptTypeNotSupported) {
289+
t.Fatalf("Did not return error when request builder failed: %v", err)
290+
}
291+
292+
_, err = client.CreateCompletionStream(ctx, CompletionRequest{Prompt: 1})
293+
if !errors.Is(err, ErrCompletionRequestPromptTypeNotSupported) {
294+
t.Fatalf("Did not return error when request builder failed: %v", err)
295+
}
296+
}

completion.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ func (c *Client) CreateCompletion(
155155
return
156156
}
157157

158-
req, err := c.requestBuilder.build(ctx, http.MethodPost, c.fullURL(urlSuffix, request.Model), request)
158+
req, err := c.requestBuilder.Build(ctx, http.MethodPost, c.fullURL(urlSuffix, request.Model), request)
159159
if err != nil {
160160
return
161161
}

edits.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ type EditsResponse struct {
3232

3333
// Perform an API call to the Edits endpoint.
3434
func (c *Client) Edits(ctx context.Context, request EditsRequest) (response EditsResponse, err error) {
35-
req, err := c.requestBuilder.build(ctx, http.MethodPost, c.fullURL("/edits", fmt.Sprint(request.Model)), request)
35+
req, err := c.requestBuilder.Build(ctx, http.MethodPost, c.fullURL("/edits", fmt.Sprint(request.Model)), request)
3636
if err != nil {
3737
return
3838
}

embeddings.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ type EmbeddingRequest struct {
132132
// CreateEmbeddings returns an EmbeddingResponse which will contain an Embedding for every item in |request.Input|.
133133
// https://beta.openai.com/docs/api-reference/embeddings/create
134134
func (c *Client) CreateEmbeddings(ctx context.Context, request EmbeddingRequest) (resp EmbeddingResponse, err error) {
135-
req, err := c.requestBuilder.build(ctx, http.MethodPost, c.fullURL("/embeddings", request.Model.String()), request)
135+
req, err := c.requestBuilder.Build(ctx, http.MethodPost, c.fullURL("/embeddings", request.Model.String()), request)
136136
if err != nil {
137137
return
138138
}

engines.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type EnginesList struct {
2222
// ListEngines Lists the currently available engines, and provides basic
2323
// information about each option such as the owner and availability.
2424
func (c *Client) ListEngines(ctx context.Context) (engines EnginesList, err error) {
25-
req, err := c.requestBuilder.build(ctx, http.MethodGet, c.fullURL("/engines"), nil)
25+
req, err := c.requestBuilder.Build(ctx, http.MethodGet, c.fullURL("/engines"), nil)
2626
if err != nil {
2727
return
2828
}
@@ -38,7 +38,7 @@ func (c *Client) GetEngine(
3838
engineID string,
3939
) (engine Engine, err error) {
4040
urlSuffix := fmt.Sprintf("/engines/%s", engineID)
41-
req, err := c.requestBuilder.build(ctx, http.MethodGet, c.fullURL(urlSuffix), nil)
41+
req, err := c.requestBuilder.Build(ctx, http.MethodGet, c.fullURL(urlSuffix), nil)
4242
if err != nil {
4343
return
4444
}

engines_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package openai_test
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"net/http"
8+
"testing"
9+
10+
. "github.com/sashabaranov/go-openai"
11+
"github.com/sashabaranov/go-openai/internal/test"
12+
"github.com/sashabaranov/go-openai/internal/test/checks"
13+
)
14+
15+
// TestGetEngine Tests the retrieve engine endpoint of the API using the mocked server.
16+
func TestGetEngine(t *testing.T) {
17+
server := test.NewTestServer()
18+
server.RegisterHandler("/v1/engines/text-davinci-003", func(w http.ResponseWriter, r *http.Request) {
19+
resBytes, _ := json.Marshal(Engine{})
20+
fmt.Fprintln(w, string(resBytes))
21+
})
22+
// create the test server
23+
ts := server.OpenAITestServer()
24+
ts.Start()
25+
defer ts.Close()
26+
27+
config := DefaultConfig(test.GetTestToken())
28+
config.BaseURL = ts.URL + "/v1"
29+
client := NewClientWithConfig(config)
30+
ctx := context.Background()
31+
32+
_, err := client.GetEngine(ctx, "text-davinci-003")
33+
checks.NoError(t, err, "GetEngine error")
34+
}

files.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (c *Client) CreateFile(ctx context.Context, request FileRequest) (file File
7070

7171
// DeleteFile deletes an existing file.
7272
func (c *Client) DeleteFile(ctx context.Context, fileID string) (err error) {
73-
req, err := c.requestBuilder.build(ctx, http.MethodDelete, c.fullURL("/files/"+fileID), nil)
73+
req, err := c.requestBuilder.Build(ctx, http.MethodDelete, c.fullURL("/files/"+fileID), nil)
7474
if err != nil {
7575
return
7676
}
@@ -82,7 +82,7 @@ func (c *Client) DeleteFile(ctx context.Context, fileID string) (err error) {
8282
// ListFiles Lists the currently available files,
8383
// and provides basic information about each file such as the file name and purpose.
8484
func (c *Client) ListFiles(ctx context.Context) (files FilesList, err error) {
85-
req, err := c.requestBuilder.build(ctx, http.MethodGet, c.fullURL("/files"), nil)
85+
req, err := c.requestBuilder.Build(ctx, http.MethodGet, c.fullURL("/files"), nil)
8686
if err != nil {
8787
return
8888
}
@@ -95,7 +95,7 @@ func (c *Client) ListFiles(ctx context.Context) (files FilesList, err error) {
9595
// such as the file name and purpose.
9696
func (c *Client) GetFile(ctx context.Context, fileID string) (file File, err error) {
9797
urlSuffix := fmt.Sprintf("/files/%s", fileID)
98-
req, err := c.requestBuilder.build(ctx, http.MethodGet, c.fullURL(urlSuffix), nil)
98+
req, err := c.requestBuilder.Build(ctx, http.MethodGet, c.fullURL(urlSuffix), nil)
9999
if err != nil {
100100
return
101101
}

fine_tunes.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ type FineTuneDeleteResponse struct {
6868

6969
func (c *Client) CreateFineTune(ctx context.Context, request FineTuneRequest) (response FineTune, err error) {
7070
urlSuffix := "/fine-tunes"
71-
req, err := c.requestBuilder.build(ctx, http.MethodPost, c.fullURL(urlSuffix), request)
71+
req, err := c.requestBuilder.Build(ctx, http.MethodPost, c.fullURL(urlSuffix), request)
7272
if err != nil {
7373
return
7474
}
@@ -79,7 +79,7 @@ func (c *Client) CreateFineTune(ctx context.Context, request FineTuneRequest) (r
7979

8080
// CancelFineTune cancel a fine-tune job.
8181
func (c *Client) CancelFineTune(ctx context.Context, fineTuneID string) (response FineTune, err error) {
82-
req, err := c.requestBuilder.build(ctx, http.MethodPost, c.fullURL("/fine-tunes/"+fineTuneID+"/cancel"), nil)
82+
req, err := c.requestBuilder.Build(ctx, http.MethodPost, c.fullURL("/fine-tunes/"+fineTuneID+"/cancel"), nil)
8383
if err != nil {
8484
return
8585
}
@@ -89,7 +89,7 @@ func (c *Client) CancelFineTune(ctx context.Context, fineTuneID string) (respons
8989
}
9090

9191
func (c *Client) ListFineTunes(ctx context.Context) (response FineTuneList, err error) {
92-
req, err := c.requestBuilder.build(ctx, http.MethodGet, c.fullURL("/fine-tunes"), nil)
92+
req, err := c.requestBuilder.Build(ctx, http.MethodGet, c.fullURL("/fine-tunes"), nil)
9393
if err != nil {
9494
return
9595
}
@@ -100,7 +100,7 @@ func (c *Client) ListFineTunes(ctx context.Context) (response FineTuneList, err
100100

101101
func (c *Client) GetFineTune(ctx context.Context, fineTuneID string) (response FineTune, err error) {
102102
urlSuffix := fmt.Sprintf("/fine-tunes/%s", fineTuneID)
103-
req, err := c.requestBuilder.build(ctx, http.MethodGet, c.fullURL(urlSuffix), nil)
103+
req, err := c.requestBuilder.Build(ctx, http.MethodGet, c.fullURL(urlSuffix), nil)
104104
if err != nil {
105105
return
106106
}
@@ -110,7 +110,7 @@ func (c *Client) GetFineTune(ctx context.Context, fineTuneID string) (response F
110110
}
111111

112112
func (c *Client) DeleteFineTune(ctx context.Context, fineTuneID string) (response FineTuneDeleteResponse, err error) {
113-
req, err := c.requestBuilder.build(ctx, http.MethodDelete, c.fullURL("/fine-tunes/"+fineTuneID), nil)
113+
req, err := c.requestBuilder.Build(ctx, http.MethodDelete, c.fullURL("/fine-tunes/"+fineTuneID), nil)
114114
if err != nil {
115115
return
116116
}
@@ -120,7 +120,7 @@ func (c *Client) DeleteFineTune(ctx context.Context, fineTuneID string) (respons
120120
}
121121

122122
func (c *Client) ListFineTuneEvents(ctx context.Context, fineTuneID string) (response FineTuneEventList, err error) {
123-
req, err := c.requestBuilder.build(ctx, http.MethodGet, c.fullURL("/fine-tunes/"+fineTuneID+"/events"), nil)
123+
req, err := c.requestBuilder.Build(ctx, http.MethodGet, c.fullURL("/fine-tunes/"+fineTuneID+"/events"), nil)
124124
if err != nil {
125125
return
126126
}

image.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type ImageResponseDataInner struct {
4444
// CreateImage - API call to create an image. This is the main endpoint of the DALL-E API.
4545
func (c *Client) CreateImage(ctx context.Context, request ImageRequest) (response ImageResponse, err error) {
4646
urlSuffix := "/images/generations"
47-
req, err := c.requestBuilder.build(ctx, http.MethodPost, c.fullURL(urlSuffix), request)
47+
req, err := c.requestBuilder.Build(ctx, http.MethodPost, c.fullURL(urlSuffix), request)
4848
if err != nil {
4949
return
5050
}

0 commit comments

Comments
 (0)