diff --git a/client_test.go b/client_test.go index 321971445..bf2c9f094 100644 --- a/client_test.go +++ b/client_test.go @@ -276,10 +276,10 @@ func TestClientReturnsRequestBuilderErrors(t *testing.T) { testCases := []TestCase{ {"CreateCompletion", func() (any, error) { - return client.CreateCompletion(ctx, CompletionRequest{Prompt: "testing"}) + return client.CreateCompletion(ctx, CompletionRequest{Model: GPT3Dot5TurboInstruct, Prompt: "testing"}) }}, {"CreateCompletionStream", func() (any, error) { - return client.CreateCompletionStream(ctx, CompletionRequest{Prompt: ""}) + return client.CreateCompletionStream(ctx, CompletionRequest{Model: GPT3Dot5TurboInstruct, Prompt: ""}) }}, {"CreateChatCompletion", func() (any, error) { return client.CreateChatCompletion(ctx, ChatCompletionRequest{Model: GPT3Dot5Turbo}) @@ -475,11 +475,11 @@ func TestClientReturnsRequestBuilderErrorsAddition(t *testing.T) { client := NewClientWithConfig(config) client.requestBuilder = &failingRequestBuilder{} ctx := context.Background() - _, err := client.CreateCompletion(ctx, CompletionRequest{Prompt: 1}) + _, err := client.CreateCompletion(ctx, CompletionRequest{Model: GPT3Dot5TurboInstruct, Prompt: 1}) if !errors.Is(err, ErrCompletionRequestPromptTypeNotSupported) { t.Fatalf("Did not return error when request builder failed: %v", err) } - _, err = client.CreateCompletionStream(ctx, CompletionRequest{Prompt: 1}) + _, err = client.CreateCompletionStream(ctx, CompletionRequest{Model: GPT3Dot5TurboInstruct, Prompt: 1}) if !errors.Is(err, ErrCompletionRequestPromptTypeNotSupported) { t.Fatalf("Did not return error when request builder failed: %v", err) } diff --git a/completion.go b/completion.go index 9c3a64dd5..71c8a7df2 100644 --- a/completion.go +++ b/completion.go @@ -5,6 +5,11 @@ import ( "net/http" ) +// Endpoint constants. +const ( + completionsEndpoint = "/completions" +) + // GPT3 Defines the models provided by OpenAI to use when generating // completions from OpenAI. // GPT3 Models are designed for text-based tasks. For code-specific @@ -95,75 +100,61 @@ const ( CodexCodeDavinci001 = "code-davinci-001" ) -var disabledModelsForEndpoints = map[string]map[string]bool{ - "/completions": { - O1Mini: true, - O1Mini20240912: true, - O1Preview: true, - O1Preview20240912: true, - O3Mini: true, - O3Mini20250131: true, - O4Mini: true, - O4Mini2020416: true, - O3: true, - O320250416: true, - GPT3Dot5Turbo: true, - GPT3Dot5Turbo0301: true, - GPT3Dot5Turbo0613: true, - GPT3Dot5Turbo1106: true, - GPT3Dot5Turbo0125: true, - GPT3Dot5Turbo16K: true, - GPT3Dot5Turbo16K0613: true, - GPT4: true, - GPT4Dot5Preview: true, - GPT4Dot5Preview20250227: true, - GPT4o: true, - GPT4o20240513: true, - GPT4o20240806: true, - GPT4o20241120: true, - GPT4oLatest: true, - GPT4oMini: true, - GPT4oMini20240718: true, - GPT4TurboPreview: true, - GPT4VisionPreview: true, - GPT4Turbo1106: true, - GPT4Turbo0125: true, - GPT4Turbo: true, - GPT4Turbo20240409: true, - GPT40314: true, - GPT40613: true, - GPT432K: true, - GPT432K0314: true, - GPT432K0613: true, - O1: true, - GPT4Dot1: true, - GPT4Dot120250414: true, - GPT4Dot1Mini: true, - GPT4Dot1Mini20250414: true, - GPT4Dot1Nano: true, - GPT4Dot1Nano20250414: true, - }, - chatCompletionsSuffix: { - CodexCodeDavinci002: true, - CodexCodeCushman001: true, - CodexCodeDavinci001: true, - GPT3TextDavinci003: true, - GPT3TextDavinci002: true, - GPT3TextCurie001: true, - GPT3TextBabbage001: true, - GPT3TextAda001: true, - GPT3TextDavinci001: true, - GPT3DavinciInstructBeta: true, - GPT3Davinci: true, - GPT3CurieInstructBeta: true, - GPT3Curie: true, - GPT3Ada: true, - GPT3Babbage: true, - }, +// This map lists models that are *not* supported by the chat completions endpoint. +// We maintain this deny list because most new models *are* supported by chat completions. +// It is simpler to list the exceptions rather than updating an allow list +// each time a new model is released and supported. +var disabledModelsForChatCompletionsEndpoint = map[string]bool{ + CodexCodeCushman001: true, + CodexCodeDavinci001: true, + CodexCodeDavinci002: true, + GPT3Ada: true, + GPT3Babbage: true, + GPT3Curie: true, + GPT3CurieInstructBeta: true, + GPT3Davinci: true, + GPT3DavinciInstructBeta: true, + GPT3TextAda001: true, + GPT3TextBabbage001: true, + GPT3TextCurie001: true, + GPT3TextDavinci001: true, + GPT3TextDavinci002: true, + GPT3TextDavinci003: true, +} + +// This map lists models that *are* supported by the deprecated completions endpoint. +// We maintain this allow list because the completions endpoint is deprecated and most new models +// are *not* supported by it. It is simpler to list the older models that are supported +// rather than updating a deny list each time a new model is released and *not* supported. +var enabledModelsForDeprecatedCompletionsEndpoint = map[string]bool{ + CodexCodeCushman001: true, + CodexCodeDavinci001: true, + CodexCodeDavinci002: true, + GPT3Ada: true, + GPT3Ada002: true, + GPT3Babbage: true, + GPT3Babbage002: true, + GPT3Curie: true, + GPT3Curie002: true, + GPT3CurieInstructBeta: true, + GPT3Davinci: true, + GPT3Davinci002: true, + GPT3DavinciInstructBeta: true, + GPT3Dot5TurboInstruct: true, + GPT3TextAda001: true, + GPT3TextBabbage001: true, + GPT3TextCurie001: true, + GPT3TextDavinci001: true, + GPT3TextDavinci002: true, + GPT3TextDavinci003: true, } func checkEndpointSupportsModel(endpoint, model string) bool { - return !disabledModelsForEndpoints[endpoint][model] + if endpoint == completionsEndpoint { + return enabledModelsForDeprecatedCompletionsEndpoint[model] + } + + return !disabledModelsForChatCompletionsEndpoint[model] } func checkPromptType(prompt any) bool { @@ -261,7 +252,7 @@ func (c *Client) CreateCompletion( return } - urlSuffix := "/completions" + urlSuffix := completionsEndpoint if !checkEndpointSupportsModel(urlSuffix, request.Model) { err = ErrCompletionUnsupportedModel return