Allow using existing Llama Server instead of running locally (#345)

* Add setting to use existing Llama server

* minor UI improvements

* support infill template configuration

---------

Co-authored-by: Carl-Robert Linnupuu <carlrobertoh@gmail.com>
This commit is contained in:
Phil 2024-02-02 11:24:41 +01:00 committed by GitHub
parent 7387cf4536
commit cceba88c35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 910 additions and 498 deletions

View file

@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.codecompletions;
import ee.carlrobert.codegpt.completions.llama.LlamaModel;
import ee.carlrobert.codegpt.settings.state.LlamaSettingsState;
import ee.carlrobert.llm.client.llama.completion.LlamaCompletionRequest;
import ee.carlrobert.llm.client.openai.completion.request.OpenAITextCompletionRequest;
@ -26,8 +27,8 @@ public class CodeCompletionRequestProvider {
}
public LlamaCompletionRequest buildLlamaRequest() {
var promptTemplate = LlamaSettingsState.getInstance().getInfillPromptTemplate();
var prompt = promptTemplate.buildPrompt(details.getPrefix(), details.getSuffix());
InfillPromptTemplate promptTemplate = getLlamaInfillPromptTemplate();
String prompt = promptTemplate.buildPrompt(details.getPrefix(), details.getSuffix());
return new LlamaCompletionRequest.Builder(prompt)
.setN_predict(MAX_TOKENS)
.setStream(true)
@ -35,4 +36,16 @@ public class CodeCompletionRequestProvider {
.setStop(promptTemplate.getStopTokens())
.build();
}
private InfillPromptTemplate getLlamaInfillPromptTemplate() {
var settings = LlamaSettingsState.getInstance();
if (!settings.isRunLocalServer()) {
return settings.getRemoteModelInfillPromptTemplate();
}
if (settings.isUseCustomModel()) {
return settings.getLocalModelInfillPromptTemplate();
}
return LlamaModel.findByHuggingFaceModel(settings.getHuggingFaceModel())
.getInfillPromptTemplate();
}
}

View file

@ -5,6 +5,7 @@ import static java.lang.String.format;
import ee.carlrobert.codegpt.CodeGPTPlugin;
import ee.carlrobert.codegpt.completions.you.YouUserManager;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.LlamaCredentialsManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialsManager;
import ee.carlrobert.codegpt.settings.advanced.AdvancedSettingsState;
import ee.carlrobert.codegpt.settings.state.AzureSettingsState;
@ -13,6 +14,7 @@ import ee.carlrobert.codegpt.settings.state.OpenAISettingsState;
import ee.carlrobert.llm.client.azure.AzureClient;
import ee.carlrobert.llm.client.azure.AzureCompletionRequestParams;
import ee.carlrobert.llm.client.llama.LlamaClient;
import ee.carlrobert.llm.client.llama.LlamaClient.Builder;
import ee.carlrobert.llm.client.openai.OpenAIClient;
import ee.carlrobert.llm.client.you.UTMParameters;
import ee.carlrobert.llm.client.you.YouClient;
@ -72,9 +74,17 @@ public class CompletionClientProvider {
}
public static LlamaClient getLlamaClient() {
return new LlamaClient.Builder()
.setPort(LlamaSettingsState.getInstance().getServerPort())
.build(getDefaultClientBuilder());
LlamaSettingsState llamaSettingsState = LlamaSettingsState.getInstance();
Builder builder = new Builder()
.setPort(llamaSettingsState.getServerPort());
if (!llamaSettingsState.isRunLocalServer()) {
builder.setHost(llamaSettingsState.getBaseHost());
String apiKey = LlamaCredentialsManager.getInstance().getApiKey();
if (apiKey != null && !apiKey.isBlank()) {
builder.setApiKey(apiKey);
}
}
return builder.build(getDefaultClientBuilder());
}
private static OkHttpClient.Builder getDefaultClientBuilder() {

View file

@ -105,9 +105,14 @@ public class CompletionRequestProvider {
Message message,
ConversationType conversationType) {
var settings = LlamaSettingsState.getInstance();
var promptTemplate = settings.isUseCustomModel()
? settings.getPromptTemplate()
: LlamaModel.findByHuggingFaceModel(settings.getHuggingFaceModel()).getPromptTemplate();
PromptTemplate promptTemplate;
if (settings.isRunLocalServer()) {
promptTemplate = settings.isUseCustomModel()
? settings.getLocalModelPromptTemplate()
: LlamaModel.findByHuggingFaceModel(settings.getHuggingFaceModel()).getPromptTemplate();
} else {
promptTemplate = settings.getRemoteModelPromptTemplate();
}
var systemPrompt = COMPLETION_SYSTEM_PROMPT;
if (conversationType == ConversationType.FIX_COMPILE_ERRORS) {

View file

@ -4,6 +4,7 @@ import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate;
import ee.carlrobert.codegpt.completions.HuggingFaceModel;
import java.util.Collections;
import java.util.List;
@ -17,6 +18,7 @@ public enum LlamaModel {
+ "support for large input contexts, and zero-shot instruction following ability for "
+ "programming tasks.",
PromptTemplate.LLAMA,
InfillPromptTemplate.LLAMA,
List.of(
HuggingFaceModel.CODE_LLAMA_7B_Q3,
HuggingFaceModel.CODE_LLAMA_7B_Q4,
@ -45,6 +47,7 @@ public enum LlamaModel {
+ "in both English and Chinese. It achieves state-of-the-art performance among "
+ "open-source code models on multiple programming languages and various benchmarks.",
PromptTemplate.ALPACA,
InfillPromptTemplate.DEEPSEEK_CODER,
List.of(
HuggingFaceModel.DEEPSEEK_CODER_1_3B_Q3,
HuggingFaceModel.DEEPSEEK_CODER_1_3B_Q4,
@ -85,6 +88,7 @@ public enum LlamaModel {
private final String label;
private final String description;
private final PromptTemplate promptTemplate;
private final InfillPromptTemplate infillPromptTemplate;
private final List<HuggingFaceModel> huggingFaceModels;
LlamaModel(
@ -92,9 +96,19 @@ public enum LlamaModel {
String description,
PromptTemplate promptTemplate,
List<HuggingFaceModel> huggingFaceModels) {
this(label, description, promptTemplate, null, huggingFaceModels);
}
LlamaModel(
String label,
String description,
PromptTemplate promptTemplate,
InfillPromptTemplate infillPromptTemplate,
List<HuggingFaceModel> huggingFaceModels) {
this.label = label;
this.description = description;
this.promptTemplate = promptTemplate;
this.infillPromptTemplate = infillPromptTemplate;
this.huggingFaceModels = huggingFaceModels;
}
@ -125,6 +139,10 @@ public enum LlamaModel {
return promptTemplate;
}
public InfillPromptTemplate getInfillPromptTemplate() {
return infillPromptTemplate;
}
public List<HuggingFaceModel> getHuggingFaceModels() {
return huggingFaceModels;
}

View file

@ -39,19 +39,15 @@ public final class LlamaServerAgent implements Disposable {
Runnable onSuccess,
Runnable onServerTerminated) {
ApplicationManager.getApplication().invokeLater(() -> {
if (!params.isUseCustomServer()) {
try {
serverProgressPanel.updateText(
CodeGPTBundle.get("llamaServerAgent.buildingProject.description"));
makeProcessHandler = new OSProcessHandler(getMakeCommandLinde());
makeProcessHandler.addProcessListener(
getMakeProcessListener(params, serverProgressPanel, onSuccess, onServerTerminated));
makeProcessHandler.startNotify();
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
} else {
startServer(params, serverProgressPanel, onSuccess, onServerTerminated);
try {
serverProgressPanel.updateText(
CodeGPTBundle.get("llamaServerAgent.buildingProject.description"));
makeProcessHandler = new OSProcessHandler(getMakeCommandLinde());
makeProcessHandler.addProcessListener(
getMakeProcessListener(params, serverProgressPanel, onSuccess, onServerTerminated));
makeProcessHandler.startNotify();
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
});
}
@ -83,31 +79,23 @@ public final class LlamaServerAgent implements Disposable {
@Override
public void processTerminated(@NotNull ProcessEvent event) {
startServer(params, serverProgressPanel, onSuccess, onServerTerminated);
try {
LOG.info("Booting up llama server");
serverProgressPanel.updateText(
CodeGPTBundle.get("llamaServerAgent.serverBootup.description"));
startServerProcessHandler = new OSProcessHandler.Silent(getServerCommandLine(params));
startServerProcessHandler.addProcessListener(
getProcessListener(params.getPort(), onSuccess, onServerTerminated));
startServerProcessHandler.startNotify();
} catch (ExecutionException ex) {
LOG.error("Unable to start llama server", ex);
throw new RuntimeException(ex);
}
}
};
}
private void startServer(
LlamaServerStartupParams params,
ServerProgressPanel serverProgressPanel,
Runnable onSuccess,
Runnable onServerTerminated) {
try {
LOG.info("Booting up llama server");
serverProgressPanel.updateText(
CodeGPTBundle.get("llamaServerAgent.serverBootup.description"));
startServerProcessHandler = new OSProcessHandler.Silent(getServerCommandLine(params));
startServerProcessHandler.addProcessListener(
getProcessListener(params.getPort(), onSuccess, onServerTerminated));
startServerProcessHandler.startNotify();
} catch (ExecutionException ex) {
LOG.error("Unable to start llama server", ex);
throw new RuntimeException(ex);
}
}
private ProcessListener getProcessListener(
int port,
Runnable onSuccess,
@ -164,8 +152,8 @@ public final class LlamaServerAgent implements Disposable {
private GeneralCommandLine getServerCommandLine(LlamaServerStartupParams params) {
GeneralCommandLine commandLine = new GeneralCommandLine().withCharset(StandardCharsets.UTF_8);
commandLine.setExePath("./" + params.getServerFileName());
commandLine.withWorkDirectory(params.getServerDirectory());
commandLine.setExePath("./server");
commandLine.withWorkDirectory(CodeGPTPlugin.getLlamaSourcePath());
commandLine.addParameters(
"-m", params.getModelPath(),
"-c", String.valueOf(params.getContextLength()),

View file

@ -1,12 +1,9 @@
package ee.carlrobert.codegpt.completions.llama;
import java.io.File;
import java.util.List;
public class LlamaServerStartupParams {
private final String serverPath;
private final boolean useCustomServer;
private final String modelPath;
private final int contextLength;
private final int threads;
@ -14,14 +11,11 @@ public class LlamaServerStartupParams {
private final List<String> additionalParameters;
public LlamaServerStartupParams(
String serverPath,
boolean useCustomServer, String modelPath,
String modelPath,
int contextLength,
int threads,
int port,
List<String> additionalParameters) {
this.serverPath = serverPath;
this.useCustomServer = useCustomServer;
this.modelPath = modelPath;
this.contextLength = contextLength;
this.threads = threads;
@ -29,22 +23,6 @@ public class LlamaServerStartupParams {
this.additionalParameters = additionalParameters;
}
public String getServerPath() {
return serverPath;
}
public String getServerFileName() {
return serverPath.substring(serverPath.lastIndexOf(File.separator) + 1);
}
public String getServerDirectory() {
return serverPath.substring(0, serverPath.lastIndexOf(File.separator) + 1);
}
public boolean isUseCustomServer() {
return useCustomServer;
}
public String getModelPath() {
return modelPath;
}

View file

@ -0,0 +1,36 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.credentialStore.CredentialAttributes;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
import org.jetbrains.annotations.Nullable;
@Service
public final class LlamaCredentialsManager {
private static final CredentialAttributes llamaApiKeyCredentialAttributes =
CredentialsUtil.createCredentialAttributes("LLAMA_API_KEY");
private String llamaApiKey;
private LlamaCredentialsManager() {
llamaApiKey = CredentialsUtil.getPassword(llamaApiKeyCredentialAttributes);
}
public static LlamaCredentialsManager getInstance() {
return ApplicationManager.getApplication().getService(LlamaCredentialsManager.class);
}
public boolean isApiKeySet() {
return llamaApiKey != null && !llamaApiKey.isEmpty();
}
public @Nullable String getApiKey() {
return llamaApiKey;
}
public void setApiKey(String llamaApiKey) {
this.llamaApiKey = llamaApiKey;
CredentialsUtil.setPassword(llamaApiKeyCredentialAttributes, llamaApiKey);
}
}

View file

@ -6,6 +6,7 @@ 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.LlamaCredentialsManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialsManager;
import ee.carlrobert.codegpt.settings.state.AzureSettingsState;
import ee.carlrobert.codegpt.settings.state.LlamaSettingsState;
@ -75,6 +76,8 @@ public class SettingsConfigurable implements Configurable {
AzureCredentialsManager.getInstance().setApiKey(serviceSelectionForm.getAzureOpenAIApiKey());
AzureCredentialsManager.getInstance()
.setAzureActiveDirectoryToken(serviceSelectionForm.getAzureActiveDirectoryToken());
LlamaCredentialsManager.getInstance()
.setApiKey(serviceSelectionForm.getLlamaServerPreferencesForm().getApiKey());
var settings = SettingsState.getInstance();
settings.setDisplayName(settingsComponent.getDisplayName());

View file

@ -1,6 +1,5 @@
package ee.carlrobert.codegpt.settings.service;
import static ee.carlrobert.codegpt.ui.UIUtil.createRadioButtonsPanel;
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
@ -25,28 +24,26 @@ import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.JBUI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.CodeGPTPlugin;
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate;
import ee.carlrobert.codegpt.completions.HuggingFaceModel;
import ee.carlrobert.codegpt.completions.llama.LlamaModel;
import ee.carlrobert.codegpt.completions.llama.LlamaServerAgent;
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.settings.state.LlamaSettingsState;
import ee.carlrobert.codegpt.ui.ChatPromptTemplatePanel;
import ee.carlrobert.codegpt.ui.InfillPromptTemplatePanel;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.apache.commons.text.StringEscapeUtils;
import org.jetbrains.annotations.NotNull;
public class LlamaModelPreferencesForm {
@ -74,14 +71,14 @@ public class LlamaModelPreferencesForm {
private final JBLabel modelExistsIcon;
private final DefaultComboBoxModel<HuggingFaceModel> huggingFaceComboBoxModel;
private final JBLabel helpIcon;
private final JBLabel promptTemplateHelpIcon;
private final JPanel downloadModelActionLinkWrapper;
private final JBLabel progressLabel;
private final JBLabel modelDetailsLabel;
private final ComboBox<PromptTemplate> promptTemplateComboBox;
private final CardLayout cardLayout;
private final JBRadioButton predefinedModelRadioButton;
private final JBRadioButton customModelRadioButton;
private final ChatPromptTemplatePanel localPromptTemplatePanel;
private final InfillPromptTemplatePanel infillPromptTemplatePanel;
public LlamaModelPreferencesForm() {
cardLayout = new CardLayout();
@ -92,7 +89,6 @@ public class LlamaModelPreferencesForm {
var llamaSettings = LlamaSettingsState.getInstance();
modelExistsIcon.setVisible(isModelExists(llamaSettings.getHuggingFaceModel()));
helpIcon = new JBLabel(General.ContextHelp);
promptTemplateHelpIcon = new JBLabel(General.ContextHelp);
huggingFaceComboBoxModel = new DefaultComboBoxModel<>();
var llm = llamaSettings.getHuggingFaceModel();
var llamaModel = LlamaModel.findByHuggingFaceModel(llm);
@ -136,24 +132,22 @@ public class LlamaModelPreferencesForm {
browsableCustomModelTextField = createBrowsableCustomModelTextField(
!llamaServerAgent.isServerRunning());
browsableCustomModelTextField.setText(llamaSettings.getCustomLlamaModelPath());
promptTemplateComboBox = new ComboBox<>(new EnumComboBoxModel<>(PromptTemplate.class));
promptTemplateComboBox.setSelectedItem(llamaSettings.getPromptTemplate());
promptTemplateComboBox.setEnabled(!llamaServerAgent.isServerRunning());
promptTemplateComboBox.addItemListener(item -> {
var template = (PromptTemplate) item.getItem();
updatePromptTemplateHelpTooltip(template);
});
updatePromptTemplateHelpTooltip(llamaSettings.getPromptTemplate());
localPromptTemplatePanel = new ChatPromptTemplatePanel(
llamaSettings.getLocalModelPromptTemplate(),
!llamaServerAgent.isServerRunning());
predefinedModelRadioButton = new JBRadioButton("Use pre-defined model",
!llamaSettings.isUseCustomModel());
customModelRadioButton = new JBRadioButton("Use custom model",
llamaSettings.isUseCustomModel());
infillPromptTemplatePanel = new InfillPromptTemplatePanel(
llamaSettings.getLocalModelInfillPromptTemplate(),
!llamaServerAgent.isServerRunning()
);
}
public JPanel getForm() {
JPanel finalPanel = new JPanel(new BorderLayout());
finalPanel.add(createRadioButtonsPanel(predefinedModelRadioButton, customModelRadioButton),
BorderLayout.NORTH);
finalPanel.add(createRadioButtonsPanel(), BorderLayout.NORTH);
finalPanel.add(createFormPanelCards(), BorderLayout.CENTER);
return finalPanel;
}
@ -197,11 +191,19 @@ public class LlamaModelPreferencesForm {
}
public void setPromptTemplate(PromptTemplate promptTemplate) {
promptTemplateComboBox.setSelectedItem(promptTemplate);
localPromptTemplatePanel.setPromptTemplate(promptTemplate);
}
public PromptTemplate getPromptTemplate() {
return promptTemplateComboBox.getItem();
return localPromptTemplatePanel.getPromptTemplate();
}
public void setInfillPromptTemplate(InfillPromptTemplate promptTemplate) {
infillPromptTemplatePanel.setPromptTemplate(promptTemplate);
}
public InfillPromptTemplate getInfillPromptTemplate() {
return infillPromptTemplatePanel.getPromptTemplate();
}
public String getActualModelPath() {
@ -229,28 +231,36 @@ public class LlamaModelPreferencesForm {
return formPanelCards;
}
private JPanel createRadioButtonsPanel() {
var buttonGroup = new ButtonGroup();
buttonGroup.add(predefinedModelRadioButton);
buttonGroup.add(customModelRadioButton);
var radioPanel = new JPanel();
radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.PAGE_AXIS));
radioPanel.add(predefinedModelRadioButton);
radioPanel.add(Box.createVerticalStrut(4));
radioPanel.add(customModelRadioButton);
radioPanel.add(Box.createVerticalStrut(8));
return radioPanel;
}
private JPanel createCustomModelForm() {
var customModelHelpText = ComponentPanelBuilder.createCommentComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.customModelPath.comment"),
true);
customModelHelpText.setBorder(JBUI.Borders.empty(0, 4));
var promptTemplateHelpText = ComponentPanelBuilder.createCommentComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.promptTemplate.comment"),
true);
promptTemplateHelpText.setBorder(JBUI.Borders.empty(0, 4));
var promptTemplateWrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
promptTemplateWrapper.add(promptTemplateComboBox);
promptTemplateWrapper.add(Box.createHorizontalStrut(8));
promptTemplateWrapper.add(promptTemplateHelpIcon);
return FormBuilder.createFormBuilder()
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.customModelPath.label"),
browsableCustomModelTextField)
.addComponentToRightColumn(customModelHelpText)
.addLabeledComponent(CodeGPTBundle.get("shared.promptTemplate"), promptTemplateWrapper)
.addComponentToRightColumn(promptTemplateHelpText)
.addLabeledComponent(CodeGPTBundle.get("shared.promptTemplate"), localPromptTemplatePanel)
.addComponentToRightColumn(localPromptTemplatePanel.getPromptTemplateHelpText())
.addLabeledComponent(CodeGPTBundle.get("shared.infillPromptTemplate"),
infillPromptTemplatePanel)
.addComponentToRightColumn(infillPromptTemplatePanel.getPromptTemplateHelpText())
.addVerticalGap(4)
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
@ -492,23 +502,6 @@ public class LlamaModelPreferencesForm {
.installOn(helpIcon);
}
private void updatePromptTemplateHelpTooltip(PromptTemplate template) {
promptTemplateHelpIcon.setToolTipText(null);
var prompt = template.buildPrompt(
"SYSTEM_PROMPT",
"USER_PROMPT",
List.of(new Message("PREV_PROMPT", "PREV_RESPONSE")));
var htmlDescription = Arrays.stream(prompt.split("\n"))
.map(StringEscapeUtils::escapeHtml4)
.collect(Collectors.joining("<br>"));
new HelpTooltip()
.setTitle(template.toString())
.setDescription("<html><p>" + htmlDescription + "</p></html>")
.installOn(promptTemplateHelpIcon);
}
private static class ModelDetails {
double fileSize;
@ -537,4 +530,4 @@ public class LlamaModelPreferencesForm {
return size + "B";
}
}
}
}

View file

@ -0,0 +1,381 @@
package ee.carlrobert.codegpt.settings.service;
import static ee.carlrobert.codegpt.ui.UIUtil.createComment;
import static ee.carlrobert.codegpt.ui.UIUtil.createForm;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import static java.util.stream.Collectors.toList;
import com.intellij.icons.AllIcons.Actions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.ui.PortField;
import com.intellij.ui.TitledSeparator;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPasswordField;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.ui.components.JBTextField;
import com.intellij.ui.components.fields.IntegerField;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.CodeGPTPlugin;
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate;
import ee.carlrobert.codegpt.completions.HuggingFaceModel;
import ee.carlrobert.codegpt.completions.llama.LlamaServerAgent;
import ee.carlrobert.codegpt.completions.llama.LlamaServerStartupParams;
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.credentials.LlamaCredentialsManager;
import ee.carlrobert.codegpt.settings.state.LlamaSettingsState;
import ee.carlrobert.codegpt.ui.ChatPromptTemplatePanel;
import ee.carlrobert.codegpt.ui.InfillPromptTemplatePanel;
import ee.carlrobert.codegpt.ui.OverlayUtil;
import ee.carlrobert.codegpt.ui.UIUtil;
import ee.carlrobert.codegpt.ui.UIUtil.RadioButtonWithLayout;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class LlamaServerPreferencesForm {
private static final String RUN_LOCAL_SERVER_FORM_CARD_CODE = "RunLocalServerSettings";
private static final String USE_EXISTING_SERVER_FORM_CARD_CODE = "UseExistingServerSettings";
private final LlamaModelPreferencesForm llamaModelPreferencesForm;
private final JBRadioButton runLocalServerRadioButton;
private final JBRadioButton useExistingServerRadioButton;
private final JBTextField baseHostField;
private final JBPasswordField apiKeyField;
private final PortField portField;
private final IntegerField maxTokensField;
private final IntegerField threadsField;
private final JBTextField additionalParametersField;
private final ChatPromptTemplatePanel remotePromptTemplatePanel;
private final InfillPromptTemplatePanel infillPromptTemplatePanel;
public LlamaServerPreferencesForm() {
var llamaSettings = LlamaSettingsState.getInstance();
var llamaServerAgent =
ApplicationManager.getApplication().getService(LlamaServerAgent.class);
var serverRunning = llamaServerAgent.isServerRunning();
portField = new PortField(llamaSettings.getServerPort());
portField.setEnabled(!serverRunning);
maxTokensField = new IntegerField("max_tokens", 256, 4096);
maxTokensField.setColumns(12);
maxTokensField.setValue(llamaSettings.getContextSize());
maxTokensField.setEnabled(!serverRunning);
threadsField = new IntegerField("threads", 1, 256);
threadsField.setColumns(12);
threadsField.setValue(llamaSettings.getThreads());
threadsField.setEnabled(!serverRunning);
additionalParametersField = new JBTextField(llamaSettings.getAdditionalParameters(), 30);
additionalParametersField.setEnabled(!serverRunning);
baseHostField = new JBTextField(llamaSettings.getBaseHost(), 30);
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(LlamaCredentialsManager.getInstance().getApiKey());
llamaModelPreferencesForm = new LlamaModelPreferencesForm();
runLocalServerRadioButton = new JBRadioButton("Run local server",
llamaSettings.isRunLocalServer());
useExistingServerRadioButton = new JBRadioButton("Use remote server",
!llamaSettings.isRunLocalServer());
remotePromptTemplatePanel = new ChatPromptTemplatePanel(
llamaSettings.getRemoteModelPromptTemplate(), true);
infillPromptTemplatePanel = new InfillPromptTemplatePanel(
llamaSettings.getRemoteModelInfillPromptTemplate(), true
);
}
public JPanel getForm() {
var llamaServerAgent =
ApplicationManager.getApplication().getService(LlamaServerAgent.class);
return createForm(Map.of(
RUN_LOCAL_SERVER_FORM_CARD_CODE, new RadioButtonWithLayout(runLocalServerRadioButton,
createRunLocalServerForm(llamaServerAgent)),
USE_EXISTING_SERVER_FORM_CARD_CODE, new RadioButtonWithLayout(useExistingServerRadioButton,
createUseExistingServerForm())
), runLocalServerRadioButton.isSelected()
? RUN_LOCAL_SERVER_FORM_CARD_CODE
: USE_EXISTING_SERVER_FORM_CARD_CODE);
}
public JComponent createUseExistingServerForm() {
var apiKeyFieldPanel = UI.PanelFactory.panel(apiKeyField)
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
.resizeX(false)
.withComment(
CodeGPTBundle.get("settingsConfigurable.service.llama.apiKey.comment"))
.withCommentHyperlinkListener(UIUtil::handleHyperlinkClicked)
.createPanel();
return withEmptyLeftBorder(FormBuilder.createFormBuilder()
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.baseHost.label"),
baseHostField)
.addComponentToRightColumn(
createComment("settingsConfigurable.service.llama.baseHost.comment"))
.addLabeledComponent(CodeGPTBundle.get("shared.promptTemplate"),
remotePromptTemplatePanel)
.addComponentToRightColumn(remotePromptTemplatePanel.getPromptTemplateHelpText())
.addLabeledComponent(CodeGPTBundle.get("shared.infillPromptTemplate"),
infillPromptTemplatePanel)
.addComponentToRightColumn(infillPromptTemplatePanel.getPromptTemplateHelpText())
.addComponent(new TitledSeparator(
CodeGPTBundle.get("settingsConfigurable.shared.authentication.title")))
.addComponent(withEmptyLeftBorder(apiKeyFieldPanel))
.getPanel());
}
public JComponent createRunLocalServerForm(LlamaServerAgent llamaServerAgent) {
var serverProgressPanel = new ServerProgressPanel();
serverProgressPanel.setBorder(JBUI.Borders.emptyRight(16));
return withEmptyLeftBorder(FormBuilder.createFormBuilder()
.addComponent(new TitledSeparator(
CodeGPTBundle.get("settingsConfigurable.service.llama.modelPreferences.title")))
.addComponent(withEmptyLeftBorder(llamaModelPreferencesForm.getForm()))
.addComponent(new TitledSeparator("Server Configuration"))
.addComponent(withEmptyLeftBorder(FormBuilder.createFormBuilder()
.addLabeledComponent(
CodeGPTBundle.get("shared.port"),
JBUI.Panels.simplePanel()
.addToLeft(portField)
.addToRight(JBUI.Panels.simplePanel()
.addToCenter(serverProgressPanel)
.addToRight(getServerButton(llamaServerAgent, serverProgressPanel))))
.addVerticalGap(4)
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.contextSize.label"),
maxTokensField)
.addComponentToRightColumn(
createComment("settingsConfigurable.service.llama.contextSize.comment"))
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.threads.label"),
threadsField)
.addComponentToRightColumn(
createComment("settingsConfigurable.service.llama.threads.comment"))
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.additionalParameters.label"),
additionalParametersField)
.addComponentToRightColumn(
createComment("settingsConfigurable.service.llama.additionalParameters.comment"))
.addVerticalGap(4)
.addComponentFillVertically(new JPanel(), 0)
.getPanel()))
.getPanel());
}
private JButton getServerButton(
LlamaServerAgent llamaServerAgent,
ServerProgressPanel serverProgressPanel) {
var serverRunning = llamaServerAgent.isServerRunning();
var serverButton = new JButton();
serverButton.setText(serverRunning
? CodeGPTBundle.get("settingsConfigurable.service.llama.stopServer.label")
: CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
serverButton.setIcon(serverRunning ? Actions.Suspend : Actions.Execute);
serverButton.addActionListener(event -> {
if (!validateModelConfiguration()) {
return;
}
if (llamaServerAgent.isServerRunning()) {
enableForm(serverButton, serverProgressPanel);
llamaServerAgent.stopAgent();
} else {
disableForm(serverButton, serverProgressPanel);
llamaServerAgent.startAgent(
new LlamaServerStartupParams(
llamaModelPreferencesForm.getActualModelPath(),
getContextSize(),
getThreads(),
getServerPort(),
getListOfAdditionalParameters()),
serverProgressPanel,
() -> {
setFormEnabled(false);
serverProgressPanel.displayComponent(new JBLabel(
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.serverRunning"),
Actions.Checked,
SwingConstants.LEADING));
},
() -> {
setFormEnabled(true);
serverButton.setText(
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
serverButton.setIcon(Actions.Execute);
serverProgressPanel.displayComponent(new JBLabel(
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.serverTerminated"),
Actions.Cancel,
SwingConstants.LEADING));
});
}
});
return serverButton;
}
private boolean validateModelConfiguration() {
return validateCustomModelPath() && validateSelectedModel();
}
private boolean validateCustomModelPath() {
if (llamaModelPreferencesForm.isUseCustomLlamaModel()) {
var customModelPath = llamaModelPreferencesForm.getCustomLlamaModelPath();
if (customModelPath == null || customModelPath.isEmpty()) {
OverlayUtil.showBalloon(
CodeGPTBundle.get("validation.error.fieldRequired"),
MessageType.ERROR,
llamaModelPreferencesForm.getBrowsableCustomModelTextField());
return false;
}
}
return true;
}
private boolean validateSelectedModel() {
if (!llamaModelPreferencesForm.isUseCustomLlamaModel()
&& !isModelExists(llamaModelPreferencesForm.getSelectedModel())) {
OverlayUtil.showBalloon(
CodeGPTBundle.get("settingsConfigurable.service.llama.overlay.modelNotDownloaded.text"),
MessageType.ERROR,
llamaModelPreferencesForm.getHuggingFaceModelComboBox());
return false;
}
return true;
}
private boolean isModelExists(HuggingFaceModel model) {
return FileUtil.exists(
CodeGPTPlugin.getLlamaModelsPath() + File.separator + model.getFileName());
}
private void enableForm(JButton serverButton, ServerProgressPanel progressPanel) {
setFormEnabled(true);
serverButton.setText(
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
serverButton.setIcon(Actions.Execute);
progressPanel.updateText(
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.stoppingServer"));
}
private void disableForm(JButton serverButton, ServerProgressPanel progressPanel) {
setFormEnabled(false);
serverButton.setText(
CodeGPTBundle.get("settingsConfigurable.service.llama.stopServer.label"));
serverButton.setIcon(Actions.Suspend);
progressPanel.startProgress(
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.startingServer"));
}
private void setFormEnabled(boolean enabled) {
llamaModelPreferencesForm.enableFields(enabled);
portField.setEnabled(enabled);
maxTokensField.setEnabled(enabled);
threadsField.setEnabled(enabled);
additionalParametersField.setEnabled(enabled);
}
public void setRunLocalServer(boolean runLocalServer) {
runLocalServerRadioButton.setSelected(runLocalServer);
}
public boolean isRunLocalServer() {
return runLocalServerRadioButton.isSelected();
}
public void setBaseHost(String baseHost) {
baseHostField.setText(baseHost);
}
public String getBaseHost() {
return baseHostField.getText();
}
public void setServerPort(int serverPort) {
portField.setNumber(serverPort);
}
public int getServerPort() {
return portField.getNumber();
}
public LlamaModelPreferencesForm getLlamaModelPreferencesForm() {
return llamaModelPreferencesForm;
}
public int getContextSize() {
return maxTokensField.getValue();
}
public void setContextSize(int contextSize) {
maxTokensField.setValue(contextSize);
}
public void setThreads(int threads) {
threadsField.setValue(threads);
}
public int getThreads() {
return threadsField.getValue();
}
public void setAdditionalParameters(String additionalParameters) {
additionalParametersField.setText(additionalParameters);
}
public String getAdditionalParameters() {
return additionalParametersField.getText();
}
public List<String> getListOfAdditionalParameters() {
if (additionalParametersField.getText().trim().isEmpty()) {
return Collections.emptyList();
}
var parameters = additionalParametersField.getText().split(",");
return Arrays.stream(parameters)
.map(String::trim)
.collect(toList());
}
public PromptTemplate getPromptTemplate() {
return isRunLocalServer() ? llamaModelPreferencesForm.getPromptTemplate()
: remotePromptTemplatePanel.getPromptTemplate();
}
public void setApiKey(String apiKey) {
apiKeyField.setText(apiKey);
}
public String getApiKey() {
return new String(apiKeyField.getPassword());
}
public void setPromptTemplate(PromptTemplate promptTemplate) {
remotePromptTemplatePanel.setPromptTemplate(promptTemplate);
}
public void setInfillPromptTemplate(InfillPromptTemplate promptTemplate) {
infillPromptTemplatePanel.setPromptTemplate(promptTemplate);
}
public InfillPromptTemplate getInfillPromptTemplate() {
return infillPromptTemplatePanel.getPromptTemplate();
}
}

View file

@ -1,385 +1,93 @@
package ee.carlrobert.codegpt.settings.service;
import static ee.carlrobert.codegpt.ui.UIUtil.createRadioButtonsPanel;
import static java.util.stream.Collectors.toList;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.icons.AllIcons.Actions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.TextBrowseFolderListener;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.ui.panel.ComponentPanelBuilder;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.ui.PortField;
import com.intellij.ui.TitledSeparator;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.ui.components.JBTextField;
import com.intellij.ui.components.fields.IntegerField;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.JBUI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.CodeGPTPlugin;
import ee.carlrobert.codegpt.completions.HuggingFaceModel;
import ee.carlrobert.codegpt.completions.llama.LlamaServerAgent;
import ee.carlrobert.codegpt.completions.llama.LlamaServerStartupParams;
import ee.carlrobert.codegpt.settings.state.LlamaSettingsState;
import ee.carlrobert.codegpt.ui.OverlayUtil;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class LlamaServiceSelectionForm extends JPanel {
private static final String BUNDLED_SERVER_FORM_CARD_CODE = "BundledServerSettings";
private static final String CUSTOM_SERVER_FORM_CARD_CODE = "CustomServerSettings";
private final LlamaModelPreferencesForm llamaModelPreferencesForm;
private final LlamaServerPreferencesForm llamaServerPreferencesForm;
private final LlamaRequestPreferencesForm llamaRequestPreferencesForm;
private final PortField portField;
private final IntegerField maxTokensField;
private final IntegerField threadsField;
private final JBTextField additionalParametersField;
private final CardLayout cardLayout;
private final JBRadioButton bundledServerRadioButton;
private final JBRadioButton customServerRadioButton;
private final TextFieldWithBrowseButton browsableCustomServerTextField;
public LlamaServiceSelectionForm() {
var llamaServerAgent =
ApplicationManager.getApplication().getService(LlamaServerAgent.class);
var serverRunning = llamaServerAgent.isServerRunning();
portField = new PortField(LlamaSettingsState.getInstance().getServerPort());
portField.setEnabled(!serverRunning);
llamaModelPreferencesForm = new LlamaModelPreferencesForm();
llamaServerPreferencesForm = new LlamaServerPreferencesForm();
llamaRequestPreferencesForm = new LlamaRequestPreferencesForm();
init();
}
var llamaSettings = LlamaSettingsState.getInstance();
maxTokensField = new IntegerField("max_tokens", 256, 4096);
maxTokensField.setColumns(12);
maxTokensField.setValue(llamaSettings.getContextSize());
maxTokensField.setEnabled(!serverRunning);
public void setRunLocalServer(boolean runLocalServer) {
llamaServerPreferencesForm.setRunLocalServer(runLocalServer);
}
threadsField = new IntegerField("threads", 1, 256);
threadsField.setColumns(12);
threadsField.setValue(llamaSettings.getThreads());
threadsField.setEnabled(!serverRunning);
public boolean isRunLocalServer() {
return llamaServerPreferencesForm.isRunLocalServer();
}
additionalParametersField = new JBTextField(llamaSettings.getAdditionalParameters(), 30);
additionalParametersField.setEnabled(!serverRunning);
public void setBaseHost(String baseHost) {
llamaServerPreferencesForm.setBaseHost(baseHost);
}
cardLayout = new CardLayout();
bundledServerRadioButton = new JBRadioButton("Use bundled server",
!llamaSettings.isUseCustomServer());
customServerRadioButton = new JBRadioButton("Use custom server",
llamaSettings.isUseCustomServer());
browsableCustomServerTextField = createBrowsableCustomServerTextField(
!llamaServerAgent.isServerRunning());
browsableCustomServerTextField.setText(llamaSettings.getCustomLlamaServerPath());
init(llamaServerAgent);
public String getBaseHost() {
return llamaServerPreferencesForm.getBaseHost();
}
public void setServerPort(int serverPort) {
portField.setNumber(serverPort);
llamaServerPreferencesForm.setServerPort(serverPort);
}
public int getServerPort() {
return portField.getNumber();
return llamaServerPreferencesForm.getServerPort();
}
public LlamaServerPreferencesForm getLlamaServerPreferencesForm() {
return llamaServerPreferencesForm;
}
public LlamaModelPreferencesForm getLlamaModelPreferencesForm() {
return llamaModelPreferencesForm;
return llamaServerPreferencesForm.getLlamaModelPreferencesForm();
}
public LlamaRequestPreferencesForm getLlamaRequestPreferencesForm() {
return llamaRequestPreferencesForm;
}
private JComponent withEmptyLeftBorder(JComponent component) {
component.setBorder(JBUI.Borders.emptyLeft(16));
return component;
}
public String getActualServerPath() {
return isUseCustomServer()
? getCustomServerPath()
: CodeGPTPlugin.getLlamaSourcePath() + File.separator + "server";
}
public int getContextSize() {
return maxTokensField.getValue();
return llamaServerPreferencesForm.getContextSize();
}
public void setContextSize(int contextSize) {
maxTokensField.setValue(contextSize);
llamaServerPreferencesForm.setContextSize(contextSize);
}
public void setThreads(int threads) {
threadsField.setValue(threads);
llamaServerPreferencesForm.setThreads(threads);
}
public int getThreads() {
return threadsField.getValue();
return llamaServerPreferencesForm.getThreads();
}
public void setAdditionalParameters(String additionalParameters) {
additionalParametersField.setText(additionalParameters);
llamaServerPreferencesForm.setAdditionalParameters(additionalParameters);
}
public String getAdditionalParameters() {
return additionalParametersField.getText();
return llamaServerPreferencesForm.getAdditionalParameters();
}
public List<String> getListOfAdditionalParameters() {
if (additionalParametersField.getText().trim().isEmpty()) {
return Collections.emptyList();
}
var parameters = additionalParametersField.getText().split(",");
return Arrays.stream(parameters)
.map(String::trim)
.collect(toList());
}
public void setIsUseCustomServer(boolean useCustomServer) {
customServerRadioButton.setSelected(useCustomServer);
}
public boolean isUseCustomServer() {
return customServerRadioButton.isSelected();
}
public void setCustomServerPath(String customServerPath) {
browsableCustomServerTextField.setText(customServerPath);
}
public String getCustomServerPath() {
return browsableCustomServerTextField.getText();
}
private void init(LlamaServerAgent llamaServerAgent) {
var serverProgressPanel = new ServerProgressPanel();
serverProgressPanel.setBorder(JBUI.Borders.emptyRight(16));
private void init() {
setLayout(new BorderLayout());
add(FormBuilder.createFormBuilder()
.addComponent(new TitledSeparator(
CodeGPTBundle.get("settingsConfigurable.service.llama.modelPreferences.title")))
.addComponent(withEmptyLeftBorder(llamaModelPreferencesForm.getForm()))
.addComponent(new TitledSeparator(
CodeGPTBundle.get("settingsConfigurable.service.llama.serverPreferences.title")))
.addComponent(withEmptyLeftBorder(FormBuilder.createFormBuilder()
.addComponent(getForm())
.addLabeledComponent(
CodeGPTBundle.get("shared.port"),
JBUI.Panels.simplePanel()
.addToLeft(portField)
.addToRight(JBUI.Panels.simplePanel()
.addToCenter(serverProgressPanel)
.addToRight(getServerButton(llamaServerAgent, serverProgressPanel))))
.addVerticalGap(4)
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.contextSize.label"),
maxTokensField)
.addComponentToRightColumn(
createComment("settingsConfigurable.service.llama.contextSize.comment"))
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.threads.label"),
threadsField)
.addComponentToRightColumn(
createComment("settingsConfigurable.service.llama.threads.comment"))
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.additionalParameters.label"),
additionalParametersField)
.addComponentToRightColumn(
createComment("settingsConfigurable.service.llama.additionalParameters.comment"))
.addVerticalGap(8)
.getPanel()))
.addComponent(llamaServerPreferencesForm.getForm())
.addComponent(new TitledSeparator("Request Preferences"))
.addComponent(withEmptyLeftBorder(llamaRequestPreferencesForm.getForm()))
.addComponentFillVertically(new JPanel(), 0)
.getPanel());
}
public JPanel getForm() {
JPanel finalPanel = new JPanel(new BorderLayout());
finalPanel.add(createRadioButtonsPanel(bundledServerRadioButton, customServerRadioButton),
BorderLayout.NORTH);
finalPanel.add(createFormPanelCards(), BorderLayout.CENTER);
return finalPanel;
}
private JPanel createFormPanelCards() {
var formPanelCards = new JPanel(cardLayout);
formPanelCards.setBorder(JBUI.Borders.emptyLeft(16));
formPanelCards.add(new JPanel(), BUNDLED_SERVER_FORM_CARD_CODE);
formPanelCards.add(createCustomServerForm(), CUSTOM_SERVER_FORM_CARD_CODE);
cardLayout.show(
formPanelCards,
bundledServerRadioButton.isSelected()
? BUNDLED_SERVER_FORM_CARD_CODE
: CUSTOM_SERVER_FORM_CARD_CODE);
bundledServerRadioButton.addActionListener(e ->
cardLayout.show(formPanelCards, BUNDLED_SERVER_FORM_CARD_CODE));
customServerRadioButton.addActionListener(e ->
cardLayout.show(formPanelCards, CUSTOM_SERVER_FORM_CARD_CODE));
return formPanelCards;
}
private JPanel createCustomServerForm() {
var customModelHelpText = ComponentPanelBuilder.createCommentComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.customServerPath.comment"),
true);
customModelHelpText.setBorder(JBUI.Borders.empty(0, 4));
return FormBuilder.createFormBuilder()
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.customServerPath.label"),
browsableCustomServerTextField)
.addComponentToRightColumn(customModelHelpText)
.addVerticalGap(4)
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}
private TextFieldWithBrowseButton createBrowsableCustomServerTextField(boolean enabled) {
var browseButton = new TextFieldWithBrowseButton();
browseButton.setEnabled(enabled);
var fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFileDescriptor();
fileChooserDescriptor.setForcedToUseIdeaFileChooser(true);
fileChooserDescriptor.setHideIgnored(false);
browseButton.addBrowseFolderListener(new TextBrowseFolderListener(fileChooserDescriptor));
return browseButton;
}
private JLabel createComment(String messageKey) {
var comment = ComponentPanelBuilder.createCommentComponent(
CodeGPTBundle.get(messageKey), true);
comment.setBorder(JBUI.Borders.empty(0, 4));
return comment;
}
private JButton getServerButton(
LlamaServerAgent llamaServerAgent,
ServerProgressPanel serverProgressPanel) {
var serverRunning = llamaServerAgent.isServerRunning();
var serverButton = new JButton();
serverButton.setText(serverRunning
? CodeGPTBundle.get("settingsConfigurable.service.llama.stopServer.label")
: CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
serverButton.setIcon(serverRunning ? Actions.Suspend : Actions.Execute);
serverButton.addActionListener(event -> {
if (!validateModelConfiguration()) {
return;
}
if (llamaServerAgent.isServerRunning()) {
enableForm(serverButton, serverProgressPanel);
llamaServerAgent.stopAgent();
} else {
disableForm(serverButton, serverProgressPanel);
llamaServerAgent.startAgent(
new LlamaServerStartupParams(
getActualServerPath(),
isUseCustomServer(),
llamaModelPreferencesForm.getActualModelPath(),
getContextSize(),
getThreads(),
getServerPort(),
getListOfAdditionalParameters()),
serverProgressPanel,
() -> {
setFormEnabled(false);
serverProgressPanel.displayComponent(new JBLabel(
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.serverRunning"),
Actions.Checked,
SwingConstants.LEADING));
},
() -> {
setFormEnabled(true);
serverButton.setText(
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
serverButton.setIcon(Actions.Execute);
serverProgressPanel.displayComponent(new JBLabel(
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.serverTerminated"),
Actions.Cancel,
SwingConstants.LEADING));
});
}
});
return serverButton;
}
private boolean validateModelConfiguration() {
return validateCustomModelPath() && validateSelectedModel();
}
private boolean validateCustomModelPath() {
if (llamaModelPreferencesForm.isUseCustomLlamaModel()) {
var customModelPath = llamaModelPreferencesForm.getCustomLlamaModelPath();
if (customModelPath == null || customModelPath.isEmpty()) {
OverlayUtil.showBalloon(
CodeGPTBundle.get("validation.error.fieldRequired"),
MessageType.ERROR,
llamaModelPreferencesForm.getBrowsableCustomModelTextField());
return false;
}
}
return true;
}
private boolean validateSelectedModel() {
if (!llamaModelPreferencesForm.isUseCustomLlamaModel()
&& !isModelExists(llamaModelPreferencesForm.getSelectedModel())) {
OverlayUtil.showBalloon(
CodeGPTBundle.get("settingsConfigurable.service.llama.overlay.modelNotDownloaded.text"),
MessageType.ERROR,
llamaModelPreferencesForm.getHuggingFaceModelComboBox());
return false;
}
return true;
}
private void enableForm(JButton serverButton, ServerProgressPanel progressPanel) {
setFormEnabled(true);
serverButton.setText(
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
serverButton.setIcon(Actions.Execute);
progressPanel.updateText(
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.stoppingServer"));
}
private void disableForm(JButton serverButton, ServerProgressPanel progressPanel) {
setFormEnabled(false);
serverButton.setText(
CodeGPTBundle.get("settingsConfigurable.service.llama.stopServer.label"));
serverButton.setIcon(Actions.Suspend);
progressPanel.startProgress(
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.startingServer"));
}
private boolean isModelExists(HuggingFaceModel model) {
return FileUtil.exists(
CodeGPTPlugin.getLlamaModelsPath() + File.separator + model.getFileName());
}
private void setFormEnabled(boolean enabled) {
llamaModelPreferencesForm.enableFields(enabled);
portField.setEnabled(enabled);
maxTokensField.setEnabled(enabled);
threadsField.setEnabled(enabled);
additionalParametersField.setEnabled(enabled);
}
}

View file

@ -14,6 +14,7 @@ import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.completions.you.auth.AuthenticationNotifier;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialsManager;
@ -361,6 +362,10 @@ public class ServiceSelectionForm {
return displayWebSearchResultsCheckBox.isSelected();
}
public LlamaServerPreferencesForm getLlamaServerPreferencesForm() {
return llamaServiceSectionPanel.getLlamaServerPreferencesForm();
}
public LlamaModelPreferencesForm getLlamaModelPreferencesForm() {
return llamaServiceSectionPanel.getLlamaModelPreferencesForm();
}
@ -385,6 +390,22 @@ public class ServiceSelectionForm {
return azurePathField.getText();
}
public void setLlamaRunLocalServer(boolean runLocalServer) {
llamaServiceSectionPanel.setRunLocalServer(runLocalServer);
}
public boolean isLlamaRunLocalServer() {
return llamaServiceSectionPanel.isRunLocalServer();
}
public void setLlamaBaseHost(String baseHost) {
llamaServiceSectionPanel.setBaseHost(baseHost);
}
public String getLlamaBaseHost() {
return llamaServiceSectionPanel.getBaseHost();
}
public void setLlamaServerPort(int serverPort) {
llamaServiceSectionPanel.setServerPort(serverPort);
}
@ -433,19 +454,11 @@ public class ServiceSelectionForm {
llamaServiceSectionPanel.setAdditionalParameters(additionalParameters);
}
public void setUseCustomLlamaServer(boolean useCustomLlamaServer) {
llamaServiceSectionPanel.setIsUseCustomServer(useCustomLlamaServer);
public PromptTemplate getLlamaPromptTemplate() {
return getLlamaServerPreferencesForm().getPromptTemplate();
}
public boolean isUseCustomLlamaServer() {
return llamaServiceSectionPanel.isUseCustomServer();
}
public void setCustomLlamaServerPath(String serverPath) {
llamaServiceSectionPanel.setCustomServerPath(serverPath);
}
public String getCustomLlamaServerPath() {
return llamaServiceSectionPanel.getCustomServerPath();
public void setLlamaPromptTemplate(PromptTemplate promptTemplate) {
getLlamaServerPreferencesForm().setPromptTemplate(promptTemplate);
}
}

View file

@ -8,6 +8,7 @@ import com.intellij.util.xmlb.XmlSerializerUtil;
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate;
import ee.carlrobert.codegpt.completions.HuggingFaceModel;
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.credentials.LlamaCredentialsManager;
import ee.carlrobert.codegpt.settings.service.ServiceSelectionForm;
import java.io.IOException;
import java.net.ServerSocket;
@ -16,13 +17,15 @@ import org.jetbrains.annotations.NotNull;
@State(name = "CodeGPT_LlamaSettings", storages = @Storage("CodeGPT_CodeGPT_LlamaSettings.xml"))
public class LlamaSettingsState implements PersistentStateComponent<LlamaSettingsState> {
private boolean runLocalServer = true;
private boolean useCustomModel;
private String customLlamaModelPath = "";
private boolean useCustomServer;
private String customLlamaServerPath = "";
private HuggingFaceModel huggingFaceModel = HuggingFaceModel.CODE_LLAMA_7B_Q4;
private PromptTemplate promptTemplate = PromptTemplate.LLAMA;
private InfillPromptTemplate infillPromptTemplate = InfillPromptTemplate.LLAMA;
private PromptTemplate localModelPromptTemplate = PromptTemplate.LLAMA;
private PromptTemplate remoteModelPromptTemplate = PromptTemplate.LLAMA;
private InfillPromptTemplate localModelInfillPromptTemplate = InfillPromptTemplate.LLAMA;
private InfillPromptTemplate remoteModelInfillPromptTemplate = InfillPromptTemplate.LLAMA;
private String baseHost = "http://localhost:8080";
private Integer serverPort = getRandomAvailablePortOrDefault();
private int contextSize = 2048;
private int threads = 8;
@ -52,18 +55,25 @@ public class LlamaSettingsState implements PersistentStateComponent<LlamaSetting
public boolean isModified(ServiceSelectionForm serviceSelectionForm) {
var modelPreferencesForm = serviceSelectionForm.getLlamaModelPreferencesForm();
var requestPreferencesForm = serviceSelectionForm.getLlamaRequestPreferencesForm();
return serverPort != serviceSelectionForm.getLlamaServerPort()
var serverPreferencesForm = serviceSelectionForm.getLlamaServerPreferencesForm();
return !serviceSelectionForm.getLlamaServerPreferencesForm().getApiKey()
.equals(LlamaCredentialsManager.getInstance().getApiKey())
|| runLocalServer != serviceSelectionForm.isLlamaRunLocalServer()
|| !localModelPromptTemplate.equals(modelPreferencesForm.getPromptTemplate())
|| !remoteModelPromptTemplate.equals(serviceSelectionForm.getLlamaPromptTemplate())
|| localModelInfillPromptTemplate != modelPreferencesForm.getInfillPromptTemplate()
|| remoteModelInfillPromptTemplate != serverPreferencesForm.getInfillPromptTemplate()
|| !baseHost.equals(serviceSelectionForm.getLlamaBaseHost())
|| serverPort != serviceSelectionForm.getLlamaServerPort()
|| contextSize != serviceSelectionForm.getContextSize()
|| threads != serviceSelectionForm.getThreads()
|| useCustomServer != serviceSelectionForm.isUseCustomLlamaServer()
|| !customLlamaServerPath.equals(serviceSelectionForm.getCustomLlamaServerPath())
|| !additionalParameters.equals(serviceSelectionForm.getAdditionalParameters())
|| huggingFaceModel != modelPreferencesForm.getSelectedModel()
|| topK != requestPreferencesForm.getTopK()
|| topP != requestPreferencesForm.getTopP()
|| minP != requestPreferencesForm.getMinP()
|| repeatPenalty != requestPreferencesForm.getRepeatPenalty()
|| !promptTemplate.equals(modelPreferencesForm.getPromptTemplate())
|| useCustomModel != modelPreferencesForm.isUseCustomLlamaModel()
|| !customLlamaModelPath.equals(modelPreferencesForm.getCustomLlamaModelPath());
}
@ -71,19 +81,24 @@ public class LlamaSettingsState implements PersistentStateComponent<LlamaSetting
public void apply(ServiceSelectionForm serviceSelectionForm) {
var modelPreferencesForm = serviceSelectionForm.getLlamaModelPreferencesForm();
customLlamaModelPath = modelPreferencesForm.getCustomLlamaModelPath();
customLlamaModelPath = modelPreferencesForm.getCustomLlamaModelPath();
huggingFaceModel = modelPreferencesForm.getSelectedModel();
useCustomModel = modelPreferencesForm.isUseCustomLlamaModel();
promptTemplate = modelPreferencesForm.getPromptTemplate();
localModelPromptTemplate = modelPreferencesForm.getPromptTemplate();
remoteModelPromptTemplate = serviceSelectionForm.getLlamaPromptTemplate();
localModelInfillPromptTemplate = modelPreferencesForm.getInfillPromptTemplate();
remoteModelInfillPromptTemplate =
serviceSelectionForm.getLlamaServerPreferencesForm().getInfillPromptTemplate();
var requestPreferencesForm = serviceSelectionForm.getLlamaRequestPreferencesForm();
topK = requestPreferencesForm.getTopK();
topP = requestPreferencesForm.getTopP();
minP = requestPreferencesForm.getMinP();
repeatPenalty = requestPreferencesForm.getRepeatPenalty();
runLocalServer = serviceSelectionForm.isLlamaRunLocalServer();
baseHost = serviceSelectionForm.getLlamaBaseHost();
serverPort = serviceSelectionForm.getLlamaServerPort();
contextSize = serviceSelectionForm.getContextSize();
threads = serviceSelectionForm.getThreads();
useCustomServer = serviceSelectionForm.isUseCustomLlamaServer();
customLlamaServerPath = serviceSelectionForm.getCustomLlamaServerPath();
additionalParameters = serviceSelectionForm.getAdditionalParameters();
}
@ -92,34 +107,24 @@ public class LlamaSettingsState implements PersistentStateComponent<LlamaSetting
modelPreferencesForm.setSelectedModel(huggingFaceModel);
modelPreferencesForm.setCustomLlamaModelPath(customLlamaModelPath);
modelPreferencesForm.setUseCustomLlamaModel(useCustomModel);
modelPreferencesForm.setPromptTemplate(promptTemplate);
modelPreferencesForm.setPromptTemplate(localModelPromptTemplate);
modelPreferencesForm.setInfillPromptTemplate(localModelInfillPromptTemplate);
var requestPreferencesForm = serviceSelectionForm.getLlamaRequestPreferencesForm();
requestPreferencesForm.setTopK(topK);
requestPreferencesForm.setTopP(topP);
requestPreferencesForm.setMinP(minP);
requestPreferencesForm.setRepeatPenalty(repeatPenalty);
serviceSelectionForm.setLlamaRunLocalServer(runLocalServer);
serviceSelectionForm.setLlamaBaseHost(baseHost);
serviceSelectionForm.setLlamaServerPort(serverPort);
serviceSelectionForm.setLlamaPromptTemplate(remoteModelPromptTemplate);
serviceSelectionForm.setContextSize(contextSize);
serviceSelectionForm.setThreads(threads);
serviceSelectionForm.setUseCustomLlamaServer(useCustomServer);
serviceSelectionForm.setCustomLlamaServerPath(customLlamaServerPath);
serviceSelectionForm.setAdditionalParameters(additionalParameters);
}
public boolean isUseCustomServer() {
return useCustomServer;
}
public void setUseCustomServer(boolean useCustomServer) {
this.useCustomServer = useCustomServer;
}
public String getCustomLlamaServerPath() {
return customLlamaServerPath;
}
public void setCustomLlamaServerPath(String customLlamaServerPath) {
this.customLlamaServerPath = customLlamaServerPath;
var llamaServerPreferencesForm = serviceSelectionForm.getLlamaServerPreferencesForm();
llamaServerPreferencesForm.setInfillPromptTemplate(remoteModelInfillPromptTemplate);
llamaServerPreferencesForm.setApiKey(LlamaCredentialsManager.getInstance().getApiKey());
}
public boolean isUseCustomModel() {
@ -146,12 +151,56 @@ public class LlamaSettingsState implements PersistentStateComponent<LlamaSetting
this.huggingFaceModel = huggingFaceModel;
}
public PromptTemplate getPromptTemplate() {
return promptTemplate;
public PromptTemplate getLocalModelPromptTemplate() {
return localModelPromptTemplate;
}
public void setPromptTemplate(PromptTemplate promptTemplate) {
this.promptTemplate = promptTemplate;
public void setLocalModelPromptTemplate(
PromptTemplate localModelPromptTemplate) {
this.localModelPromptTemplate = localModelPromptTemplate;
}
public InfillPromptTemplate getLocalModelInfillPromptTemplate() {
return localModelInfillPromptTemplate;
}
public void setLocalModelInfillPromptTemplate(
InfillPromptTemplate localModelInfillPromptTemplate) {
this.localModelInfillPromptTemplate = localModelInfillPromptTemplate;
}
public InfillPromptTemplate getRemoteModelInfillPromptTemplate() {
return remoteModelInfillPromptTemplate;
}
public void setRemoteModelInfillPromptTemplate(
InfillPromptTemplate remoteModelInfillPromptTemplate) {
this.remoteModelInfillPromptTemplate = remoteModelInfillPromptTemplate;
}
public boolean isRunLocalServer() {
return runLocalServer;
}
public void setRunLocalServer(boolean runLocalServer) {
this.runLocalServer = runLocalServer;
}
public String getBaseHost() {
return baseHost;
}
public void setBaseHost(String baseHost) {
this.baseHost = baseHost;
}
public PromptTemplate getRemoteModelPromptTemplate() {
return remoteModelPromptTemplate;
}
public void setRemoteModelPromptTemplate(
PromptTemplate remoteModelPromptTemplate) {
this.remoteModelPromptTemplate = remoteModelPromptTemplate;
}
public Integer getServerPort() {
@ -218,14 +267,6 @@ public class LlamaSettingsState implements PersistentStateComponent<LlamaSetting
this.repeatPenalty = repeatPenalty;
}
public InfillPromptTemplate getInfillPromptTemplate() {
return infillPromptTemplate;
}
public void setInfillPromptTemplate(InfillPromptTemplate infillPromptTemplate) {
this.infillPromptTemplate = infillPromptTemplate;
}
private static Integer getRandomAvailablePortOrDefault() {
try (ServerSocket socket = new ServerSocket(0)) {
return socket.getLocalPort();

View file

@ -0,0 +1,81 @@
package ee.carlrobert.codegpt.ui;
import com.intellij.icons.AllIcons.General;
import com.intellij.ide.HelpTooltip;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.panel.ComponentPanelBuilder;
import com.intellij.ui.EnumComboBoxModel;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ui.JBUI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import java.awt.FlowLayout;
import java.util.Arrays;
import java.util.stream.Collectors;
import javax.swing.Box;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.apache.commons.text.StringEscapeUtils;
public abstract class BasePromptTemplatePanel<T extends Enum<T>> extends JPanel {
private final JBLabel promptTemplateHelpIcon;
protected final ComboBox<T> promptTemplateComboBox;
private final JLabel promptTemplateHelpText;
private final Class<T> enumClass;
public BasePromptTemplatePanel(
Class<T> enumClass,
T initiallySelectedTemplate,
boolean enabled,
String helpTextKey) {
super(new FlowLayout(FlowLayout.LEADING, 0, 0));
this.enumClass = enumClass;
promptTemplateComboBox = new ComboBox<>(new EnumComboBoxModel<>(enumClass));
promptTemplateComboBox.setSelectedItem(initiallySelectedTemplate);
promptTemplateComboBox.setEnabled(enabled);
promptTemplateComboBox.addItemListener(
item -> updatePromptTemplateHelpTooltip(enumClass.cast(item.getItem())));
add(promptTemplateComboBox);
add(Box.createHorizontalStrut(8));
promptTemplateHelpIcon = new JBLabel(General.ContextHelp);
add(promptTemplateHelpIcon);
promptTemplateHelpText = ComponentPanelBuilder.createCommentComponent(
CodeGPTBundle.get(helpTextKey),
true);
promptTemplateHelpText.setBorder(JBUI.Borders.empty(0, 4));
updatePromptTemplateHelpTooltip(initiallySelectedTemplate);
}
public void setPromptTemplate(T promptTemplate) {
promptTemplateComboBox.setSelectedItem(promptTemplate);
}
public T getPromptTemplate() {
Object selectedItem = promptTemplateComboBox.getSelectedItem();
if (!enumClass.isInstance(selectedItem)) {
throw new IllegalStateException("Selected item is not an instance of the expected type.");
}
return enumClass.cast(selectedItem);
}
public JLabel getPromptTemplateHelpText() {
return promptTemplateHelpText;
}
protected abstract String buildPromptDescription(T template);
private void updatePromptTemplateHelpTooltip(T template) {
promptTemplateHelpIcon.setToolTipText(null);
var htmlDescription = Arrays.stream(buildPromptDescription(template).split("\n"))
.map(StringEscapeUtils::escapeHtml4)
.collect(Collectors.joining("<br>"));
new HelpTooltip()
.setTitle(template.toString())
.setDescription("<html><p>" + htmlDescription + "</p></html>")
.installOn(promptTemplateHelpIcon);
}
}

View file

@ -0,0 +1,24 @@
package ee.carlrobert.codegpt.ui;
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.conversations.message.Message;
import java.util.List;
public class ChatPromptTemplatePanel extends BasePromptTemplatePanel<PromptTemplate> {
public ChatPromptTemplatePanel(PromptTemplate initiallySelectedTemplate, boolean enabled) {
super(
PromptTemplate.class,
initiallySelectedTemplate,
enabled,
"settingsConfigurable.service.llama.promptTemplate.comment");
}
@Override
protected String buildPromptDescription(PromptTemplate template) {
return template.buildPrompt(
"SYSTEM_PROMPT",
"USER_PROMPT",
List.of(new Message("PREV_PROMPT", "PREV_RESPONSE")));
}
}

View file

@ -0,0 +1,21 @@
package ee.carlrobert.codegpt.ui;
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate;
public class InfillPromptTemplatePanel extends BasePromptTemplatePanel<InfillPromptTemplate> {
public InfillPromptTemplatePanel(
InfillPromptTemplate initiallySelectedTemplate,
boolean enabled) {
super(
InfillPromptTemplate.class,
initiallySelectedTemplate,
enabled,
"settingsConfigurable.service.llama.infillTemplate.comment");
}
@Override
protected String buildPromptDescription(InfillPromptTemplate template) {
return template.buildPrompt("PREFIX", "SUFFIX");
}
}

View file

@ -4,15 +4,27 @@ import static javax.swing.event.HyperlinkEvent.EventType.ACTIVATED;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
import com.intellij.openapi.ui.panel.ComponentPanelBuilder;
import com.intellij.ui.JBColor;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.ui.components.JBTextArea;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.toolwindow.chat.ui.SmartScroller;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
@ -109,17 +121,99 @@ public class UIUtil {
textArea.getActionMap().put("text-submit", onSubmit);
}
public static JPanel createRadioButtonsPanel(JBRadioButton... radioButtons) {
public static JPanel createRadioButtonsPanel(List<JBRadioButton> radioButtons) {
var buttonGroup = new ButtonGroup();
var radioPanel = new JPanel();
radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.PAGE_AXIS));
for (int i = 0; i < radioButtons.length; i++) {
JBRadioButton radioButton = radioButtons[i];
for (int i = 0; i < radioButtons.size(); i++) {
JBRadioButton radioButton = radioButtons.get(i);
buttonGroup.add(radioButton);
radioPanel.add(radioButton);
radioPanel.add(Box.createVerticalStrut(i == radioButtons.length - 1 ? 8 : 4));
radioPanel.add(Box.createVerticalStrut(i == radioButtons.size() - 1 ? 8 : 4));
}
return withEmptyLeftBorder(radioPanel);
}
public static <T extends JComponent> T withEmptyLeftBorder(T component) {
component.setBorder(JBUI.Borders.emptyLeft(16));
return component;
}
public static JLabel createComment(String messageKey) {
var comment = ComponentPanelBuilder.createCommentComponent(
CodeGPTBundle.get(messageKey), true);
comment.setBorder(JBUI.Borders.empty(0, 4));
return comment;
}
public static JPanel createForm(Map<String, RadioButtonWithLayout> layouts,
String initialLayout) {
JPanel finalPanel = new JPanel(new BorderLayout());
finalPanel.add(createRadioButtonsPanel(layouts.values().stream().map(
RadioButtonWithLayout::getRadioButton).collect(Collectors.toList())),
BorderLayout.NORTH);
finalPanel.add(createRadioButtonGroupLayouts(layouts, initialLayout), BorderLayout.CENTER);
return finalPanel;
}
/**
* Creates RadioButton group to toggle between different layouts.
*
* @param layouts Map from layout name to RadioButton + Layout to be shown
* @param initialLayout Key of {@code layouts} entry to be initially shown
* @return Panel with the RadioButton group
*/
public static JPanel createRadioButtonGroupLayouts(
Map<String, RadioButtonWithLayout> layouts,
String initialLayout) {
CardLayout cardlayout = new CardLayout() {
@Override
public void show(Container parent, String name) {
super.show(parent, name);
// Set height to selected components height instead of consistent height
Optional<Component> selectedComponent = Arrays.stream(parent.getComponents())
.filter(component -> name.equals(component.getName()))
.findFirst();
if (selectedComponent.isEmpty()) {
return;
}
parent.setPreferredSize(new Dimension(parent.getPreferredSize().width,
(int) selectedComponent.get().getPreferredSize().getHeight()));
}
};
var formPanelCards = new JPanel(cardlayout);
for (Entry<String, RadioButtonWithLayout> layout : layouts.entrySet()) {
RadioButtonWithLayout value = layout.getValue();
Component component = value.getComponent();
String key = layout.getKey();
component.setName(key);
formPanelCards.add(component, key);
value.getRadioButton().addActionListener(e -> cardlayout.show(formPanelCards, key));
}
cardlayout.show(formPanelCards, initialLayout);
return formPanelCards;
}
public static class RadioButtonWithLayout {
private final JBRadioButton radioButton;
private final Component layout;
public RadioButtonWithLayout(JBRadioButton radioButton, Component layout) {
this.radioButton = radioButton;
this.layout = layout;
}
public JBRadioButton getRadioButton() {
return radioButton;
}
public Component getComponent() {
return layout;
}
return radioPanel;
}
}

View file

@ -35,6 +35,7 @@ settingsConfigurable.service.you.displayResults.label=Display web search results
settingsConfigurable.service.you.authentication.title=Authentication (Optional)
settingsConfigurable.service.you.userInformation.title=User Information
settingsConfigurable.service.you.chatPreferences.title=Chat Preferences
settingsConfigurable.service.llama.apiKey.comment=API Key for authentication, added to 'Authorization' header as bearer (Optional)
settingsConfigurable.service.llama.modelPreferences.title=Model Preferences
settingsConfigurable.service.llama.serverPreferences.title=Server Preferences
settingsConfigurable.service.llama.modelSize.label=Model size:
@ -45,6 +46,7 @@ settingsConfigurable.service.llama.customModelPath.comment=Only .gguf files are
settingsConfigurable.service.llama.customServerPath.label=Server path:
settingsConfigurable.service.llama.customServerPath.comment=Precompiled executable llama-cpp server, only .exe (Windows) or executable File (Linux) are supported
settingsConfigurable.service.llama.promptTemplate.comment=Choose the template to use during interactions with the language model. Make sure it matches the custom model you're working with.
settingsConfigurable.service.llama.infillTemplate.comment=The template to use for code completions. Make sure the model you're working with supports code infilling.
settingsConfigurable.service.llama.downloadModelLink.label=Download Model
settingsConfigurable.service.llama.cancelDownloadLink.label=Cancel Downloading
settingsConfigurable.service.llama.linkToModel.label=Link to model
@ -54,6 +56,8 @@ settingsConfigurable.service.llama.threads.label=Threads:
settingsConfigurable.service.llama.threads.comment=The number of threads available to execute the model. It is not recommended to specify a number greater than the number of processor cores.
settingsConfigurable.service.llama.additionalParameters.label=Additional parameters:
settingsConfigurable.service.llama.additionalParameters.comment=<html>Additional command-line parameters for the server startup process, separated by commas. See the full <a href="https://github.com/ggerganov/llama.cpp/blob/master/examples/server/README.md">list of options</a>.<p><i>Example: "--n-gpu-layers, 1, --no-mmap, --mlock"</i></p></html>
settingsConfigurable.service.llama.baseHost.label=Base host:
settingsConfigurable.service.llama.baseHost.comment=URL to existing LLama server
settingsConfigurable.service.llama.startServer.label=Start server
settingsConfigurable.service.llama.stopServer.label=Stop server
settingsConfigurable.service.llama.progress.serverRunning=Server running
@ -168,5 +172,6 @@ notification.compilationError.okLabel=Resolve errors
notification.completionError.description=Completion failed:<br/>%s
statusBar.widget.tooltip=Status
shared.promptTemplate=Prompt template:
shared.infillPromptTemplate=Infill template:
shared.port=Port:
codeCompletion.progress.title=Code completion in progress