mirror of
https://github.com/hanzo-go/openai.git
synced 2026-09-24 00:31:39 +00:00
Go 1.27.1, and the code it can say more simply
Modules declare go 1.27.1 and the build images follow. go fix applied the modernizers, and the stream request helper is now a generic method on Client; omitzero is not applied, since it changes what the JSON says. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
+1
-1
@@ -96,7 +96,7 @@ func (c *Client) CreateChatCompletionStream(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := sendRequestStream[ChatCompletionStreamResponse](c, req)
|
||||
resp, err := c.sendRequestStream[ChatCompletionStreamResponse](req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -157,21 +157,21 @@ func (c *Client) sendRequestRaw(req *http.Request) (response RawResponse, err er
|
||||
return
|
||||
}
|
||||
|
||||
func sendRequestStream[T streamable](client *Client, req *http.Request) (*streamReader[T], error) {
|
||||
func (c *Client) sendRequestStream[T streamable](req *http.Request) (*streamReader[T], error) {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Accept", "text/event-stream")
|
||||
req.Header.Set("Cache-Control", "no-cache")
|
||||
req.Header.Set("Connection", "keep-alive")
|
||||
|
||||
resp, err := client.config.HTTPClient.Do(req) //nolint:bodyclose // body is closed in stream.Close()
|
||||
resp, err := c.config.HTTPClient.Do(req) //nolint:bodyclose // body is closed in stream.Close()
|
||||
if err != nil {
|
||||
return new(streamReader[T]), err
|
||||
}
|
||||
if isFailureStatusCode(resp) {
|
||||
return new(streamReader[T]), client.handleErrorResp(resp)
|
||||
return new(streamReader[T]), c.handleErrorResp(resp)
|
||||
}
|
||||
return &streamReader[T]{
|
||||
emptyMessagesLimit: client.config.EmptyMessagesLimit,
|
||||
emptyMessagesLimit: c.config.EmptyMessagesLimit,
|
||||
reader: bufio.NewReader(resp.Body),
|
||||
response: resp,
|
||||
errAccumulator: utils.NewErrorAccumulator(),
|
||||
|
||||
+5
-5
@@ -59,8 +59,8 @@ func TestDecodeResponse(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
expected interface{}
|
||||
value any
|
||||
expected any
|
||||
body io.Reader
|
||||
hasError bool
|
||||
}{
|
||||
@@ -78,9 +78,9 @@ func TestDecodeResponse(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "map input",
|
||||
value: &map[string]interface{}{},
|
||||
value: &map[string]any{},
|
||||
body: bytes.NewReader([]byte(`{"test": "test"}`)),
|
||||
expected: map[string]interface{}{
|
||||
expected: map[string]any{
|
||||
"test": "test",
|
||||
},
|
||||
},
|
||||
@@ -100,7 +100,7 @@ func TestDecodeResponse(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
assertEqual := func(t *testing.T, expected, actual interface{}) {
|
||||
assertEqual := func(t *testing.T, expected, actual any) {
|
||||
t.Helper()
|
||||
if expected == actual {
|
||||
return
|
||||
|
||||
+3
-3
@@ -68,7 +68,7 @@ func TestMultiplePromptsCompletionsWrong(t *testing.T) {
|
||||
req := openai.CompletionRequest{
|
||||
MaxTokens: 5,
|
||||
Model: "ada",
|
||||
Prompt: []interface{}{"Lorem ipsum", 9},
|
||||
Prompt: []any{"Lorem ipsum", 9},
|
||||
}
|
||||
_, err := client.CreateCompletion(context.Background(), req)
|
||||
if !errors.Is(err, openai.ErrCompletionRequestPromptTypeNotSupported) {
|
||||
@@ -85,7 +85,7 @@ func TestMultiplePromptsCompletions(t *testing.T) {
|
||||
req := openai.CompletionRequest{
|
||||
MaxTokens: 5,
|
||||
Model: "ada",
|
||||
Prompt: []interface{}{"Lorem ipsum", "Lorem ipsum"},
|
||||
Prompt: []any{"Lorem ipsum", "Lorem ipsum"},
|
||||
}
|
||||
_, err := client.CreateCompletion(context.Background(), req)
|
||||
checks.NoError(t, err, "CreateCompletion error")
|
||||
@@ -124,7 +124,7 @@ func handleCompletionEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
switch v := completionReq.Prompt.(type) {
|
||||
case string:
|
||||
prompts = append(prompts, v)
|
||||
case []interface{}:
|
||||
case []any:
|
||||
for _, item := range v {
|
||||
if str, ok := item.(string); ok {
|
||||
prompts = append(prompts, str)
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ func (b base64String) Decode() ([]float32, error) {
|
||||
|
||||
const sizeOfFloat32 = 4
|
||||
floats := make([]float32, len(decodedData)/sizeOfFloat32)
|
||||
for i := 0; i < len(floats); i++ {
|
||||
for i := range floats {
|
||||
floats[i] = math.Float32frombits(binary.LittleEndian.Uint32(decodedData[i*4 : (i+1)*4]))
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -224,13 +224,13 @@ func assertAPIErrorMessage(t *testing.T, apiErr openai.APIError, expected string
|
||||
}
|
||||
}
|
||||
|
||||
func assertAPIErrorInnerError(t *testing.T, apiErr openai.APIError, expected interface{}) {
|
||||
func assertAPIErrorInnerError(t *testing.T, apiErr openai.APIError, expected any) {
|
||||
if !reflect.DeepEqual(apiErr.InnerError, expected) {
|
||||
t.Errorf("Unexpected APIError InnerError: %v; expected: %v; ", apiErr, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func assertAPIErrorCode(t *testing.T, apiErr openai.APIError, expected interface{}) {
|
||||
func assertAPIErrorCode(t *testing.T, apiErr openai.APIError, expected any) {
|
||||
switch v := apiErr.Code.(type) {
|
||||
case int:
|
||||
if v != expected {
|
||||
|
||||
+4
-5
@@ -95,7 +95,7 @@ func reflectSchema(t reflect.Type) (*Definition, error) {
|
||||
return nil, err
|
||||
}
|
||||
d = *object
|
||||
case reflect.Ptr:
|
||||
case reflect.Pointer:
|
||||
definition, err := reflectSchema(t.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -117,8 +117,7 @@ func reflectSchemaObject(t reflect.Type) (*Definition, error) {
|
||||
}
|
||||
properties := make(map[string]Definition)
|
||||
var requiredFields []string
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
for field := range t.Fields() {
|
||||
if !field.IsExported() {
|
||||
continue
|
||||
}
|
||||
@@ -126,8 +125,8 @@ func reflectSchemaObject(t reflect.Type) (*Definition, error) {
|
||||
var required = true
|
||||
if jsonTag == "" {
|
||||
jsonTag = field.Name
|
||||
} else if strings.HasSuffix(jsonTag, ",omitempty") {
|
||||
jsonTag = strings.TrimSuffix(jsonTag, ",omitempty")
|
||||
} else if before, ok := strings.CutSuffix(jsonTag, ",omitempty"); ok {
|
||||
jsonTag = before
|
||||
required = false
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ func TestDefinition_MarshalJSON(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
wantBytes := []byte(tt.want)
|
||||
var want map[string]interface{}
|
||||
var want map[string]any
|
||||
err := json.Unmarshal(wantBytes, &want)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to Unmarshal JSON: error = %v", err)
|
||||
@@ -201,7 +201,7 @@ func structToMap(t *testing.T, v any) map[string]any {
|
||||
return nil
|
||||
}
|
||||
|
||||
var got map[string]interface{}
|
||||
var got map[string]any
|
||||
err = json.Unmarshal(gotBytes, &got)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to Unmarshal JSON: error = %v", err)
|
||||
|
||||
+2
-10
@@ -3,6 +3,7 @@ package jsonschema
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"slices"
|
||||
)
|
||||
|
||||
func VerifySchemaAndUnmarshal(schema Definition, content []byte, v any) error {
|
||||
@@ -63,7 +64,7 @@ func validateObject(schema Definition, data any) bool {
|
||||
value, exists := dataMap[key]
|
||||
if exists && !Validate(valueSchema, value) {
|
||||
return false
|
||||
} else if !exists && contains(schema.Required, key) {
|
||||
} else if !exists && slices.Contains(schema.Required, key) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -82,12 +83,3 @@ func validateArray(schema Definition, data any) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func contains[S ~[]E, E comparable](s S, v E) bool {
|
||||
for i := range s {
|
||||
if v == s[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -21,18 +21,18 @@ type Model struct {
|
||||
|
||||
// Permission struct represents an OpenAPI permission.
|
||||
type Permission struct {
|
||||
CreatedAt int64 `json:"created"`
|
||||
ID string `json:"id"`
|
||||
Object string `json:"object"`
|
||||
AllowCreateEngine bool `json:"allow_create_engine"`
|
||||
AllowSampling bool `json:"allow_sampling"`
|
||||
AllowLogprobs bool `json:"allow_logprobs"`
|
||||
AllowSearchIndices bool `json:"allow_search_indices"`
|
||||
AllowView bool `json:"allow_view"`
|
||||
AllowFineTuning bool `json:"allow_fine_tuning"`
|
||||
Organization string `json:"organization"`
|
||||
Group interface{} `json:"group"`
|
||||
IsBlocking bool `json:"is_blocking"`
|
||||
CreatedAt int64 `json:"created"`
|
||||
ID string `json:"id"`
|
||||
Object string `json:"object"`
|
||||
AllowCreateEngine bool `json:"allow_create_engine"`
|
||||
AllowSampling bool `json:"allow_sampling"`
|
||||
AllowLogprobs bool `json:"allow_logprobs"`
|
||||
AllowSearchIndices bool `json:"allow_search_indices"`
|
||||
AllowView bool `json:"allow_view"`
|
||||
AllowFineTuning bool `json:"allow_fine_tuning"`
|
||||
Organization string `json:"organization"`
|
||||
Group any `json:"group"`
|
||||
IsBlocking bool `json:"is_blocking"`
|
||||
}
|
||||
|
||||
// FineTuneModelDeleteResponse represents the deletion status of a fine-tuned model.
|
||||
|
||||
+1
-3
@@ -205,9 +205,7 @@ func TestRun(t *testing.T) {
|
||||
checks.NoError(t, err, "CancelRun error")
|
||||
|
||||
_, err = client.CreateThreadAndRun(ctx, openai.CreateThreadAndRunRequest{
|
||||
RunRequest: openai.RunRequest{
|
||||
AssistantID: assistantID,
|
||||
},
|
||||
AssistantID: assistantID,
|
||||
Thread: openai.ThreadRequest{
|
||||
Messages: []openai.ThreadMessage{
|
||||
{
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ func TestSpeechIntegration(t *testing.T) {
|
||||
}
|
||||
|
||||
// Parse the JSON body of the request
|
||||
var params map[string]interface{}
|
||||
var params map[string]any
|
||||
err = json.NewDecoder(r.Body).Decode(¶ms)
|
||||
if err != nil {
|
||||
http.Error(w, "failed to parse request body", http.StatusBadRequest)
|
||||
|
||||
@@ -44,7 +44,7 @@ func (c *Client) CreateCompletionStream(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := sendRequestStream[CompletionResponse](c, req)
|
||||
resp, err := c.sendRequestStream[CompletionResponse](req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
+2
-3
@@ -193,7 +193,7 @@ func TestCreateCompletionStreamTooManyEmptyStreamMessagesError(t *testing.T) {
|
||||
dataBytes = append(dataBytes, []byte("data: "+data+"\n\n")...)
|
||||
|
||||
// Totally 301 empty messages (300 is the limit)
|
||||
for i := 0; i < 299; i++ {
|
||||
for range 299 {
|
||||
dataBytes = append(dataBytes, '\n')
|
||||
}
|
||||
|
||||
@@ -296,8 +296,7 @@ func TestCreateCompletionStreamBrokenJSONError(t *testing.T) {
|
||||
|
||||
_, _ = stream.Recv()
|
||||
_, streamErr := stream.Recv()
|
||||
var syntaxError *json.SyntaxError
|
||||
if !errors.As(streamErr, &syntaxError) {
|
||||
if _, ok := errors.AsType[*json.SyntaxError](streamErr); !ok {
|
||||
t.Errorf("TestCreateCompletionStreamBrokenJSONError did not return json.SyntaxError")
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -84,7 +84,7 @@ func TestThread(t *testing.T) {
|
||||
checks.NoError(t, err, "RetrieveThread error")
|
||||
|
||||
_, err = client.ModifyThread(ctx, threadID, openai.ModifyThreadRequest{
|
||||
Metadata: map[string]interface{}{
|
||||
Metadata: map[string]any{
|
||||
"key": "value",
|
||||
},
|
||||
})
|
||||
@@ -167,7 +167,7 @@ func TestAzureThread(t *testing.T) {
|
||||
checks.NoError(t, err, "RetrieveThread error")
|
||||
|
||||
_, err = client.ModifyThread(ctx, threadID, openai.ModifyThreadRequest{
|
||||
Metadata: map[string]interface{}{
|
||||
Metadata: map[string]any{
|
||||
"key": "value",
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user