diff --git a/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestProvider.java b/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestProvider.java index ab941750..07701c33 100644 --- a/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestProvider.java +++ b/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestProvider.java @@ -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(); + } } diff --git a/src/main/java/ee/carlrobert/codegpt/completions/CompletionClientProvider.java b/src/main/java/ee/carlrobert/codegpt/completions/CompletionClientProvider.java index c2e3b719..4afcbbcd 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/CompletionClientProvider.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/CompletionClientProvider.java @@ -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() { diff --git a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestProvider.java b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestProvider.java index e64bd838..fe52ff7b 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestProvider.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestProvider.java @@ -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) { diff --git a/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaModel.java b/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaModel.java index 4e0afd49..f6496a5f 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaModel.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaModel.java @@ -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 huggingFaceModels; LlamaModel( @@ -92,9 +96,19 @@ public enum LlamaModel { String description, PromptTemplate promptTemplate, List huggingFaceModels) { + this(label, description, promptTemplate, null, huggingFaceModels); + } + + LlamaModel( + String label, + String description, + PromptTemplate promptTemplate, + InfillPromptTemplate infillPromptTemplate, + List 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 getHuggingFaceModels() { return huggingFaceModels; } diff --git a/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaServerAgent.java b/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaServerAgent.java index f09a9803..34568997 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaServerAgent.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaServerAgent.java @@ -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()), diff --git a/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaServerStartupParams.java b/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaServerStartupParams.java index fcb94837..5ea26679 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaServerStartupParams.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/llama/LlamaServerStartupParams.java @@ -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 additionalParameters; public LlamaServerStartupParams( - String serverPath, - boolean useCustomServer, String modelPath, + String modelPath, int contextLength, int threads, int port, List 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; } diff --git a/src/main/java/ee/carlrobert/codegpt/credentials/LlamaCredentialsManager.java b/src/main/java/ee/carlrobert/codegpt/credentials/LlamaCredentialsManager.java new file mode 100644 index 00000000..e4e9c1e8 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/credentials/LlamaCredentialsManager.java @@ -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); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/settings/SettingsConfigurable.java b/src/main/java/ee/carlrobert/codegpt/settings/SettingsConfigurable.java index 21e84e2f..2df7a5f6 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/SettingsConfigurable.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/SettingsConfigurable.java @@ -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()); diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaModelPreferencesForm.java b/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaModelPreferencesForm.java index d951fc1e..8bf3554d 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaModelPreferencesForm.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaModelPreferencesForm.java @@ -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 huggingFaceComboBoxModel; private final JBLabel helpIcon; - private final JBLabel promptTemplateHelpIcon; private final JPanel downloadModelActionLinkWrapper; private final JBLabel progressLabel; private final JBLabel modelDetailsLabel; - private final ComboBox 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("
")); - - new HelpTooltip() - .setTitle(template.toString()) - .setDescription("

" + htmlDescription + "

") - .installOn(promptTemplateHelpIcon); - } - private static class ModelDetails { double fileSize; @@ -537,4 +530,4 @@ public class LlamaModelPreferencesForm { return size + "B"; } } -} +} \ No newline at end of file diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaServerPreferencesForm.java b/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaServerPreferencesForm.java new file mode 100644 index 00000000..089a999f --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaServerPreferencesForm.java @@ -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 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(); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaServiceSelectionForm.java b/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaServiceSelectionForm.java index 5b77d8ad..45c2be14 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaServiceSelectionForm.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/LlamaServiceSelectionForm.java @@ -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 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); - } } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/ServiceSelectionForm.java b/src/main/java/ee/carlrobert/codegpt/settings/service/ServiceSelectionForm.java index 3f77d163..47125ca3 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/service/ServiceSelectionForm.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/ServiceSelectionForm.java @@ -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); } } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/state/LlamaSettingsState.java b/src/main/java/ee/carlrobert/codegpt/settings/state/LlamaSettingsState.java index 434158ac..384f5e39 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/state/LlamaSettingsState.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/state/LlamaSettingsState.java @@ -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 { + 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> extends JPanel { + + private final JBLabel promptTemplateHelpIcon; + protected final ComboBox promptTemplateComboBox; + private final JLabel promptTemplateHelpText; + private final Class enumClass; + + public BasePromptTemplatePanel( + Class 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("
")); + + new HelpTooltip() + .setTitle(template.toString()) + .setDescription("

" + htmlDescription + "

") + .installOn(promptTemplateHelpIcon); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ui/ChatPromptTemplatePanel.java b/src/main/java/ee/carlrobert/codegpt/ui/ChatPromptTemplatePanel.java new file mode 100644 index 00000000..db656350 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ui/ChatPromptTemplatePanel.java @@ -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 { + + 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"))); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ui/InfillPromptTemplatePanel.java b/src/main/java/ee/carlrobert/codegpt/ui/InfillPromptTemplatePanel.java new file mode 100644 index 00000000..66d56e10 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ui/InfillPromptTemplatePanel.java @@ -0,0 +1,21 @@ +package ee.carlrobert.codegpt.ui; + +import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate; + +public class InfillPromptTemplatePanel extends BasePromptTemplatePanel { + + 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"); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ui/UIUtil.java b/src/main/java/ee/carlrobert/codegpt/ui/UIUtil.java index dd1e3803..fc2725ae 100644 --- a/src/main/java/ee/carlrobert/codegpt/ui/UIUtil.java +++ b/src/main/java/ee/carlrobert/codegpt/ui/UIUtil.java @@ -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 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 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 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 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 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 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; } } diff --git a/src/main/resources/messages/codegpt.properties b/src/main/resources/messages/codegpt.properties index 886d36e4..cd1781de 100644 --- a/src/main/resources/messages/codegpt.properties +++ b/src/main/resources/messages/codegpt.properties @@ -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=Additional command-line parameters for the server startup process, separated by commas. See the full list of options.

Example: "--n-gpu-layers, 1, --no-mmap, --mlock"

+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:
%s statusBar.widget.tooltip=Status shared.promptTemplate=Prompt template: +shared.infillPromptTemplate=Infill template: shared.port=Port: codeCompletion.progress.title=Code completion in progress \ No newline at end of file