Adding a backport of the azure changes to the 5.3.x to support both old and new OpenAI APIs

This commit is contained in:
arafatkatze 2024-07-14 23:58:44 +02:00 committed by Anish Lakhwara
parent ece951aa6c
commit 6834a0a6ea
7 changed files with 733 additions and 173 deletions

View File

@ -30,7 +30,6 @@ var authProxyURL = os.Getenv("CODY_AZURE_OPENAI_IDENTITY_HTTP_PROXY")
// it will acquire a short lived token and reusing the client
// prevents acquiring a new token on every request.
// The client will refresh the token as needed.
var apiClient completionsClient
type completionsClient struct {
@ -123,10 +122,9 @@ type azureCompletionClient struct {
func (c *azureCompletionClient) Complete(
ctx context.Context,
feature types.CompletionsFeature,
_ types.CompletionsVersion,
version types.CompletionsVersion,
requestParams types.CompletionRequestParameters,
) (*types.CompletionResponse, error) {
switch feature {
case types.CompletionsFeatureCode:
return completeAutocomplete(ctx, c.client, requestParams)
@ -141,6 +139,35 @@ func completeAutocomplete(
ctx context.Context,
client CompletionsClient,
requestParams types.CompletionRequestParameters,
) (*types.CompletionResponse, error) {
if requestParams.AzureUseDeprecatedCompletionsAPIForOldModels {
return doCompletionsAPIAutocomplete(ctx, client, requestParams)
}
return doChatCompletionsAPIAutocomplete(ctx, client, requestParams)
}
func doChatCompletionsAPIAutocomplete(
ctx context.Context,
client CompletionsClient,
requestParams types.CompletionRequestParameters,
) (*types.CompletionResponse, error) {
response, err := client.GetChatCompletions(ctx, getChatOptions(requestParams), nil)
if err != nil {
return nil, toStatusCodeError(err)
}
if !hasValidFirstChatChoice(response.Choices) {
return &types.CompletionResponse{}, nil
}
return &types.CompletionResponse{
Completion: *response.Choices[0].Delta.Content,
StopReason: string(*response.Choices[0].FinishReason),
}, nil
}
func doCompletionsAPIAutocomplete(
ctx context.Context,
client CompletionsClient,
requestParams types.CompletionRequestParameters,
) (*types.CompletionResponse, error) {
options, err := getCompletionsOptions(requestParams)
if err != nil {
@ -150,7 +177,6 @@ func completeAutocomplete(
if err != nil {
return nil, toStatusCodeError(err)
}
// Text and FinishReason are documented as REQUIRED but checking just to be safe
if !hasValidFirstCompletionsChoice(response.Choices) {
return &types.CompletionResponse{}, nil
@ -182,7 +208,7 @@ func completeChat(
func (c *azureCompletionClient) Stream(
ctx context.Context,
feature types.CompletionsFeature,
_ types.CompletionsVersion,
version types.CompletionsVersion,
requestParams types.CompletionRequestParameters,
sendEvent types.SendCompletionEvent,
) error {
@ -201,6 +227,60 @@ func streamAutocomplete(
client CompletionsClient,
requestParams types.CompletionRequestParameters,
sendEvent types.SendCompletionEvent,
) error {
if requestParams.AzureUseDeprecatedCompletionsAPIForOldModels {
return doStreamCompletionsAPI(ctx, client, requestParams, sendEvent)
}
return doStreamChatCompletionsAPI(ctx, client, requestParams, sendEvent)
}
// Streaming with ChatCompletions API
func doStreamChatCompletionsAPI(
ctx context.Context,
client CompletionsClient,
requestParams types.CompletionRequestParameters,
sendEvent types.SendCompletionEvent,
) error {
resp, err := client.GetChatCompletionsStream(ctx, getChatOptions(requestParams), nil)
if err != nil {
return err
}
defer resp.ChatCompletionsStream.Close()
var content string
for {
entry, err := resp.ChatCompletionsStream.Read()
if errors.Is(err, io.EOF) {
return nil
}
if err != nil {
return err
}
if hasValidFirstChatChoice(entry.Choices) {
content += *entry.Choices[0].Delta.Content
finish := ""
if entry.Choices[0].FinishReason != nil {
finish = string(*entry.Choices[0].FinishReason)
}
ev := types.CompletionResponse{
Completion: content,
StopReason: finish,
}
err := sendEvent(ev)
if err != nil {
return err
}
}
}
}
// Streaming with Completions API
func doStreamCompletionsAPI(
ctx context.Context,
client CompletionsClient,
requestParams types.CompletionRequestParameters,
sendEvent types.SendCompletionEvent,
) error {
options, err := getCompletionsOptions(requestParams)
if err != nil {
@ -225,7 +305,6 @@ func streamAutocomplete(
if err != nil {
return err
}
// hasValidFirstCompletionsChoice checks for a valid 1st choice which has text
if hasValidFirstCompletionsChoice(entry.Choices) {
content += *entry.Choices[0].Text
@ -261,6 +340,7 @@ func streamChat(
// Azure sends incremental deltas for each message in a chat stream
// build up the full message content over multiple responses
var content string
for {
entry, err := resp.ChatCompletionsStream.Read()
// stream is done

View File

@ -105,6 +105,7 @@ func newCompletionsHandler(
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
requestParams.AzureUseDeprecatedCompletionsAPIForOldModels = completionsConfig.AzureUseDeprecatedCompletionsAPIForOldModels
ctx, done := Trace(ctx, traceFamily, requestParams.Model, requestParams.MaxTokensToSample).
WithErrorP(&err).

View File

@ -48,21 +48,27 @@ type CodyCompletionRequestParameters struct {
// that is faster (but probably "dumber").
Fast bool
}
type CompletionRequest struct {
Feature CompletionsFeature
Version CompletionsVersion
Parameters CompletionRequestParameters
}
type CompletionRequestParameters struct {
// Prompt exists only for backwards compatibility. Do not use it in new
// implementations. It will be removed once we are reasonably sure 99%
// of VSCode extension installations are upgraded to a new Cody version.
Prompt string `json:"prompt"`
Messages []Message `json:"messages"`
MaxTokensToSample int `json:"maxTokensToSample,omitempty"`
Temperature float32 `json:"temperature,omitempty"`
StopSequences []string `json:"stopSequences,omitempty"`
TopK int `json:"topK,omitempty"`
TopP float32 `json:"topP,omitempty"`
Model string `json:"model,omitempty"`
Stream *bool `json:"stream,omitempty"`
Logprobs *uint8 `json:"logprobs"`
Prompt string `json:"prompt"`
Messages []Message `json:"messages"`
MaxTokensToSample int `json:"maxTokensToSample,omitempty"`
Temperature float32 `json:"temperature,omitempty"`
StopSequences []string `json:"stopSequences,omitempty"`
TopK int `json:"topK,omitempty"`
TopP float32 `json:"topP,omitempty"`
Model string `json:"model,omitempty"`
Stream *bool `json:"stream,omitempty"`
Logprobs *uint8 `json:"logprobs"`
AzureUseDeprecatedCompletionsAPIForOldModels bool `json:"azureUseDeprecatedCompletionsAPIForOldModels,omitempty"`
}
// IsStream returns whether a streaming response is requested. For backwards

View File

@ -835,18 +835,19 @@ func GetCompletionsConfig(siteConfig schema.SiteConfiguration) (c *conftypes.Com
}
computedConfig := &conftypes.CompletionsConfig{
Provider: conftypes.CompletionsProviderName(completionsConfig.Provider),
AccessToken: completionsConfig.AccessToken,
ChatModel: completionsConfig.ChatModel,
ChatModelMaxTokens: completionsConfig.ChatModelMaxTokens,
FastChatModel: completionsConfig.FastChatModel,
FastChatModelMaxTokens: completionsConfig.FastChatModelMaxTokens,
CompletionModel: completionsConfig.CompletionModel,
CompletionModelMaxTokens: completionsConfig.CompletionModelMaxTokens,
Endpoint: completionsConfig.Endpoint,
PerUserDailyLimit: completionsConfig.PerUserDailyLimit,
PerUserCodeCompletionsDailyLimit: completionsConfig.PerUserCodeCompletionsDailyLimit,
PerCommunityUserChatMonthlyLLMRequestLimit: completionsConfig.PerCommunityUserChatMonthlyLLMRequestLimit,
Provider: conftypes.CompletionsProviderName(completionsConfig.Provider),
AccessToken: completionsConfig.AccessToken,
ChatModel: completionsConfig.ChatModel,
ChatModelMaxTokens: completionsConfig.ChatModelMaxTokens,
FastChatModel: completionsConfig.FastChatModel,
FastChatModelMaxTokens: completionsConfig.FastChatModelMaxTokens,
AzureUseDeprecatedCompletionsAPIForOldModels: completionsConfig.AzureUseDeprecatedCompletionsAPIForOldModels,
CompletionModel: completionsConfig.CompletionModel,
CompletionModelMaxTokens: completionsConfig.CompletionModelMaxTokens,
Endpoint: completionsConfig.Endpoint,
PerUserDailyLimit: completionsConfig.PerUserDailyLimit,
PerUserCodeCompletionsDailyLimit: completionsConfig.PerUserCodeCompletionsDailyLimit,
PerCommunityUserChatMonthlyLLMRequestLimit: completionsConfig.PerCommunityUserChatMonthlyLLMRequestLimit,
PerCommunityUserCodeCompletionsMonthlyLLMRequestLimit: completionsConfig.PerCommunityUserCodeCompletionsMonthlyLLMRequestLimit,
PerProUserChatDailyLLMRequestLimit: completionsConfig.PerProUserChatDailyLLMRequestLimit,
PerProUserCodeCompletionsDailyLLMRequestLimit: completionsConfig.PerProUserCodeCompletionsDailyLLMRequestLimit,

View File

@ -12,6 +12,10 @@ type CompletionsConfig struct {
CompletionModel string
CompletionModelMaxTokens int
AzureCompletionModel string
AzureChatModel string
AzureUseDeprecatedCompletionsAPIForOldModels bool
AccessToken string
Provider CompletionsProviderName
Endpoint string

View File

@ -630,6 +630,8 @@ type CodyGateway struct {
type Completions struct {
// AccessToken description: The access token used to authenticate with the external completions provider. If using the default provider 'sourcegraph', and if 'licenseKey' is set, a default access token is generated.
AccessToken string `json:"accessToken,omitempty"`
// AzureUseDeprecatedCompletionsAPIForOldModels description: Enables the use of the older completions API for select Azure OpenAI models.
AzureUseDeprecatedCompletionsAPIForOldModels bool `json:"azureUseDeprecatedCompletionsAPIForOldModels,omitempty"`
// ChatModel description: The model used for chat completions. If using the default provider 'sourcegraph', a reasonable default model will be set.
// NOTE: The Anthropic messages API does not support model names like claude-2 or claude-instant-1 where only the major version is specified as they are retired. We recommed using a specific model identifier as specified here https://docs.anthropic.com/claude/docs/models-overview#model-comparison
ChatModel string `json:"chatModel,omitempty"`

File diff suppressed because it is too large Load Diff