From a514983ca3304f74a44080cbaa1efaa234fbf75d Mon Sep 17 00:00:00 2001 From: Carl-Robert Linnupuu Date: Wed, 3 May 2023 22:16:25 +0100 Subject: [PATCH] 1.10.6 - Add support for both Azure auth methods --- build.gradle.kts | 4 +- .../codegpt/client/ClientProvider.java | 42 +++++++++++-------- .../state/settings/SettingsComponent.java | 22 ++++++++-- .../state/settings/SettingsConfigurable.java | 5 +++ .../codegpt/state/settings/SettingsState.java | 1 + src/main/resources/META-INF/plugin.xml | 1 + .../codegpt/client/RequestHandlerTest.java | 2 +- 7 files changed, 54 insertions(+), 23 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0855e810..04166ecc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } group = "ee.carlrobert" -version = "1.10.5" +version = "1.10.6" repositories { mavenCentral() @@ -24,7 +24,7 @@ dependencies { implementation("com.fifesoft:rsyntaxtextarea:3.3.2") implementation("com.vladsch.flexmark:flexmark-all:0.64.0") implementation("org.apache.commons:commons-text:1.10.0") - implementation("ee.carlrobert:openai-client:1.0.14") + implementation("ee.carlrobert:openai-client:1.1.0") implementation("com.knuddels:jtokkit:0.2.0") testImplementation("org.assertj:assertj-core:3.24.2") diff --git a/src/main/java/ee/carlrobert/codegpt/client/ClientProvider.java b/src/main/java/ee/carlrobert/codegpt/client/ClientProvider.java index 844af62a..21a5533d 100644 --- a/src/main/java/ee/carlrobert/codegpt/client/ClientProvider.java +++ b/src/main/java/ee/carlrobert/codegpt/client/ClientProvider.java @@ -2,6 +2,8 @@ package ee.carlrobert.codegpt.client; import ee.carlrobert.codegpt.state.settings.SettingsState; import ee.carlrobert.codegpt.state.settings.advanced.AdvancedSettingsState; +import ee.carlrobert.openai.client.AzureClient; +import ee.carlrobert.openai.client.Client; import ee.carlrobert.openai.client.OpenAIClient; import ee.carlrobert.openai.client.ProxyAuthenticator; import ee.carlrobert.openai.client.azure.AzureClientRequestParams; @@ -14,37 +16,41 @@ import java.util.concurrent.TimeUnit; public class ClientProvider { public static DashboardClient getDashboardClient() { - return getClientBuilder().buildDashboardClient(); + return getOpenAIClientBuilder().buildDashboardClient(); } + public static CompletionClient getChatCompletionClient(SettingsState settings) { - if (settings.useAzureService) { - return getClientBuilder().buildAzureChatCompletionClient(getAzureRequestParams()); - } - return getClientBuilder().buildChatCompletionClient(); + return getClientBuilder(settings).buildChatCompletionClient(); } public static CompletionClient getTextCompletionClient(SettingsState settings) { - if (settings.useAzureService) { - return getClientBuilder().buildAzureTextCompletionClient(getAzureRequestParams()); - } - return getClientBuilder().buildTextCompletionClient(); + return getClientBuilder(settings).buildTextCompletionClient(); } - private static AzureClientRequestParams getAzureRequestParams() { - var settings = SettingsState.getInstance(); - return new AzureClientRequestParams(settings.resourceName, settings.deploymentId, settings.apiVersion); + private static Client.Builder getClientBuilder(SettingsState settings) { + return settings.useAzureService ? getAzureClientBuilder() : getOpenAIClientBuilder(); } - private static OpenAIClient.Builder getClientBuilder() { + private static OpenAIClient.Builder getOpenAIClientBuilder() { var settings = SettingsState.getInstance(); - var builder = new OpenAIClient.Builder(settings.apiKey) // TODO: ENV var? - .setConnectTimeout(60L, TimeUnit.SECONDS) - .setReadTimeout(30L, TimeUnit.SECONDS); + var builder = new OpenAIClient.Builder(settings.apiKey); if (settings.useOpenAIService) { builder.setOrganization(settings.organization); } + return (OpenAIClient.Builder) addDefaultClientParams(builder); + } + private static AzureClient.Builder getAzureClientBuilder() { + var settings = SettingsState.getInstance(); + var params = new AzureClientRequestParams( + settings.resourceName, settings.deploymentId, settings.apiVersion); + var builder = new AzureClient.Builder(settings.apiKey, params) + .setActiveDirectoryAuthentication(settings.useActiveDirectoryAuthentication); + return (AzureClient.Builder) addDefaultClientParams(builder); + } + + private static Client.Builder addDefaultClientParams(Client.Builder builder) { var advancedSettings = AdvancedSettingsState.getInstance(); var proxyHost = advancedSettings.proxyHost; var proxyPort = advancedSettings.proxyPort; @@ -61,7 +67,9 @@ public class ClientProvider { builder.setHost(advancedSettings.host); } - return builder; + return builder + .setConnectTimeout(60L, TimeUnit.SECONDS) + .setReadTimeout(30L, TimeUnit.SECONDS); } } diff --git a/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsComponent.java b/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsComponent.java index c28a05e5..fecefcd0 100644 --- a/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsComponent.java +++ b/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsComponent.java @@ -24,13 +24,14 @@ import javax.swing.event.HyperlinkEvent; public class SettingsComponent { private final JPanel mainPanel; + private final JBTextField apiKeyField; + private final JBTextField organizationField; private final JBTextField resourceNameField; private final JBTextField deploymentIdField; private final JBTextField apiVersionField; - private final JBTextField apiKeyField; - private final JBTextField organizationField; private final JBTextField displayNameField; private final JBCheckBox useOpenAIAccountNameCheckBox; + private final JBCheckBox useActiveDirectoryAuthenticationCheckBox; private final JBRadioButton useAzureServiceRadioButton; private final JBRadioButton useOpenAIServiceRadioButton; private final ComboBox chatCompletionBaseModelComboBox; @@ -49,7 +50,10 @@ public class SettingsComponent { apiVersionField = new JBTextField(settings.resourceName, 40); organizationField = new JBTextField(settings.organization, 40); displayNameField = new JBTextField(settings.displayName, 20); - useOpenAIAccountNameCheckBox = new JBCheckBox("Use OpenAI account name", true); + useOpenAIAccountNameCheckBox = new JBCheckBox( + "Use OpenAI account name", settings.useOpenAIAccountName); + useActiveDirectoryAuthenticationCheckBox = new JBCheckBox( + "Use Azure Active Directory authentication", settings.useActiveDirectoryAuthentication); chatCompletionBaseModelComboBox = new BaseModelComboBox( new ChatCompletionModel[]{ ChatCompletionModel.GPT_3_5, @@ -117,6 +121,14 @@ public class SettingsComponent { useAzureServiceRadioButton.setSelected(selected); } + public boolean isUseActiveDirectoryAuthentication() { + return useActiveDirectoryAuthenticationCheckBox.isSelected(); + } + + public void setUseActiveDirectoryAuthenticationSelected(boolean selected) { + useActiveDirectoryAuthenticationCheckBox.setSelected(selected); + } + public boolean isUseAzureService() { return useAzureServiceRadioButton.isSelected(); } @@ -294,12 +306,16 @@ public class SettingsComponent { .withComment( "API version to be used for Azure OpenAI Service") .createPanel(); + var authFieldPanel = UI.PanelFactory.panel(useActiveDirectoryAuthenticationCheckBox) + .resizeX(false) + .createPanel(); azureRelatedFieldsPanel.setLayout(new BoxLayout(azureRelatedFieldsPanel, BoxLayout.Y_AXIS)); azureRelatedFieldsPanel.setBorder(JBUI.Borders.empty(8, 16, 0, 0)); azureRelatedFieldsPanel.add(resourceNameFieldPanel); azureRelatedFieldsPanel.add(deploymentIdFieldPanel); azureRelatedFieldsPanel.add(apiVersionFieldPanel); + azureRelatedFieldsPanel.add(authFieldPanel); SwingUtils.setEqualLabelWidths(deploymentIdFieldPanel, resourceNameFieldPanel); SwingUtils.setEqualLabelWidths(apiVersionFieldPanel, resourceNameFieldPanel); diff --git a/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsConfigurable.java b/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsConfigurable.java index 34aa81f8..ff674347 100644 --- a/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsConfigurable.java +++ b/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsConfigurable.java @@ -39,6 +39,8 @@ public class SettingsConfigurable implements Configurable { return !settingsComponent.getApiKey().equals(settings.apiKey) || settingsComponent.isUseOpenAIService() != settings.useOpenAIService || settingsComponent.isUseAzureService() != settings.useAzureService || + settingsComponent.isUseActiveDirectoryAuthentication() != + settings.useActiveDirectoryAuthentication || !settingsComponent.getResourceName().equals(settings.resourceName) || !settingsComponent.getDeploymentId().equals(settings.deploymentId) || !settingsComponent.getApiVersion().equals(settings.apiVersion) || @@ -77,6 +79,7 @@ public class SettingsConfigurable implements Configurable { settings.apiKey = settingsComponent.getApiKey(); settings.useOpenAIService = settingsComponent.isUseOpenAIService(); settings.useAzureService = settingsComponent.isUseAzureService(); + settings.useActiveDirectoryAuthentication = settingsComponent.isUseActiveDirectoryAuthentication(); settings.resourceName = settingsComponent.getResourceName(); settings.deploymentId = settingsComponent.getDeploymentId(); settings.apiVersion = settingsComponent.getApiVersion(); @@ -97,6 +100,8 @@ public class SettingsConfigurable implements Configurable { settingsComponent.setApiKey(settings.apiKey); settingsComponent.setUseOpenAIServiceSelected(settings.useAzureService); settingsComponent.setUseAzureServiceSelected(settings.useAzureService); + settingsComponent.setUseActiveDirectoryAuthenticationSelected( + settings.useActiveDirectoryAuthentication); settingsComponent.setResourceName(settings.resourceName); settingsComponent.setDeploymentId(settings.deploymentId); settingsComponent.setApiVersionField(settings.apiVersion); diff --git a/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsState.java b/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsState.java index 8e1c0088..3ef01d43 100644 --- a/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsState.java +++ b/src/main/java/ee/carlrobert/codegpt/state/settings/SettingsState.java @@ -24,6 +24,7 @@ public class SettingsState implements PersistentStateComponent { public String resourceName = ""; public String deploymentId = ""; public String apiVersion = ""; + public boolean useActiveDirectoryAuthentication; public String organization = ""; public String displayName = getDisplayName(); public boolean useOpenAIAccountName = true; diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index eb99c27e..a7c3f0fe 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -68,6 +68,7 @@
  • Sync model settings on tab change
  • Improve error msg display
  • Add Azure Service support
  • +
  • Support both Azure authentications
  • ]]> diff --git a/src/test/java/ee/carlrobert/codegpt/client/RequestHandlerTest.java b/src/test/java/ee/carlrobert/codegpt/client/RequestHandlerTest.java index e0ab8b66..0fc5874b 100644 --- a/src/test/java/ee/carlrobert/codegpt/client/RequestHandlerTest.java +++ b/src/test/java/ee/carlrobert/codegpt/client/RequestHandlerTest.java @@ -125,7 +125,7 @@ public class RequestHandlerTest extends BasePlatformTestCase { settings.chatCompletionBaseModel = ChatCompletionModel.GPT_3_5.getCode(); expectStreamRequest("/openai/deployments/TEST_DEPLOYMENT_ID/chat/completions", request -> { assertThat(request.getUri().getQuery()).isEqualTo("api-version=TEST_API_VERSION"); - assertThat(request.getHeaders().get("Authorization").get(0)).isEqualTo("Bearer TEST_API_KEY"); + assertThat(request.getHeaders().get("Api-key").get(0)).isEqualTo("TEST_API_KEY"); assertThat(request.getBody()) .extracting( "model",