1.1.2 - Add option to select other language models(closes #7)

This commit is contained in:
Carl-Robert Linnupuu 2023-02-27 23:53:51 +00:00
parent 36c8255aa6
commit f8fdb2cbab
8 changed files with 144 additions and 43 deletions

View file

@ -0,0 +1,25 @@
package ee.carlrobert.chatgpt.client;
public enum BaseModel {
ADA("text-ada-001", "Ada - Fastest"),
BABBAGE("text-babbage-001", "Babbage - Powerful"),
CURIE("text-curie-001", "Curie - Fast and efficient"),
DAVINCI("text-davinci-003", "Davinci - Most powerful (Default)");
private final String model;
private final String description;
BaseModel(String model, String description) {
this.model = model;
this.description = description;
}
public String getModel() {
return model;
}
public String getDescription() {
return description;
}
}

View file

@ -1,7 +1,10 @@
package ee.carlrobert.chatgpt.client.gpt;
import static java.lang.String.format;
import ee.carlrobert.chatgpt.EmptyCallback;
import ee.carlrobert.chatgpt.client.ApiRequestDetails;
import ee.carlrobert.chatgpt.client.BaseModel;
import ee.carlrobert.chatgpt.client.Client;
import ee.carlrobert.chatgpt.ide.settings.SettingsState;
import java.net.http.HttpResponse;
@ -32,13 +35,16 @@ public class GPTClient extends Client {
protected ApiRequestDetails getRequestDetails(String prompt) {
return new ApiRequestDetails(
"https://api.openai.com/v1/completions",
format("https://api.openai.com/v1/engines/%s/completions", SettingsState.getInstance().baseModel.getModel()),
Map.of(
"model", "text-davinci-003",
"stop", List.of("<|im_end|>"),
"stop", List.of(" Human:", " AI:"),
"prompt", buildPrompt(prompt),
"max_tokens", 1000,
"temperature", 1.0,
"temperature", 0.9,
"best_of", 1,
"frequency_penalty", 0,
"presence_penalty", 0.6,
"top_p", 1,
"stream", true
),
SettingsState.getInstance().apiKey);
@ -68,26 +74,32 @@ public class GPTClient extends Client {
}
}
private StringBuilder getBasePrompt() {
var isDavinciModel = SettingsState.getInstance().baseModel == BaseModel.DAVINCI;
if (isDavinciModel) {
return new StringBuilder("""
You are ChatGPT, a large language model trained by OpenAI.
Answer in a markdown language, code blocks should contain language whenever possible.
""");
}
return new StringBuilder(
"The following is a conversation with an AI assistant. The assistant is helpful, creative, clever, and very friendly.\n\n");
}
private String buildPrompt(String prompt) {
var basePrompt = new StringBuilder("""
You are ChatGPT, a large language model trained by OpenAI.
One of your main goals is code generation but not only.
Answer in a markdown language. Markdown code blocks should contain language whenever possible.
""");
var basePrompt = getBasePrompt();
queries.forEach(query ->
basePrompt.append("User:\n")
basePrompt.append("Human: ")
.append(query.getKey())
.append("<|im_end|>\n")
.append("\n")
.append("ChatGPT:\n")
.append("AI: ")
.append(query.getValue())
.append("<|im_end|>\n")
.append("\n"));
basePrompt.append("User:\n")
basePrompt.append("Human: ")
.append(prompt)
.append("<|im_end|>\n")
.append("\n")
.append("ChatGPT:\n");
.append("AI: ")
.append("\n");
return basePrompt.toString();
}
}

View file

@ -0,0 +1,41 @@
package ee.carlrobert.chatgpt.ide.settings;
import ee.carlrobert.chatgpt.client.BaseModel;
import java.awt.Component;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class BaseModelComboBox extends JComboBox<BaseModel> {
public BaseModelComboBox(BaseModel selectedModel) {
super(new BaseModel[] {
BaseModel.DAVINCI,
BaseModel.CURIE,
BaseModel.BABBAGE,
BaseModel.ADA,
});
setSelectedItem(selectedModel);
setRenderer(getBasicComboBoxRenderer());
}
private BasicComboBoxRenderer getBasicComboBoxRenderer() {
return new BasicComboBoxRenderer() {
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index,
isSelected, cellHasFocus);
if (value != null) {
BaseModel model = (BaseModel) value;
setText(model.getDescription());
}
return this;
}
};
}
}

