feat: support custom OpenAI-compatible service (#383)

This commit is contained in:
Carl-Robert 2024-02-23 17:41:44 +02:00 committed by GitHub
parent c8bb33d9b2
commit 8507c779b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 772 additions and 166 deletions

View file

@ -37,6 +37,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import okhttp3.sse.EventSource;
import org.jetbrains.annotations.NotNull;
public class GenerateGitCommitMessageAction extends AnAction {
@ -102,7 +103,7 @@ public class GenerateGitCommitMessageAction extends AnAction {
private final StringBuilder messageBuilder = new StringBuilder();
@Override
public void onMessage(String message) {
public void onMessage(String message, EventSource eventSource) {
messageBuilder.append(message);
var application = ApplicationManager.getApplication();
application.invokeLater(() ->

View file

@ -10,6 +10,10 @@ public class CallParameters {
private final Message message;
private final boolean retry;
public CallParameters(Conversation conversation, Message message) {
this(conversation, ConversationType.DEFAULT, message, false);
}
public CallParameters(
Conversation conversation,
ConversationType conversationType,

View file

@ -26,14 +26,9 @@ import okhttp3.OkHttpClient;
public class CompletionClientProvider {
public static OpenAIClient getOpenAIClient() {
var settings = OpenAISettings.getCurrentState();
var builder = new OpenAIClient.Builder(OpenAICredentialManager.getInstance().getCredential())
.setOrganization(settings.getOrganization());
var baseHost = settings.getBaseHost();
if (baseHost != null) {
builder.setHost(baseHost);
}
return builder.build(getDefaultClientBuilder());
return new OpenAIClient.Builder(OpenAICredentialManager.getInstance().getCredential())
.setOrganization(OpenAISettings.getCurrentState().getOrganization())
.build(getDefaultClientBuilder());
}
public static AzureClient getAzureClient() {
@ -87,7 +82,7 @@ public class CompletionClientProvider {
return builder.build(getDefaultClientBuilder());
}
private static OkHttpClient.Builder getDefaultClientBuilder() {
public static OkHttpClient.Builder getDefaultClientBuilder() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
var advancedSettings = AdvancedSettings.getCurrentState();
var proxyHost = advancedSettings.getProxyHost();

View file

@ -101,7 +101,7 @@ public class CompletionRequestHandler {
}
@Override
public void onMessage(String message) {
public void onMessage(String message, EventSource eventSource) {
publish(message);
}

View file

@ -5,6 +5,8 @@ import static java.lang.String.format;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import ee.carlrobert.codegpt.CodeGPTPlugin;
@ -14,10 +16,12 @@ import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.conversations.Conversation;
import ee.carlrobert.codegpt.conversations.ConversationsState;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.credentials.CustomServiceCredentialManager;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.IncludedFilesSettings;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceState;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
import ee.carlrobert.codegpt.settings.service.you.YouSettings;
@ -31,11 +35,16 @@ import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionMe
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionRequest;
import ee.carlrobert.llm.client.you.completion.YouCompletionRequest;
import ee.carlrobert.llm.client.you.completion.YouCompletionRequestMessage;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import okhttp3.Request;
import okhttp3.RequestBody;
import org.jetbrains.annotations.Nullable;
public class CompletionRequestProvider {
@ -247,4 +256,51 @@ public class CompletionRequestProvider {
return messages.stream().filter(Objects::nonNull).collect(toList());
}
public Request buildCustomOpenAIChatCompletionRequest(
CustomServiceState customConfiguration,
CallParameters callParameters) {
var requestBuilder = new Request.Builder().url(customConfiguration.getUrl().trim());
for (var entry : customConfiguration.getHeaders().entrySet()) {
String value = entry.getValue();
if (value.contains("$CUSTOM_SERVICE_API_KEY")) {
value = value.replace("$CUSTOM_SERVICE_API_KEY",
CustomServiceCredentialManager.getInstance().getCredential());
}
requestBuilder.addHeader(entry.getKey(), value);
}
var body = customConfiguration.getBody().entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> processEntryValue(entry.getValue(), callParameters)
));
try {
var requestBody = RequestBody.create(new ObjectMapper()
.writerWithDefaultPrettyPrinter()
.writeValueAsString(body)
.getBytes(StandardCharsets.UTF_8));
return requestBuilder.post(requestBody).build();
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
private Object processEntryValue(Object value, CallParameters callParameters) {
if (!(value instanceof String)) {
return value;
}
String stringValue = (String) value;
switch (stringValue.toLowerCase().trim()) {
case "$openai_messages":
return buildMessages(callParameters, false);
case "true":
case "false":
return Boolean.parseBoolean(stringValue);
default:
return value;
}
}
}

View file

@ -16,15 +16,19 @@ import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
import ee.carlrobert.llm.client.llama.completion.LlamaCompletionRequest;
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionEventSourceListener;
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionMessage;
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionRequest;
import ee.carlrobert.llm.completion.CompletionEventListener;
import java.util.List;
import java.util.Optional;
import okhttp3.Request;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSources;
@Service
public final class CompletionRequestService {
@ -36,6 +40,15 @@ public final class CompletionRequestService {
return ApplicationManager.getApplication().getService(CompletionRequestService.class);
}
public EventSource getCustomOpenAIChatCompletionAsync(
Request customRequest,
CompletionEventListener<String> eventListener) {
var httpClient = CompletionClientProvider.getDefaultClientBuilder().build();
return EventSources.createFactory(httpClient).newEventSource(
customRequest,
new OpenAIChatCompletionEventSourceListener(eventListener));
}
public EventSource getChatCompletionAsync(
CallParameters callParameters,
boolean useContextualSearch,
@ -44,13 +57,19 @@ public final class CompletionRequestService {
switch (GeneralSettings.getCurrentState().getSelectedService()) {
case OPENAI:
var openAISettings = OpenAISettings.getCurrentState();
var customModel = openAISettings.getCustomModel();
return CompletionClientProvider.getOpenAIClient().getChatCompletionAsync(
requestProvider.buildOpenAIChatCompletionRequest(
customModel.trim().isEmpty() ? openAISettings.getModel() : customModel,
openAISettings.getModel(),
callParameters,
useContextualSearch,
openAISettings.isUsingCustomPath() ? openAISettings.getPath() : null),
null),
eventListener);
case CUSTOM_OPENAI:
var customConfiguration = CustomServiceSettings.getCurrentState();
return getCustomOpenAIChatCompletionAsync(
requestProvider.buildCustomOpenAIChatCompletionRequest(
customConfiguration,
callParameters),
eventListener);
case AZURE:
var azureSettings = AzureSettings.getCurrentState();

View file

@ -190,6 +190,8 @@ public final class ConversationService {
switch (serviceType) {
case OPENAI:
return OpenAISettings.getCurrentState().getModel();
case CUSTOM_OPENAI:
return "CustomService";
case AZURE:
return AzureSettings.getCurrentState().getDeploymentId();
case YOU:

View file

@ -0,0 +1,16 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
@Service
public final class CustomServiceCredentialManager extends SingleCredentialManager {
private CustomServiceCredentialManager() {
super("CUSTOM_SERVICE_API_KEY");
}
public static CustomServiceCredentialManager getInstance() {
return ApplicationManager.getApplication().getService(CustomServiceCredentialManager.class);
}
}

View file

@ -1,6 +1,7 @@
package ee.carlrobert.codegpt.settings;
import static ee.carlrobert.codegpt.settings.service.ServiceType.AZURE;
import static ee.carlrobert.codegpt.settings.service.ServiceType.CUSTOM_OPENAI;
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
import static ee.carlrobert.codegpt.settings.service.ServiceType.YOU;
@ -8,13 +9,16 @@ import static java.util.stream.Collectors.toList;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.SystemInfoRt;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.settings.service.ServiceSelectionForm;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.util.Arrays;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComponent;
@ -30,9 +34,12 @@ public class GeneralSettingsComponent {
public GeneralSettingsComponent(Disposable parentDisposable, GeneralSettings settings) {
displayNameField = new JBTextField(settings.getState().getDisplayName(), 20);
serviceSelectionForm = new ServiceSelectionForm(parentDisposable);
var cardLayout = new CardLayout();
var cardLayout = new DynamicCardLayout();
var cards = new JPanel(cardLayout);
cards.add(serviceSelectionForm.getOpenAISettingsForm().getForm(), OPENAI.getCode());
cards.add(
serviceSelectionForm.getCustomConfigurationSettingsForm().getForm(),
CUSTOM_OPENAI.getCode());
cards.add(serviceSelectionForm.getAzureSettingsForm().getForm(), AZURE.getCode());
cards.add(serviceSelectionForm.getYouSettingsForm(), YOU.getCode());
cards.add(serviceSelectionForm.getLlamaSettingsForm(), LLAMA_CPP.getCode());
@ -83,4 +90,29 @@ public class GeneralSettingsComponent {
public void setDisplayName(String displayName) {
displayNameField.setText(displayName);
}
static class DynamicCardLayout extends CardLayout {
@Override
public Dimension preferredLayoutSize(Container parent) {
Component current = findVisibleComponent(parent);
if (current != null) {
Insets insets = parent.getInsets();
Dimension preferredSize = current.getPreferredSize();
preferredSize.width += insets.left + insets.right;
preferredSize.height += insets.top + insets.bottom;
return preferredSize;
}
return super.preferredLayoutSize(parent);
}
private Component findVisibleComponent(Container parent) {
for (Component comp : parent.getComponents()) {
if (comp.isVisible()) {
return comp;
}
}
return null;
}
}
}

View file

@ -6,10 +6,13 @@ import com.intellij.openapi.util.Disposer;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.conversations.ConversationsState;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.CustomServiceCredentialManager;
import ee.carlrobert.codegpt.credentials.LlamaCredentialManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettingsForm;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceForm;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
import ee.carlrobert.codegpt.settings.service.llama.form.LlamaSettingsForm;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
@ -56,6 +59,8 @@ public class GeneralSettingsConfigurable implements Configurable {
return !component.getDisplayName().equals(settings.getDisplayName())
|| component.getSelectedService() != settings.getSelectedService()
|| OpenAISettings.getInstance().isModified(serviceSelectionForm.getOpenAISettingsForm())
|| CustomServiceSettings.getInstance()
.isModified(serviceSelectionForm.getCustomConfigurationSettingsForm())
|| AzureSettings.getInstance().isModified(serviceSelectionForm.getAzureSettingsForm())
|| YouSettings.getInstance().isModified(serviceSelectionForm.getYouSettingsForm())
|| LlamaSettings.getInstance().isModified(serviceSelectionForm.getLlamaSettingsForm());
@ -70,6 +75,7 @@ public class GeneralSettingsConfigurable implements Configurable {
var serviceSelectionForm = component.getServiceSelectionForm();
var openAISettingsForm = serviceSelectionForm.getOpenAISettingsForm();
applyOpenAISettings(openAISettingsForm);
applyCustomOpenAISettings(serviceSelectionForm.getCustomConfigurationSettingsForm());
applyAzureSettings(serviceSelectionForm.getAzureSettingsForm());
applyYouSettings(serviceSelectionForm.getYouSettingsForm());
applyLlamaSettings(serviceSelectionForm.getLlamaSettingsForm());
@ -87,6 +93,16 @@ public class GeneralSettingsConfigurable implements Configurable {
}
}
private void applyOpenAISettings(OpenAISettingsForm form) {
OpenAICredentialManager.getInstance().setCredential(form.getApiKey());
OpenAISettings.getInstance().loadState(form.getCurrentState());
}
private void applyCustomOpenAISettings(CustomServiceForm form) {
CustomServiceCredentialManager.getInstance().setCredential(form.getApiKey());
CustomServiceSettings.getInstance().loadState(form.getCurrentState());
}
private void applyLlamaSettings(LlamaSettingsForm form) {
LlamaCredentialManager.getInstance()
.setCredential(form.getLlamaServerPreferencesForm().getApiKey());
@ -109,12 +125,7 @@ public class GeneralSettingsConfigurable implements Configurable {
var settings = GeneralSettings.getCurrentState();
component.setDisplayName(settings.getDisplayName());
component.setSelectedService(settings.getSelectedService());
var serviceSelectionForm = component.getServiceSelectionForm();
serviceSelectionForm.getOpenAISettingsForm().resetForm();
serviceSelectionForm.getAzureSettingsForm().resetForm();
serviceSelectionForm.getLlamaSettingsForm().resetForm();
serviceSelectionForm.getYouSettingsForm().resetForm();
component.getServiceSelectionForm().resetForms();
}
@Override
@ -125,11 +136,6 @@ public class GeneralSettingsConfigurable implements Configurable {
component = null;
}
private void applyOpenAISettings(OpenAISettingsForm form) {
OpenAICredentialManager.getInstance().setCredential(form.getApiKey());
OpenAISettings.getInstance().loadState(form.getCurrentState());
}
private void resetActiveTab() {
ConversationsState.getInstance().setCurrentConversation(null);
var project = ApplicationUtil.findCurrentProject();

View file

@ -3,23 +3,27 @@ package ee.carlrobert.codegpt.settings.service;
import com.intellij.openapi.Disposable;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettingsForm;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceForm;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
import ee.carlrobert.codegpt.settings.service.llama.form.LlamaSettingsForm;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettingsForm;
import ee.carlrobert.codegpt.settings.service.you.YouSettings;
import ee.carlrobert.codegpt.settings.service.you.YouSettingsForm;
import ee.carlrobert.codegpt.settings.service.you.YouSettingsState;
public class ServiceSelectionForm {
private final OpenAISettingsForm openAISettingsForm;
private final CustomServiceForm customServiceForm;
private final AzureSettingsForm azureSettingsForm;
private final LlamaSettingsForm llamaSettingsForm;
private final YouSettingsForm youSettingsForm;
public ServiceSelectionForm(Disposable parentDisposable) {
openAISettingsForm = new OpenAISettingsForm(OpenAISettings.getCurrentState());
customServiceForm = new CustomServiceForm(
CustomServiceSettings.getCurrentState());
azureSettingsForm = new AzureSettingsForm(AzureSettings.getCurrentState());
youSettingsForm = new YouSettingsForm(YouSettings.getCurrentState(), parentDisposable);
llamaSettingsForm = new LlamaSettingsForm(LlamaSettings.getCurrentState());
@ -29,6 +33,10 @@ public class ServiceSelectionForm {
return openAISettingsForm;
}
public CustomServiceForm getCustomConfigurationSettingsForm() {
return customServiceForm;
}
public AzureSettingsForm getAzureSettingsForm() {
return azureSettingsForm;
}
@ -40,4 +48,12 @@ public class ServiceSelectionForm {
public LlamaSettingsForm getLlamaSettingsForm() {
return llamaSettingsForm;
}
public void resetForms() {
openAISettingsForm.resetForm();
customServiceForm.resetForm();
azureSettingsForm.resetForm();
youSettingsForm.resetForm();
llamaSettingsForm.resetForm();
}
}

View file

@ -3,18 +3,19 @@ package ee.carlrobert.codegpt.settings.service;
import ee.carlrobert.codegpt.CodeGPTBundle;
public enum ServiceType {
OPENAI("OPENAI", CodeGPTBundle.get("service.openai.title"), "chat.completion"),
AZURE("AZURE", CodeGPTBundle.get("service.azure.title"), "azure.chat.completion"),
YOU("YOU", CodeGPTBundle.get("service.you.title"), "you.chat.completion"),
LLAMA_CPP("LLAMA_CPP", CodeGPTBundle.get("service.llama.title"), "llama.chat.completion");
OPENAI("OPENAI", "service.openai.title", "chat.completion"),
CUSTOM_OPENAI("CUSTOM_OPENAI", "service.custom.openai.title", "custom.openai.chat.completion"),
AZURE("AZURE", "service.azure.title", "azure.chat.completion"),
YOU("YOU", "service.you.title", "you.chat.completion"),
LLAMA_CPP("LLAMA_CPP", "service.llama.title", "llama.chat.completion");
private final String code;
private final String label;
private final String completionCode;
ServiceType(String code, String label, String completionCode) {
ServiceType(String code, String messageKey, String completionCode) {
this.code = code;
this.label = label;
this.label = CodeGPTBundle.get(messageKey);
this.completionCode = completionCode;
}

View file

@ -0,0 +1,175 @@
package ee.carlrobert.codegpt.settings.service.custom;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.icons.AllIcons.General;
import com.intellij.ide.HelpTooltip;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.MessageType;
import com.intellij.ui.EnumComboBoxModel;
import com.intellij.ui.TitledSeparator;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPasswordField;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.completions.CallParameters;
import ee.carlrobert.codegpt.completions.CompletionRequestProvider;
import ee.carlrobert.codegpt.completions.CompletionRequestService;
import ee.carlrobert.codegpt.conversations.Conversation;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.credentials.CustomServiceCredentialManager;
import ee.carlrobert.codegpt.ui.OverlayUtil;
import ee.carlrobert.codegpt.ui.UIUtil;
import ee.carlrobert.llm.client.openai.completion.ErrorDetails;
import ee.carlrobert.llm.completion.CompletionEventListener;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.net.MalformedURLException;
import java.net.URL;
import javax.annotation.Nullable;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import okhttp3.sse.EventSource;
public class CustomServiceForm {
private final JBPasswordField apiKeyField;
private final JBTextField urlField;
private final CustomServiceFormTabbedPane tabbedPane;
private final JButton testConnectionButton;
private final JBLabel templateHelpText;
private final ComboBox<CustomServiceTemplate> templateComboBox;
public CustomServiceForm(CustomServiceState settings) {
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(CustomServiceCredentialManager.getInstance().getCredential());
urlField = new JBTextField(settings.getUrl(), 30);
tabbedPane = new CustomServiceFormTabbedPane(settings);
testConnectionButton = new JButton(CodeGPTBundle.get(
"settingsConfigurable.service.custom.openai.testConnection.label"));
testConnectionButton.addActionListener(e -> testConnection(getCurrentState()));
templateHelpText = new JBLabel(General.ContextHelp);
templateComboBox = new ComboBox<>(
new EnumComboBoxModel<>(CustomServiceTemplate.class));
templateComboBox.setSelectedItem(settings.getTemplate());
templateComboBox.addItemListener(e -> {
var template = (CustomServiceTemplate) e.getItem();
updateTemplateHelpTextTooltip(template);
urlField.setText(template.getUrl());
tabbedPane.setHeaders(template.getHeaders());
tabbedPane.setBody(template.getBody());
});
updateTemplateHelpTextTooltip(settings.getTemplate());
}
public JPanel getForm() {
var urlPanel = new JPanel(new BorderLayout(8, 0));
urlPanel.add(urlField, BorderLayout.CENTER);
urlPanel.add(testConnectionButton, BorderLayout.EAST);
var templateComboBoxWrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
templateComboBoxWrapper.add(templateComboBox);
templateComboBoxWrapper.add(Box.createHorizontalStrut(8));
templateComboBoxWrapper.add(templateHelpText);
var form = FormBuilder.createFormBuilder()
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.custom.openai.presetTemplate.label"),
templateComboBoxWrapper)
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"),
apiKeyField)
.addComponentToRightColumn(
UIUtil.createComment("settingsConfigurable.service.custom.openai.apiKey.comment"))
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.custom.openai.url.label"),
urlPanel)
.addComponent(tabbedPane)
.getPanel();
return FormBuilder.createFormBuilder()
.addComponent(new TitledSeparator(
CodeGPTBundle.get("settingsConfigurable.service.openai.configuration.title")))
.addComponent(withEmptyLeftBorder(form))
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}
public @Nullable String getApiKey() {
var apiKey = new String(apiKeyField.getPassword());
return apiKey.isEmpty() ? null : apiKey;
}
public CustomServiceState getCurrentState() {
var state = new CustomServiceState();
state.setUrl(urlField.getText());
state.setTemplate(templateComboBox.getItem());
state.setHeaders(tabbedPane.getHeaders());
state.setBody(tabbedPane.getBody());
return state;
}
public void resetForm() {
var state = CustomServiceSettings.getCurrentState();
apiKeyField.setText(CustomServiceCredentialManager.getInstance().getCredential());
urlField.setText(state.getUrl());
templateComboBox.setSelectedItem(state.getTemplate());
tabbedPane.setHeaders(state.getHeaders());
tabbedPane.setBody(state.getBody());
}
private void updateTemplateHelpTextTooltip(CustomServiceTemplate template) {
templateHelpText.setToolTipText(null);
try {
new HelpTooltip()
.setTitle(template.getName())
.setBrowserLink(
CodeGPTBundle.get("settingsConfigurable.service.custom.openai.linkToDocs"),
new URL(template.getDocsUrl()))
.installOn(templateHelpText);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
private void testConnection(CustomServiceState customConfiguration) {
var conversation = new Conversation();
var request = new CompletionRequestProvider(conversation)
.buildCustomOpenAIChatCompletionRequest(
customConfiguration,
new CallParameters(conversation, new Message("Hello!")));
CompletionRequestService.getInstance()
.getCustomOpenAIChatCompletionAsync(request, new TestConnectionEventListener());
}
class TestConnectionEventListener implements CompletionEventListener<String> {
@Override
public void onMessage(String value, EventSource eventSource) {
if (value != null && !value.isEmpty()) {
SwingUtilities.invokeLater(() -> {
OverlayUtil.showBalloon(
CodeGPTBundle.get("settingsConfigurable.service.custom.openai.connectionSuccess"),
MessageType.INFO,
testConnectionButton);
eventSource.cancel();
});
}
}
@Override
public void onError(ErrorDetails error, Throwable ex) {
SwingUtilities.invokeLater(() ->
OverlayUtil.showBalloon(
CodeGPTBundle.get("settingsConfigurable.service.custom.openai.connectionFailed")
+ "\n\n"
+ error.getMessage(),
MessageType.ERROR,
testConnectionButton));
}
}
}

View file

@ -0,0 +1,94 @@
package ee.carlrobert.codegpt.settings.service.custom;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBTabbedPane;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.JBUI;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JPanel;
import javax.swing.table.DefaultTableModel;
class CustomServiceFormTabbedPane extends JBTabbedPane {
private final JBTable headersTable;
private final JBTable bodyTable;
CustomServiceFormTabbedPane(CustomServiceState customConfiguration) {
headersTable = new JBTable(
new DefaultTableModel(toArray(customConfiguration.getHeaders()),
new Object[]{"Key", "Value"}));
bodyTable = new JBTable(
new DefaultTableModel(toArray(customConfiguration.getBody()),
new Object[]{"Key", "Value"}));
setTabComponentInsets(JBUI.insetsTop(8));
addTab("Headers", createTablePanel(headersTable));
addTab("Body", createTablePanel(bodyTable));
}
public void setEnabled(boolean enabled) {
headersTable.setEnabled(enabled);
bodyTable.setEnabled(enabled);
}
public void setHeaders(Map<String, String> headers) {
setTableData(headersTable, headers);
}
public Map<String, String> getHeaders() {
return getTableData(headersTable).entrySet().stream()
.filter(entry -> entry.getKey() != null && entry.getValue() != null)
.collect(toMap(Entry::getKey, entry -> (String) entry.getValue()));
}
public void setBody(Map<String, ?> body) {
setTableData(bodyTable, body);
}
public Map<String, ?> getBody() {
return getTableData(bodyTable);
}
private void setTableData(JBTable table, Map<String, ?> values) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.setRowCount(0);
for (var entry : values.entrySet()) {
model.addRow(new Object[]{entry.getKey(), entry.getValue()});
}
}
private Map<String, Object> getTableData(JBTable table) {
var model = (DefaultTableModel) table.getModel();
var data = new HashMap<String, Object>();
for (int i = 0; i < model.getRowCount(); i++) {
var key = (String) model.getValueAt(i, 0);
data.put(key, model.getValueAt(i, 1));
}
return data;
}
public static Object[][] toArray(Map<?, ?> actionsMap) {
return actionsMap.entrySet()
.stream()
.map((entry) -> new Object[]{entry.getKey(), entry.getValue()})
.collect(toList())
.toArray(new Object[0][0]);
}
private JPanel createTablePanel(JBTable table) {
return ToolbarDecorator.createDecorator(table)
.setAddAction(anActionButton ->
((DefaultTableModel) table.getModel()).addRow(new Object[]{"", null}))
.setRemoveAction(anActionButton ->
((DefaultTableModel) table.getModel()).removeRow(table.getSelectedRow()))
.disableUpAction()
.disableDownAction()
.createPanel();
}
}

View file

@ -0,0 +1,43 @@
package ee.carlrobert.codegpt.settings.service.custom;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import ee.carlrobert.codegpt.credentials.CustomServiceCredentialManager;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
@State(
name = "CodeGPT_CustomServiceSettings",
storages = @Storage("CodeGPT_CustomServiceSettings.xml"))
public class CustomServiceSettings implements PersistentStateComponent<CustomServiceState> {
private CustomServiceState state = new CustomServiceState();
@Override
@NotNull
public CustomServiceState getState() {
return state;
}
@Override
public void loadState(@NotNull CustomServiceState state) {
this.state = state;
}
public static CustomServiceState getCurrentState() {
return getInstance().getState();
}
public static CustomServiceSettings getInstance() {
return ApplicationManager.getApplication().getService(CustomServiceSettings.class);
}
public boolean isModified(CustomServiceForm form) {
return !form.getCurrentState().equals(state)
|| !StringUtils.equals(
form.getApiKey(),
CustomServiceCredentialManager.getInstance().getCredential());
}
}

View file

@ -0,0 +1,66 @@
package ee.carlrobert.codegpt.settings.service.custom;
import static ee.carlrobert.codegpt.settings.service.custom.CustomServiceTemplate.OPENAI;
import java.util.Map;
import java.util.Objects;
public class CustomServiceState {
private String url = OPENAI.getUrl();
private Map<String, String> headers = OPENAI.getHeaders();
private Map<String, ?> body = OPENAI.getBody();
private CustomServiceTemplate template = OPENAI;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Map<String, String> getHeaders() {
return headers;
}
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
public Map<String, ?> getBody() {
return body;
}
public void setBody(Map<String, ?> body) {
this.body = body;
}
public CustomServiceTemplate getTemplate() {
return template;
}
public void setTemplate(CustomServiceTemplate template) {
this.template = template;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CustomServiceState that = (CustomServiceState) o;
return Objects.equals(url, that.url)
&& Objects.equals(headers, that.headers)
&& Objects.equals(body, that.body)
&& template == that.template;
}
@Override
public int hashCode() {
return Objects.hash(url, headers, body, template);
}
}

View file

@ -0,0 +1,158 @@
package ee.carlrobert.codegpt.settings.service.custom;
import java.util.HashMap;
import java.util.Map;
public enum CustomServiceTemplate {
// Cloud providers
ANYSCALE(
"Anyscale",
"https://docs.endpoints.anyscale.com/",
"https://api.endpoints.anyscale.com/v1/chat/completions",
getDefaultHeadersWithAuthentication(),
getDefaultBodyParams(Map.of(
"model", "mistralai/Mixtral-8x7B-Instruct-v0.1",
"max_tokens", 1024))),
AZURE(
"Azure OpenAI",
"https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#chat-completions",
"https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}/chat/completions?api-version=2023-05-15",
getDefaultHeaders("api-key", "$CUSTOM_SERVICE_API_KEY"),
getDefaultBodyParams(Map.of())),
DEEP_INFRA(
"DeepInfra",
"https://deepinfra.com/docs/advanced/openai_api",
"https://api.deepinfra.com/v1/openai/chat/completions",
getDefaultHeadersWithAuthentication(),
getDefaultBodyParams(Map.of(
"model", "meta-llama/Llama-2-70b-chat-hf",
"max_tokens", 1024))),
FIREWORKS(
"Fireworks",
"https://readme.fireworks.ai/reference/createchatcompletion",
"https://api.fireworks.ai/inference/v1/chat/completions",
getDefaultHeadersWithAuthentication(),
getDefaultBodyParams(Map.of(
"model", "accounts/fireworks/models/llama-v2-7b-chat",
"max_tokens", 1024))),
GROQ(
"Groq",
"https://docs.api.groq.com/md/openai.oas.html",
"https://api.groq.com/openai/v1/chat/completions",
getDefaultHeadersWithAuthentication(),
getDefaultBodyParams(Map.of(
"model", "codellama-34b",
"max_tokens", 1024))),
OPENAI(
"OpenAI",
"https://platform.openai.com/docs/api-reference/chat",
"https://api.openai.com/v1/chat/completions",
getDefaultHeaders("Authorization", "Bearer $CUSTOM_SERVICE_API_KEY"),
getDefaultBodyParams(Map.of(
"model", "gpt-4",
"max_tokens", 1024))),
PERPLEXITY(
"Perplexity AI",
"https://docs.perplexity.ai/reference/post_chat_completions",
"https://api.perplexity.ai/chat/completions",
getDefaultHeadersWithAuthentication(),
getDefaultBodyParams(Map.of(
"model", "codellama",
"max_tokens", 1024))),
TOGETHER(
"Together AI",
"https://docs.together.ai/docs/openai-api-compatibility",
"https://api.together.xyz/v1/chat/completions",
getDefaultHeaders("Authorization", "Bearer $CUSTOM_SERVICE_API_KEY"),
getDefaultBodyParams(Map.of(
"model", "deepseek-ai/deepseek-coder-33b-instruct",
"max_tokens", 1024))),
// Local providers
OLLAMA(
"Ollama",
"https://github.com/ollama/ollama/blob/main/docs/openai.md",
"http://localhost:11434/v1/chat/completions",
getDefaultHeaders(),
getDefaultBodyParams(Map.of("model", "codellama"))),
LLAMA_CPP(
"LLaMA C/C++",
"https://github.com/ggerganov/llama.cpp/blob/master/examples/server/README.md",
"http://localhost:8080/v1/chat/completions",
getDefaultHeaders(),
getDefaultBodyParams(Map.of()));
private final String name;
private final String docsUrl;
private final String url;
private final Map<String, String> headers;
private final Map<String, ?> body;
CustomServiceTemplate(
String name,
String docsUrl,
String url,
Map<String, String> headers,
Map<String, ?> body) {
this.name = name;
this.docsUrl = docsUrl;
this.url = url;
this.headers = headers;
this.body = body;
}
public String getName() {
return name;
}
public String getDocsUrl() {
return docsUrl;
}
public String getUrl() {
return url;
}
public Map<String, String> getHeaders() {
return headers;
}
public Map<String, ?> getBody() {
return body;
}
@Override
public String toString() {
return name;
}
private static Map<String, String> getDefaultHeadersWithAuthentication() {
return getDefaultHeaders("Authorization", "Bearer $CUSTOM_SERVICE_API_KEY");
}
private static Map<String, String> getDefaultHeaders() {
return getDefaultHeaders(Map.of());
}
private static Map<String, String> getDefaultHeaders(String key, String value) {
return getDefaultHeaders(Map.of(key, value));
}
private static Map<String, String> getDefaultHeaders(Map<String, String> additionalHeaders) {
var defaultHeaders = new HashMap<>(Map.of(
"Content-Type", "application/json",
"X-LLM-Application-Tag", "codegpt"));
defaultHeaders.putAll(additionalHeaders);
return defaultHeaders;
}
private static Map<String, ?> getDefaultBodyParams(Map<String, ?> additionalParams) {
var defaultParams = new HashMap<String, Object>(Map.of(
"stream", true,
"messages", "$OPENAI_MESSAGES",
"temperature", 0.1));
defaultParams.putAll(additionalParams);
return defaultParams;
}
}

View file

@ -3,7 +3,6 @@ package ee.carlrobert.codegpt.settings.service.openai;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.EnumComboBoxModel;
import com.intellij.ui.TitledSeparator;
import com.intellij.ui.components.JBPasswordField;
@ -16,15 +15,10 @@ import ee.carlrobert.codegpt.ui.UIUtil;
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
import javax.annotation.Nullable;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import org.jetbrains.annotations.NotNull;
public class OpenAISettingsForm {
private final JBPasswordField apiKeyField;
private final JBTextField customModelField;
private final JBTextField baseHostField;
private final JBTextField pathField;
private final JBTextField organizationField;
private final ComboBox<OpenAIChatCompletionModel> completionModelComboBox;
@ -32,64 +26,34 @@ public class OpenAISettingsForm {
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(OpenAICredentialManager.getInstance().getCredential());
organizationField = new JBTextField(settings.getOrganization(), 30);
completionModelComboBox = new ComboBox<>(
new EnumComboBoxModel<>(OpenAIChatCompletionModel.class));
completionModelComboBox.setEnabled(settings.getCustomModel().isEmpty());
completionModelComboBox.setSelectedItem(
OpenAIChatCompletionModel.findByCode(settings.getModel()));
customModelField = new JBTextField(settings.getCustomModel(), 20);
customModelField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(@NotNull DocumentEvent e) {
completionModelComboBox.setEnabled(customModelField.getText().isEmpty());
}
});
baseHostField = new JBTextField(settings.getBaseHost(), 30);
pathField = new JBTextField(settings.getPath(), 30);
organizationField = new JBTextField(settings.getOrganization(), 30);
}
public JPanel getForm() {
var requestConfigurationPanel = UI.PanelFactory.grid()
.add(UI.PanelFactory.panel(completionModelComboBox)
.withLabel(CodeGPTBundle.get(
"settingsConfigurable.shared.model.label"))
.resizeX(false))
.add(UI.PanelFactory.panel(customModelField)
.withLabel(CodeGPTBundle.get(
"settingsConfigurable.service.openai.customModel.label"))
.resizeX(false))
var configurationGrid = UI.PanelFactory.grid()
.add(UI.PanelFactory.panel(apiKeyField)
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
.resizeX(false)
.withComment(CodeGPTBundle.get("settingsConfigurable.service.openai.apiKey.comment"))
.withCommentHyperlinkListener(UIUtil::handleHyperlinkClicked))
.add(UI.PanelFactory.panel(organizationField)
.withLabel(CodeGPTBundle.get(
"settingsConfigurable.service.openai.organization.label"))
.withLabel(CodeGPTBundle.get("settingsConfigurable.service.openai.organization.label"))
.resizeX(false)
.withComment(CodeGPTBundle.get(
"settingsConfigurable.section.openai.organization.comment")))
.add(UI.PanelFactory.panel(baseHostField)
.withLabel(CodeGPTBundle.get(
"settingsConfigurable.shared.baseHost.label"))
.add(UI.PanelFactory.panel(completionModelComboBox)
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.model.label"))
.resizeX(false))
.add(UI.PanelFactory.panel(pathField)
.withLabel(CodeGPTBundle.get(
"settingsConfigurable.shared.path.label"))
.resizeX(false))
.createPanel();
var apiKeyFieldPanel = UI.PanelFactory.panel(apiKeyField)
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
.resizeX(false)
.withComment(
CodeGPTBundle.get("settingsConfigurable.service.openai.apiKey.comment"))
.withCommentHyperlinkListener(UIUtil::handleHyperlinkClicked)
.createPanel();
return FormBuilder.createFormBuilder()
.addComponent(new TitledSeparator(
CodeGPTBundle.get("settingsConfigurable.shared.authentication.title")))
.addComponent(withEmptyLeftBorder(apiKeyFieldPanel))
.addComponent(new TitledSeparator(
CodeGPTBundle.get("settingsConfigurable.shared.requestConfiguration.title")))
.addComponent(withEmptyLeftBorder(requestConfigurationPanel))
CodeGPTBundle.get("settingsConfigurable.service.openai.configuration.title")))
.addComponent(withEmptyLeftBorder(configurationGrid))
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}
@ -108,10 +72,7 @@ public class OpenAISettingsForm {
public OpenAISettingsState getCurrentState() {
var state = new OpenAISettingsState();
state.setModel(getModel());
state.setCustomModel(customModelField.getText());
state.setOrganization(organizationField.getText());
state.setBaseHost(baseHostField.getText());
state.setPath(pathField.getText());
return state;
}
@ -120,9 +81,6 @@ public class OpenAISettingsForm {
apiKeyField.setText(OpenAICredentialManager.getInstance().getCredential());
completionModelComboBox.setSelectedItem(
OpenAIChatCompletionModel.findByCode(state.getModel()));
customModelField.setText(state.getCustomModel());
organizationField.setText(state.getOrganization());
baseHostField.setText(state.getBaseHost());
pathField.setText(state.getPath());
}
}

View file

@ -5,17 +5,8 @@ import java.util.Objects;
public class OpenAISettingsState {
private static final String BASE_PATH = "/v1/chat/completions";
private String organization = "";
private String baseHost = "https://api.openai.com";
private String path = BASE_PATH;
private String model = OpenAIChatCompletionModel.GPT_3_5.getCode();
private String customModel = "";
public boolean isUsingCustomPath() {
return !BASE_PATH.equals(path);
}
private String model = OpenAIChatCompletionModel.GPT_3_5_0125_16k.getCode();
public String getOrganization() {
return organization;
@ -25,22 +16,6 @@ public class OpenAISettingsState {
this.organization = organization;
}
public String getBaseHost() {
return baseHost;
}
public void setBaseHost(String openAIBaseHost) {
this.baseHost = openAIBaseHost;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getModel() {
return model;
}
@ -49,14 +24,6 @@ public class OpenAISettingsState {
this.model = model;
}
public String getCustomModel() {
return customModel;
}
public void setCustomModel(String customModel) {
this.customModel = customModel;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -66,15 +33,11 @@ public class OpenAISettingsState {
return false;
}
OpenAISettingsState that = (OpenAISettingsState) o;
return Objects.equals(organization, that.organization)
&& Objects.equals(baseHost, that.baseHost)
&& Objects.equals(path, that.path)
&& Objects.equals(model, that.model)
&& Objects.equals(customModel, that.customModel);
return Objects.equals(organization, that.organization) && Objects.equals(model, that.model);
}
@Override
public int hashCode() {
return Objects.hash(organization, baseHost, path, model, customModel);
return Objects.hash(organization, model);
}
}

View file

@ -4,8 +4,6 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import ee.carlrobert.codegpt.credentials.YouCredentialManager;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
@State(name = "CodeGPT_YouSettings", storages = @Storage("CodeGPT_YouSettings.xml"))
@ -33,8 +31,6 @@ public class YouSettings implements PersistentStateComponent<YouSettingsState> {
}
public boolean isModified(YouSettingsForm form) {
var password = YouCredentialManager.getInstance().getCredential();
return !form.getCurrentState().equals(state)
|| (!form.getEmail().isEmpty() && !StringUtils.equals(form.getPassword(), password));
return !form.getCurrentState().equals(state);
}
}

View file

@ -1,5 +1,7 @@
package ee.carlrobert.codegpt.toolwindow.chat.standard;
package ee.carlrobert.codegpt.toolwindow.chat.ui.textarea;
import static ee.carlrobert.codegpt.settings.service.ServiceType.CUSTOM_OPENAI;
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
import static java.lang.String.format;
import com.intellij.openapi.actionSystem.AnAction;
@ -15,6 +17,7 @@ import ee.carlrobert.codegpt.conversations.ConversationsState;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.GeneralSettingsState;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettingsState;
@ -56,22 +59,19 @@ public class ModelComboBoxAction extends ComboBoxAction {
var presentation = ((ComboBoxButton) button).getPresentation();
var actionGroup = new DefaultActionGroup();
actionGroup.addSeparator("OpenAI");
var settings = OpenAISettings.getCurrentState();
if (settings.getCustomModel().isEmpty()) {
List.of(
OpenAIChatCompletionModel.GPT_4_0125_128k,
OpenAIChatCompletionModel.GPT_3_5_0125_16k,
OpenAIChatCompletionModel.GPT_4_32k,
OpenAIChatCompletionModel.GPT_4,
OpenAIChatCompletionModel.GPT_3_5)
.forEach(model -> actionGroup.add(createOpenAIModelAction(model, presentation)));
} else {
actionGroup.add(createModelAction(
ServiceType.OPENAI,
settings.getCustomModel(),
Icons.OpenAI,
presentation));
}
List.of(
OpenAIChatCompletionModel.GPT_4_0125_128k,
OpenAIChatCompletionModel.GPT_3_5_0125_16k,
OpenAIChatCompletionModel.GPT_4_32k,
OpenAIChatCompletionModel.GPT_4,
OpenAIChatCompletionModel.GPT_3_5)
.forEach(model -> actionGroup.add(createOpenAIModelAction(model, presentation)));
actionGroup.addSeparator("Custom OpenAI Service");
actionGroup.add(createModelAction(
CUSTOM_OPENAI,
CustomServiceSettings.getCurrentState().getTemplate().getName(),
Icons.OpenAI,
presentation));
actionGroup.addSeparator();
actionGroup.add(
createModelAction(ServiceType.AZURE, "Azure OpenAI", Icons.Azure, presentation));
@ -96,7 +96,14 @@ public class ModelComboBoxAction extends ComboBoxAction {
switch (selectedService) {
case OPENAI:
templatePresentation.setIcon(Icons.OpenAI);
templatePresentation.setText(getOpenAiPresentationText());
templatePresentation.setText(
OpenAIChatCompletionModel.findByCode(openAISettings.getModel()).getDescription());
break;
case CUSTOM_OPENAI:
templatePresentation.setIcon(Icons.OpenAI);
templatePresentation.setText(CustomServiceSettings.getCurrentState()
.getTemplate()
.getName());
break;
case AZURE:
templatePresentation.setIcon(Icons.Azure);
@ -114,14 +121,6 @@ public class ModelComboBoxAction extends ComboBoxAction {
}
}
private String getOpenAiPresentationText() {
var settings = OpenAISettings.getCurrentState();
if (settings.getCustomModel().isEmpty()) {
return OpenAIChatCompletionModel.findByCode(openAISettings.getModel()).getDescription();
}
return settings.getCustomModel();
}
private String getLlamaCppPresentationText() {
var llamaSettingState = LlamaSettings.getCurrentState();
if (!llamaSettingState.isRunLocalServer()) {
@ -178,7 +177,7 @@ public class ModelComboBoxAction extends ComboBoxAction {
private AnAction createOpenAIModelAction(
OpenAIChatCompletionModel model,
Presentation comboBoxPresentation) {
createModelAction(ServiceType.OPENAI, model.getDescription(), Icons.OpenAI,
createModelAction(OPENAI, model.getDescription(), Icons.OpenAI,
comboBoxPresentation);
return new DumbAwareAction(model.getDescription(), "", Icons.OpenAI) {
@Override
@ -191,7 +190,7 @@ public class ModelComboBoxAction extends ComboBoxAction {
public void actionPerformed(@NotNull AnActionEvent e) {
openAISettings.setModel(model.getCode());
handleProviderChange(
ServiceType.OPENAI,
OPENAI,
model.getDescription(),
Icons.OpenAI,
comboBoxPresentation);

View file

@ -8,7 +8,6 @@ import com.intellij.util.ui.JBUI;
import ee.carlrobert.codegpt.completions.you.YouSubscriptionNotifier;
import ee.carlrobert.codegpt.completions.you.auth.SignedOutNotifier;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.toolwindow.chat.standard.ModelComboBoxAction;
import java.awt.BorderLayout;
import javax.swing.JPanel;