View file

@ -6,6 +6,7 @@ import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UI;
import ee.carlrobert.chatgpt.client.BaseModel;
import java.awt.Desktop;
import java.io.IOException;
import java.net.URISyntaxException;
@ -21,6 +22,7 @@ public class SettingsComponent {
private final JPanel mainPanel;
private final JBTextField apiKeyField;
private final JComboBox<BaseModel> baseModelComboBox;
private final JComboBox<String> reverseProxyComboBox;
private final JBTextField accessTokenField;
private final JBRadioButton useGPTRadioButton;
@ -28,6 +30,7 @@ public class SettingsComponent {
public SettingsComponent(SettingsState settings) {
apiKeyField = new JBTextField(settings.apiKey);
baseModelComboBox = new BaseModelComboBox(settings.baseModel);
reverseProxyComboBox = new JComboBox<>(new String[] {
"https://chat.duti.tech/api/conversation",
"https://gpt.pawan.krd/backend-api/conversation"
@ -41,16 +44,8 @@ public class SettingsComponent {
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
if (settings.isGPTOptionSelected) {
reverseProxyComboBox.setEnabled(false);
accessTokenField.setEnabled(false);
} else {
apiKeyField.setEnabled(false);
reverseProxyComboBox.setEnabled(true);
accessTokenField.setEnabled(true);
}
registerButtons();
registerFields(settings.isChatGPTOptionSelected);
}
public JPanel getPanel() {
@ -103,6 +98,14 @@ public class SettingsComponent {
reverseProxyComboBox.setSelectedItem(reverseProxyUrl);
}
public BaseModel getBaseModel() {
return (BaseModel) baseModelComboBox.getSelectedItem();
}
public void setBaseModel(BaseModel baseModel) {
baseModelComboBox.setSelectedItem(baseModel);
}
private JPanel createMainSelectionForm() {
var panel = FormBuilder.createFormBuilder()
.addVerticalGap(8)
@ -121,22 +124,30 @@ public class SettingsComponent {
}
private JPanel createFirstSelectionForm() {
var baseModelPanel = UI.PanelFactory.panel(baseModelComboBox)
.withLabel("Model:")
.createPanel();
var apiKeyFieldPanel = UI.PanelFactory.panel(apiKeyField)
.withLabel("API key:")
.withComment("You can find your Secret API key in your <a href=\"https://platform.openai.com/account/api-keys\">User settings</a>.")
.withCommentHyperlinkListener(this::handleHyperlinkClicked)
.createPanel();
setEqualLabelWidths(baseModelPanel, apiKeyFieldPanel);
var panel = FormBuilder.createFormBuilder()
.addComponent(UI.PanelFactory.panel(apiKeyField)
.withLabel("API key:")
.withComment("You can find your Secret API key in your <a href=\"https://platform.openai.com/account/api-keys\">User settings</a>.")
.withCommentHyperlinkListener(this::handleHyperlinkClicked)
.createPanel())
.addComponent(baseModelPanel)
.addVerticalGap(8)
.addComponent(apiKeyFieldPanel)
.getPanel();
panel.setBorder(JBUI.Borders.emptyLeft(24));
return panel;
}
private JPanel createSecondSelectionForm() {
var reverseProxyUrlPanel = FormBuilder.createFormBuilder()
.addLabeledComponent("Reverse proxy url:", reverseProxyComboBox)
.getPanel();
var reverseProxyUrlPanel = UI.PanelFactory.panel(reverseProxyComboBox)
.withLabel("Reverse proxy url:")
.createPanel();
var accessTokenPanel = UI.PanelFactory.panel(accessTokenField)
.withLabel("Access token:")
.withComment(
@ -144,11 +155,7 @@ public class SettingsComponent {
.withCommentHyperlinkListener(this::handleHyperlinkClicked)
.createPanel();
var accessTokenLabel = accessTokenPanel.getComponents()[0];
var reverseProxyUrlLabel = reverseProxyUrlPanel.getComponents()[0];
if (accessTokenLabel instanceof JLabel && reverseProxyUrlLabel instanceof JLabel) {
accessTokenLabel.setPreferredSize(reverseProxyUrlLabel.getPreferredSize());
}
setEqualLabelWidths(accessTokenPanel, reverseProxyUrlPanel);
var panel = FormBuilder.createFormBuilder()
.addComponent(reverseProxyUrlPanel)
@ -159,16 +166,26 @@ public class SettingsComponent {
return panel;
}
// TODO: Find better way of doing this
private void setEqualLabelWidths(JPanel firstPanel, JPanel secondPanel) {
var firstLabel = firstPanel.getComponents()[0];
var secondLabel = secondPanel.getComponents()[0];
if (firstLabel instanceof JLabel && secondLabel instanceof JLabel) {
firstLabel.setPreferredSize(secondLabel.getPreferredSize());
}
}
private void registerButtons() {
ButtonGroup myButtonGroup = new ButtonGroup();
myButtonGroup.add(useGPTRadioButton);
myButtonGroup.add(useChatGPTRadioButton);
useGPTRadioButton.addActionListener(e -> handleRadioOptionChange(false));
useChatGPTRadioButton.addActionListener(e -> handleRadioOptionChange(true));
useGPTRadioButton.addActionListener(e -> registerFields(false));
useChatGPTRadioButton.addActionListener(e -> registerFields(true));
}
private void handleRadioOptionChange(boolean isUseChatGPTOption) {
private void registerFields(boolean isUseChatGPTOption) {
apiKeyField.setEnabled(!isUseChatGPTOption);
baseModelComboBox.setEnabled(!isUseChatGPTOption);
accessTokenField.setEnabled(isUseChatGPTOption);
reverseProxyComboBox.setEnabled(isUseChatGPTOption);
}

View file

@ -34,6 +34,7 @@ public class SettingsConfigurable implements Configurable {
return !settingsComponent.getApiKey().equals(settings.apiKey) ||
!settingsComponent.getAccessToken().equals(settings.accessToken) ||
!settingsComponent.getReverseProxyUrl().equals(settings.reverseProxyUrl) ||
!settingsComponent.getBaseModel().equals(settings.baseModel) ||
settingsComponent.isGPTOptionSelected() != settings.isGPTOptionSelected ||
settingsComponent.isChatGPTOptionSelected() != settings.isChatGPTOptionSelected;
}
@ -46,6 +47,7 @@ public class SettingsConfigurable implements Configurable {
settings.accessToken = settingsComponent.getAccessToken();
settings.apiKey = settingsComponent.getApiKey();
settings.reverseProxyUrl = settingsComponent.getReverseProxyUrl();
settings.baseModel = settingsComponent.getBaseModel();
}
@Override
@ -56,6 +58,7 @@ public class SettingsConfigurable implements Configurable {
settingsComponent.setAccessToken(settings.accessToken);
settingsComponent.setApiKey(settings.apiKey);
settingsComponent.setReverseProxyUrl(settings.reverseProxyUrl);
settingsComponent.setBaseModel(settings.baseModel);
}
@Override

View file

@ -5,6 +5,7 @@ import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.util.xmlb.XmlSerializerUtil;
import ee.carlrobert.chatgpt.client.BaseModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -17,6 +18,7 @@ public class SettingsState implements PersistentStateComponent<SettingsState> {
public String apiKey = "";
public String accessToken = "";
public String reverseProxyUrl = "";
public BaseModel baseModel = BaseModel.DAVINCI;
public boolean isGPTOptionSelected = true;
public boolean isChatGPTOptionSelected = false;