mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-24 22:16:15 +00:00
feat: add server and build logs for llama.cpp
This commit is contained in:
parent
556089f25e
commit
6cfbd98566
30 changed files with 2231 additions and 1086 deletions
|
|
@ -48,16 +48,9 @@ public class CompletionClientProvider {
|
|||
|
||||
public static LlamaClient getLlamaClient() {
|
||||
var llamaSettings = LlamaSettings.getCurrentState();
|
||||
var builder = new LlamaClient.Builder()
|
||||
.setPort(llamaSettings.getServerPort());
|
||||
if (!llamaSettings.isRunLocalServer()) {
|
||||
builder.setHost(llamaSettings.getBaseHost());
|
||||
String apiKey = getCredential(CredentialKey.LlamaApiKey.INSTANCE);
|
||||
if (apiKey != null && !apiKey.isBlank()) {
|
||||
builder.setApiKey(apiKey);
|
||||
}
|
||||
}
|
||||
return builder.build(getDefaultClientBuilder());
|
||||
return new LlamaClient.Builder()
|
||||
.setPort(llamaSettings.getServerPort())
|
||||
.build(getDefaultClientBuilder());
|
||||
}
|
||||
|
||||
public static OllamaClient getOllamaClient() {
|
||||
|
|
|
|||
|
|
@ -1,254 +0,0 @@
|
|||
package ee.carlrobert.codegpt.completions.llama;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessListener;
|
||||
import com.intellij.execution.process.ProcessOutputType;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
import ee.carlrobert.codegpt.CodeGPTPlugin;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.form.ServerProgressPanel;
|
||||
import ee.carlrobert.codegpt.ui.OverlayUtil;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Service
|
||||
public final class LlamaServerAgent implements Disposable {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(LlamaServerAgent.class);
|
||||
|
||||
private @Nullable OSProcessHandler makeSetupProcessHandler;
|
||||
private @Nullable OSProcessHandler makeBuildProcessHandler;
|
||||
private @Nullable OSProcessHandler startServerProcessHandler;
|
||||
private ServerProgressPanel activeServerProgressPanel;
|
||||
private boolean stoppedByUser;
|
||||
|
||||
public void startAgent(
|
||||
LlamaServerStartupParams params,
|
||||
ServerProgressPanel serverProgressPanel,
|
||||
Runnable onSuccess,
|
||||
Consumer<ServerProgressPanel> onServerStopped) {
|
||||
this.activeServerProgressPanel = serverProgressPanel;
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
try {
|
||||
stoppedByUser = false;
|
||||
serverProgressPanel.displayText(
|
||||
CodeGPTBundle.get("llamaServerAgent.buildingProject.description"));
|
||||
|
||||
makeSetupProcessHandler = new OSProcessHandler(getCMakeSetupCommandLine(params));
|
||||
makeSetupProcessHandler.addProcessListener(new ProcessAdapter() {
|
||||
private final List<String> errorLines = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
|
||||
if (ProcessOutputType.isStderr(outputType)) {
|
||||
errorLines.add(event.getText());
|
||||
return;
|
||||
}
|
||||
LOG.info(event.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(@NotNull ProcessEvent event) {
|
||||
int exitCode = event.getExitCode();
|
||||
LOG.info(format("CMake setup exited with code %d", exitCode));
|
||||
if (stoppedByUser) {
|
||||
onServerStopped.accept(activeServerProgressPanel);
|
||||
return;
|
||||
}
|
||||
if (exitCode != 0) {
|
||||
showServerError(String.join(",", errorLines), onServerStopped);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
makeBuildProcessHandler = new OSProcessHandler(getCMakeBuildCommandLine(params));
|
||||
makeBuildProcessHandler.addProcessListener(
|
||||
getMakeProcessListener(params, onSuccess, onServerStopped));
|
||||
makeBuildProcessHandler.startNotify();
|
||||
} catch (ExecutionException e) {
|
||||
showServerError(e.getMessage(), onServerStopped);
|
||||
}
|
||||
}
|
||||
});
|
||||
makeSetupProcessHandler.startNotify();
|
||||
} catch (ExecutionException e) {
|
||||
showServerError(e.getMessage(), onServerStopped);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void stopAgent() {
|
||||
stoppedByUser = true;
|
||||
if (makeSetupProcessHandler != null) {
|
||||
makeSetupProcessHandler.destroyProcess();
|
||||
}
|
||||
if (startServerProcessHandler != null) {
|
||||
startServerProcessHandler.destroyProcess();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isServerRunning() {
|
||||
return (makeSetupProcessHandler != null
|
||||
&& makeSetupProcessHandler.isStartNotified()
|
||||
&& !makeSetupProcessHandler.isProcessTerminated())
|
||||
|| (startServerProcessHandler != null
|
||||
&& startServerProcessHandler.isStartNotified()
|
||||
&& !startServerProcessHandler.isProcessTerminated());
|
||||
}
|
||||
|
||||
private ProcessListener getMakeProcessListener(
|
||||
LlamaServerStartupParams params,
|
||||
Runnable onSuccess,
|
||||
Consumer<ServerProgressPanel> onServerStopped) {
|
||||
LOG.info("Building llama project");
|
||||
|
||||
return new ProcessAdapter() {
|
||||
|
||||
private final List<String> errorLines = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
|
||||
if (ProcessOutputType.isStderr(outputType)) {
|
||||
errorLines.add(event.getText());
|
||||
return;
|
||||
}
|
||||
LOG.info(event.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(@NotNull ProcessEvent event) {
|
||||
int exitCode = event.getExitCode();
|
||||
LOG.info(format("Server build exited with code %d", exitCode));
|
||||
if (stoppedByUser) {
|
||||
onServerStopped.accept(activeServerProgressPanel);
|
||||
return;
|
||||
}
|
||||
if (exitCode != 0) {
|
||||
showServerError(String.join(",", errorLines), onServerStopped);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LOG.info("Booting up llama server");
|
||||
|
||||
activeServerProgressPanel.displayText(
|
||||
CodeGPTBundle.get("llamaServerAgent.serverBootup.description"));
|
||||
startServerProcessHandler = new OSProcessHandler.Silent(getServerCommandLine(params));
|
||||
startServerProcessHandler.addProcessListener(
|
||||
getProcessListener(params.port(), onSuccess, onServerStopped));
|
||||
startServerProcessHandler.startNotify();
|
||||
} catch (ExecutionException ex) {
|
||||
showServerError(ex.getMessage(), onServerStopped);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ProcessListener getProcessListener(
|
||||
int port,
|
||||
Runnable onSuccess,
|
||||
Consumer<ServerProgressPanel> onServerStopped) {
|
||||
return new ProcessAdapter() {
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final List<String> errorLines = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public void processTerminated(@NotNull ProcessEvent event) {
|
||||
LOG.info(format("Server stopped with code %d", event.getExitCode()));
|
||||
if (stoppedByUser) {
|
||||
onServerStopped.accept(activeServerProgressPanel);
|
||||
} else {
|
||||
showServerError(String.join(",", errorLines), onServerStopped);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
|
||||
LOG.info(event.getText());
|
||||
|
||||
// TODO: Use proper successful boot up validation
|
||||
if (event.getText().contains("server is listening")) {
|
||||
LOG.info("Server up and running!");
|
||||
|
||||
LlamaSettings.getCurrentState().setServerPort(port);
|
||||
onSuccess.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void showServerError(String errorText, Consumer<ServerProgressPanel> onServerStopped) {
|
||||
onServerStopped.accept(activeServerProgressPanel);
|
||||
LOG.info("Unable to start llama server:\n" + errorText);
|
||||
OverlayUtil.showClosableBalloon(errorText, MessageType.ERROR, activeServerProgressPanel);
|
||||
}
|
||||
|
||||
private static GeneralCommandLine getCMakeSetupCommandLine(LlamaServerStartupParams params) {
|
||||
GeneralCommandLine cmakeSetupCommand = new GeneralCommandLine().withCharset(
|
||||
StandardCharsets.UTF_8);
|
||||
cmakeSetupCommand.setExePath("cmake");
|
||||
cmakeSetupCommand.withWorkDirectory(CodeGPTPlugin.getLlamaSourcePath());
|
||||
cmakeSetupCommand.addParameters("-B", "build");
|
||||
cmakeSetupCommand.withEnvironment(params.additionalEnvironmentVariables());
|
||||
cmakeSetupCommand.setRedirectErrorStream(false);
|
||||
return cmakeSetupCommand;
|
||||
}
|
||||
|
||||
private static GeneralCommandLine getCMakeBuildCommandLine(LlamaServerStartupParams params) {
|
||||
GeneralCommandLine cmakeBuildCommand = new GeneralCommandLine().withCharset(
|
||||
StandardCharsets.UTF_8);
|
||||
cmakeBuildCommand.setExePath("cmake");
|
||||
cmakeBuildCommand.withWorkDirectory(CodeGPTPlugin.getLlamaSourcePath());
|
||||
cmakeBuildCommand.addParameters("--build", "build", "--config", "Release", "-j", "4");
|
||||
cmakeBuildCommand.withEnvironment(params.additionalEnvironmentVariables());
|
||||
cmakeBuildCommand.setRedirectErrorStream(false);
|
||||
return cmakeBuildCommand;
|
||||
}
|
||||
|
||||
private GeneralCommandLine getServerCommandLine(LlamaServerStartupParams params) {
|
||||
GeneralCommandLine commandLine = new GeneralCommandLine().withCharset(StandardCharsets.UTF_8);
|
||||
commandLine.setExePath("./build/bin/llama-server");
|
||||
commandLine.withWorkDirectory(CodeGPTPlugin.getLlamaSourcePath());
|
||||
commandLine.addParameters(
|
||||
"-m", params.modelPath(),
|
||||
"-c", String.valueOf(params.contextLength()),
|
||||
"--port", String.valueOf(params.port()),
|
||||
"-t", String.valueOf(params.threads()));
|
||||
commandLine.addParameters(params.additionalRunParameters());
|
||||
commandLine.withEnvironment(params.additionalEnvironmentVariables());
|
||||
commandLine.setRedirectErrorStream(false);
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
public void setActiveServerProgressPanel(
|
||||
ServerProgressPanel activeServerProgressPanel) {
|
||||
this.activeServerProgressPanel = activeServerProgressPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (makeSetupProcessHandler != null && !makeSetupProcessHandler.isProcessTerminated()) {
|
||||
makeSetupProcessHandler.destroyProcess();
|
||||
}
|
||||
if (startServerProcessHandler != null && !startServerProcessHandler.isProcessTerminated()) {
|
||||
startServerProcessHandler.destroyProcess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package ee.carlrobert.codegpt.settings.service.llama;
|
||||
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.LlamaApiKey;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
|
||||
import static org.apache.commons.lang3.SystemUtils.IS_OS_LINUX;
|
||||
import static org.apache.commons.lang3.SystemUtils.IS_OS_MAC_OSX;
|
||||
|
|
@ -13,7 +12,6 @@ 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.PromptTemplate;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.form.LlamaSettingsForm;
|
||||
import java.io.File;
|
||||
|
|
@ -23,7 +21,6 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@State(name = "CodeGPT", storages = @Storage("CodeGPT_LlamaSettings.xml"))
|
||||
|
|
@ -40,17 +37,12 @@ public class LlamaSettings implements PersistentStateComponent<LlamaSettingsStat
|
|||
@Override
|
||||
public void loadState(@NotNull LlamaSettingsState state) {
|
||||
this.state = state;
|
||||
// Catch if model's name has changed which could lead to
|
||||
// HuggingFaceModel or PromptTemplates not being found
|
||||
if (this.state.getHuggingFaceModel() == null) {
|
||||
this.state.setHuggingFaceModel(HuggingFaceModel.CODE_QWEN_2_5_1_5B_Q8_0);
|
||||
}
|
||||
if (this.state.getLocalModelPromptTemplate() == null) {
|
||||
this.state.setLocalModelPromptTemplate(PromptTemplate.CODE_QWEN);
|
||||
}
|
||||
if (this.state.getRemoteModelInfillPromptTemplate() == null) {
|
||||
this.state.setRemoteModelInfillPromptTemplate(InfillPromptTemplate.CODE_QWEN_2_5);
|
||||
}
|
||||
if (this.state.getLocalModelInfillPromptTemplate() == null) {
|
||||
this.state.setLocalModelInfillPromptTemplate(InfillPromptTemplate.CODE_QWEN);
|
||||
}
|
||||
|
|
@ -60,13 +52,10 @@ public class LlamaSettings implements PersistentStateComponent<LlamaSettingsStat
|
|||
return getInstance().getState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Code Completions enabled in settings and a model with InfillPromptTemplate selected.
|
||||
*/
|
||||
public static boolean isCodeCompletionsPossible() {
|
||||
return getInstance().getState().isCodeCompletionsEnabled()
|
||||
&& LlamaModel.findByHuggingFaceModel(getInstance().getState().getHuggingFaceModel())
|
||||
.getInfillPromptTemplate() != null;
|
||||
&& LlamaModel.findByHuggingFaceModel(getInstance().getState().getHuggingFaceModel())
|
||||
.getInfillPromptTemplate() != null;
|
||||
}
|
||||
|
||||
public static LlamaSettings getInstance() {
|
||||
|
|
@ -74,15 +63,12 @@ public class LlamaSettings implements PersistentStateComponent<LlamaSettingsStat
|
|||
}
|
||||
|
||||
public boolean isModified(LlamaSettingsForm form) {
|
||||
return !form.getCurrentState().equals(state)
|
||||
|| !StringUtils.equals(
|
||||
form.getLlamaServerPreferencesForm().getApiKey(),
|
||||
CredentialsStore.getCredential(LlamaApiKey.INSTANCE));
|
||||
return !form.getCurrentState().equals(state);
|
||||
}
|
||||
|
||||
public static boolean isRunnable() {
|
||||
return (IS_OS_MAC_OSX || IS_OS_LINUX)
|
||||
&& GeneralSettings.getCurrentState().getSelectedService() == LLAMA_CPP;
|
||||
&& GeneralSettings.getCurrentState().getSelectedService() == LLAMA_CPP;
|
||||
}
|
||||
|
||||
public static boolean isRunnable(HuggingFaceModel model) {
|
||||
|
|
@ -97,19 +83,18 @@ public class LlamaSettings implements PersistentStateComponent<LlamaSettingsStat
|
|||
return Paths.get(System.getProperty("user.home"), ".codegpt/models/gguf");
|
||||
}
|
||||
|
||||
// Copied from LlamaModelPreferencesForm
|
||||
public String getActualModelPath() {
|
||||
return state.isUseCustomModel()
|
||||
? state.getCustomLlamaModelPath()
|
||||
: getLlamaModelsPath() + File.separator
|
||||
? state.getCustomLlamaModelPath()
|
||||
: getLlamaModelsPath() + File.separator
|
||||
+ state.getHuggingFaceModel().getFileName();
|
||||
}
|
||||
|
||||
public static List<String> getAdditionalParametersList(String additionalParameters) {
|
||||
return Arrays.stream(additionalParameters.split(","))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isBlank())
|
||||
.toList();
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isBlank())
|
||||
.toList();
|
||||
}
|
||||
|
||||
public static Map<String, String> getAdditionalEnvironmentVariablesMap(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package ee.carlrobert.codegpt.settings.service.llama;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfoRt;
|
||||
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate;
|
||||
import ee.carlrobert.codegpt.completions.HuggingFaceModel;
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
|
||||
|
|
@ -10,15 +9,11 @@ import java.util.Objects;
|
|||
|
||||
public class LlamaSettingsState {
|
||||
|
||||
private boolean runLocalServer = SystemInfoRt.isUnix;
|
||||
private boolean useCustomModel;
|
||||
private String customLlamaModelPath = "";
|
||||
private HuggingFaceModel huggingFaceModel = HuggingFaceModel.CODE_QWEN_2_5_1_5B_Q8_0;
|
||||
private PromptTemplate localModelPromptTemplate = PromptTemplate.LLAMA;
|
||||
private PromptTemplate remoteModelPromptTemplate = PromptTemplate.LLAMA;
|
||||
private InfillPromptTemplate localModelInfillPromptTemplate = InfillPromptTemplate.CODE_LLAMA;
|
||||
private InfillPromptTemplate remoteModelInfillPromptTemplate = InfillPromptTemplate.CODE_LLAMA;
|
||||
private String baseHost = "http://localhost:8080";
|
||||
private Integer serverPort = getRandomAvailablePortOrDefault();
|
||||
private int contextSize = 2048;
|
||||
private int threads = 8;
|
||||
|
|
@ -73,39 +68,6 @@ public class LlamaSettingsState {
|
|||
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() {
|
||||
return serverPort;
|
||||
|
|
@ -212,8 +174,7 @@ public class LlamaSettingsState {
|
|||
return false;
|
||||
}
|
||||
LlamaSettingsState that = (LlamaSettingsState) o;
|
||||
return runLocalServer == that.runLocalServer
|
||||
&& useCustomModel == that.useCustomModel
|
||||
return useCustomModel == that.useCustomModel
|
||||
&& contextSize == that.contextSize
|
||||
&& threads == that.threads
|
||||
&& topK == that.topK
|
||||
|
|
@ -223,10 +184,7 @@ public class LlamaSettingsState {
|
|||
&& Objects.equals(customLlamaModelPath, that.customLlamaModelPath)
|
||||
&& huggingFaceModel == that.huggingFaceModel
|
||||
&& localModelPromptTemplate == that.localModelPromptTemplate
|
||||
&& remoteModelPromptTemplate == that.remoteModelPromptTemplate
|
||||
&& localModelInfillPromptTemplate == that.localModelInfillPromptTemplate
|
||||
&& remoteModelInfillPromptTemplate == that.remoteModelInfillPromptTemplate
|
||||
&& Objects.equals(baseHost, that.baseHost)
|
||||
&& Objects.equals(serverPort, that.serverPort)
|
||||
&& Objects.equals(additionalParameters, that.additionalParameters)
|
||||
&& Objects.equals(additionalBuildParameters, that.additionalBuildParameters)
|
||||
|
|
@ -236,9 +194,9 @@ public class LlamaSettingsState {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(runLocalServer, useCustomModel, customLlamaModelPath, huggingFaceModel,
|
||||
localModelPromptTemplate, remoteModelPromptTemplate, localModelInfillPromptTemplate,
|
||||
remoteModelInfillPromptTemplate, baseHost, serverPort, contextSize, threads,
|
||||
return Objects.hash(useCustomModel, customLlamaModelPath, huggingFaceModel,
|
||||
localModelPromptTemplate, localModelInfillPromptTemplate,
|
||||
serverPort, contextSize, threads,
|
||||
additionalParameters, additionalBuildParameters, additionalEnvironmentVariables, topK, topP,
|
||||
minP, repeatPenalty,
|
||||
codeCompletionsEnabled);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import static ee.carlrobert.codegpt.settings.service.llama.LlamaSettings.isModel
|
|||
import static java.lang.String.format;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
import com.intellij.icons.AllIcons.Actions;
|
||||
import com.intellij.icons.AllIcons.General;
|
||||
import com.intellij.ide.HelpTooltip;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
|
|
@ -14,6 +13,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
|||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.TextBrowseFolderListener;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.ui.panel.ComponentPanelBuilder;
|
||||
|
|
@ -34,24 +34,34 @@ import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState;
|
|||
import java.awt.BorderLayout;
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class LlamaModelPreferencesForm {
|
||||
|
||||
private static final String PREDEFINED_MODEL_FORM_CARD_CODE = "PredefinedModelSettings";
|
||||
private static final String CUSTOM_MODEL_FORM_CARD_CODE = "CustomModelSettings";
|
||||
private static final String GROUP_DOWNLOADED = "Downloaded";
|
||||
private static final String GROUP_NOT_DOWNLOADED = "Not Downloaded";
|
||||
|
||||
private static final Map<Integer, Map<Integer, ModelDetails>> modelDetailsMap = Map.of(
|
||||
7, Map.of(
|
||||
3, new ModelDetails(3.30, 5.80),
|
||||
|
|
@ -69,11 +79,11 @@ public class LlamaModelPreferencesForm {
|
|||
private final TextFieldWithBrowseButton browsableCustomModelTextField;
|
||||
private final ComboBox<LlamaModel> modelComboBox;
|
||||
private final ComboBox<ModelSize> modelSizeComboBox;
|
||||
private final ComboBox<HuggingFaceModel> huggingFaceModelComboBox;
|
||||
private final JBLabel modelExistsIcon;
|
||||
private final DefaultComboBoxModel<HuggingFaceModel> huggingFaceComboBoxModel;
|
||||
private final ComboBox<Object> huggingFaceModelComboBox;
|
||||
private final DefaultComboBoxModel<Object> huggingFaceComboBoxModel;
|
||||
private final JBLabel helpIcon;
|
||||
private final JPanel downloadModelActionLinkWrapper;
|
||||
private final JPanel modelActionsWrapper;
|
||||
private final JBLabel progressLabel;
|
||||
private final JBLabel modelDetailsLabel;
|
||||
private final CardLayout cardLayout;
|
||||
|
|
@ -84,59 +94,55 @@ public class LlamaModelPreferencesForm {
|
|||
|
||||
public LlamaModelPreferencesForm() {
|
||||
cardLayout = new CardLayout();
|
||||
progressLabel = new JBLabel("");
|
||||
progressLabel.setBorder(JBUI.Borders.emptyLeft(2));
|
||||
progressLabel.setFont(JBUI.Fonts.smallFont());
|
||||
modelExistsIcon = new JBLabel(Actions.Checked);
|
||||
var llamaSettings = LlamaSettings.getCurrentState();
|
||||
modelExistsIcon.setVisible(isModelExists(llamaSettings.getHuggingFaceModel()));
|
||||
progressLabel = createProgressLabel();
|
||||
helpIcon = new JBLabel(General.ContextHelp);
|
||||
huggingFaceComboBoxModel = new DefaultComboBoxModel<>();
|
||||
|
||||
var llamaSettings = LlamaSettings.getCurrentState();
|
||||
var llm = llamaSettings.getHuggingFaceModel();
|
||||
var llamaModel = LlamaModel.findByHuggingFaceModel(llm);
|
||||
|
||||
var selectableModels = llamaModel.getHuggingFaceModels().stream()
|
||||
.filter(model -> model.getParameterSize() == llm.getParameterSize())
|
||||
.toList();
|
||||
huggingFaceComboBoxModel.addAll(selectableModels);
|
||||
huggingFaceComboBoxModel.setSelectedItem(llm);
|
||||
downloadModelActionLinkWrapper = new JPanel(new BorderLayout());
|
||||
downloadModelActionLinkWrapper.setBorder(JBUI.Borders.emptyLeft(2));
|
||||
downloadModelActionLinkWrapper.add(
|
||||
createDownloadModelLink(
|
||||
progressLabel,
|
||||
downloadModelActionLinkWrapper,
|
||||
huggingFaceComboBoxModel),
|
||||
BorderLayout.WEST);
|
||||
initializeHuggingFaceModel(llamaModel, llm);
|
||||
|
||||
downloadModelActionLinkWrapper = createActionPanel();
|
||||
modelActionsWrapper = createActionPanel();
|
||||
updateModelActionsPanel(llm);
|
||||
|
||||
modelDetailsLabel = new JBLabel();
|
||||
huggingFaceModelComboBox = createModelQuantizationComboBox(huggingFaceComboBoxModel);
|
||||
huggingFaceModelComboBox = createModelQuantizationComboBox();
|
||||
|
||||
var llamaServerAgent = ApplicationManager.getApplication().getService(LlamaServerAgent.class);
|
||||
huggingFaceModelComboBox.setEnabled(!llamaServerAgent.isServerRunning());
|
||||
var serverRunning = llamaServerAgent.isServerRunning();
|
||||
|
||||
huggingFaceModelComboBox.setEnabled(!serverRunning);
|
||||
|
||||
var modelSizeComboBoxModel = new DefaultComboBoxModel<ModelSize>();
|
||||
var modelComboBoxModel = new DefaultComboBoxModel<LlamaModel>();
|
||||
modelComboBoxModel.addAll(LlamaModel.getSorted());
|
||||
var modelComboBoxModel = createLlamaModelComboBoxModel();
|
||||
|
||||
modelComboBox = createModelComboBox(
|
||||
modelComboBoxModel, llamaModel, llm, llamaServerAgent, modelSizeComboBoxModel);
|
||||
modelComboBox.setEnabled(!llamaServerAgent.isServerRunning());
|
||||
modelComboBox.setEnabled(!serverRunning);
|
||||
|
||||
modelSizeComboBox = createModelSizeComboBox(
|
||||
modelComboBoxModel,
|
||||
modelSizeComboBoxModel,
|
||||
llamaServerAgent,
|
||||
huggingFaceComboBoxModel);
|
||||
browsableCustomModelTextField = createBrowsableCustomModelTextField(
|
||||
!llamaServerAgent.isServerRunning());
|
||||
llamaServerAgent);
|
||||
|
||||
browsableCustomModelTextField = createBrowsableCustomModelTextField(!serverRunning);
|
||||
browsableCustomModelTextField.setText(llamaSettings.getCustomLlamaModelPath());
|
||||
|
||||
localPromptTemplatePanel = new ChatPromptTemplatePanel(
|
||||
llamaSettings.getLocalModelPromptTemplate(),
|
||||
!llamaServerAgent.isServerRunning());
|
||||
!serverRunning);
|
||||
|
||||
predefinedModelRadioButton = new JBRadioButton("Use pre-defined model",
|
||||
!llamaSettings.isUseCustomModel());
|
||||
customModelRadioButton = new JBRadioButton("Use custom model",
|
||||
llamaSettings.isUseCustomModel());
|
||||
|
||||
infillPromptTemplatePanel = new InfillPromptTemplatePanel(
|
||||
llamaSettings.getLocalModelInfillPromptTemplate(),
|
||||
!llamaServerAgent.isServerRunning()
|
||||
);
|
||||
!serverRunning);
|
||||
}
|
||||
|
||||
public JPanel getForm() {
|
||||
|
|
@ -164,12 +170,15 @@ public class LlamaModelPreferencesForm {
|
|||
return browsableCustomModelTextField;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ComboBox<HuggingFaceModel> getHuggingFaceModelComboBox() {
|
||||
return huggingFaceModelComboBox;
|
||||
return (ComboBox<HuggingFaceModel>) (ComboBox<?>) huggingFaceModelComboBox;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HuggingFaceModel getSelectedModel() {
|
||||
return (HuggingFaceModel) huggingFaceComboBoxModel.getSelectedItem();
|
||||
var selected = huggingFaceComboBoxModel.getSelectedItem();
|
||||
return selected instanceof HuggingFaceModel ? (HuggingFaceModel) selected : null;
|
||||
}
|
||||
|
||||
public String getCustomLlamaModelPath() {
|
||||
|
|
@ -189,9 +198,40 @@ public class LlamaModelPreferencesForm {
|
|||
}
|
||||
|
||||
public String getActualModelPath() {
|
||||
return isUseCustomLlamaModel()
|
||||
? getCustomLlamaModelPath()
|
||||
: getLlamaModelsPath().resolve(getSelectedModel().getFileName()).toString();
|
||||
if (isUseCustomLlamaModel()) {
|
||||
return getCustomLlamaModelPath();
|
||||
}
|
||||
var selectedModel = getSelectedModel();
|
||||
return selectedModel != null
|
||||
? getLlamaModelsPath().resolve(selectedModel.getFileName()).toString()
|
||||
: "";
|
||||
}
|
||||
|
||||
private JBLabel createProgressLabel() {
|
||||
var label = new JBLabel("");
|
||||
label.setBorder(JBUI.Borders.emptyLeft(4));
|
||||
label.setFont(JBUI.Fonts.smallFont());
|
||||
return label;
|
||||
}
|
||||
|
||||
private JPanel createActionPanel() {
|
||||
var panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(JBUI.Borders.emptyLeft(4));
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void initializeHuggingFaceModel(LlamaModel llamaModel, HuggingFaceModel llm) {
|
||||
var selectableModels = llamaModel.getHuggingFaceModels().stream()
|
||||
.filter(model -> model.getParameterSize() == llm.getParameterSize())
|
||||
.toList();
|
||||
populateModelComboBoxWithGroups(selectableModels);
|
||||
huggingFaceComboBoxModel.setSelectedItem(llm);
|
||||
}
|
||||
|
||||
private DefaultComboBoxModel<LlamaModel> createLlamaModelComboBoxModel() {
|
||||
var model = new DefaultComboBoxModel<LlamaModel>();
|
||||
model.addAll(LlamaModel.getSorted());
|
||||
return model;
|
||||
}
|
||||
|
||||
private JPanel createFormPanelCards() {
|
||||
|
|
@ -199,6 +239,7 @@ public class LlamaModelPreferencesForm {
|
|||
formPanelCards.setBorder(JBUI.Borders.emptyLeft(16));
|
||||
formPanelCards.add(createPredefinedModelForm(), PREDEFINED_MODEL_FORM_CARD_CODE);
|
||||
formPanelCards.add(createCustomModelForm(), CUSTOM_MODEL_FORM_CARD_CODE);
|
||||
|
||||
cardLayout.show(
|
||||
formPanelCards,
|
||||
predefinedModelRadioButton.isSelected()
|
||||
|
|
@ -218,15 +259,27 @@ public class LlamaModelPreferencesForm {
|
|||
buttonGroup.add(predefinedModelRadioButton);
|
||||
buttonGroup.add(customModelRadioButton);
|
||||
|
||||
var predefinedModelHelpText = createHelpText(
|
||||
"settingsConfigurable.service.llama.predefinedModel.comment");
|
||||
var customModelHelpText = createHelpText(
|
||||
"settingsConfigurable.service.llama.customModel.comment");
|
||||
|
||||
var radioPanel = new JPanel();
|
||||
radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.PAGE_AXIS));
|
||||
radioPanel.add(predefinedModelRadioButton);
|
||||
radioPanel.add(Box.createVerticalStrut(4));
|
||||
radioPanel.add(predefinedModelHelpText);
|
||||
radioPanel.add(customModelRadioButton);
|
||||
radioPanel.add(Box.createVerticalStrut(8));
|
||||
radioPanel.add(customModelHelpText);
|
||||
return radioPanel;
|
||||
}
|
||||
|
||||
private Component createHelpText(String bundleKey) {
|
||||
var helpText = ComponentPanelBuilder.createCommentComponent(
|
||||
CodeGPTBundle.get(bundleKey), true);
|
||||
helpText.setBorder(JBUI.Borders.empty(0, 28, 8, 0));
|
||||
return helpText;
|
||||
}
|
||||
|
||||
private JPanel createCustomModelForm() {
|
||||
var customModelHelpText = ComponentPanelBuilder.createCommentComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.customModelPath.comment"),
|
||||
|
|
@ -254,17 +307,8 @@ public class LlamaModelPreferencesForm {
|
|||
true);
|
||||
quantizationHelpText.setBorder(JBUI.Borders.empty(0, 4));
|
||||
|
||||
var modelComboBoxWrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
modelComboBoxWrapper.add(modelComboBox);
|
||||
modelComboBoxWrapper.add(Box.createHorizontalStrut(8));
|
||||
modelComboBoxWrapper.add(helpIcon);
|
||||
modelComboBoxWrapper.add(Box.createHorizontalStrut(4));
|
||||
modelComboBoxWrapper.add(modelExistsIcon);
|
||||
|
||||
var huggingFaceModelComboBoxWrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
huggingFaceModelComboBoxWrapper.add(huggingFaceModelComboBox);
|
||||
huggingFaceModelComboBoxWrapper.add(Box.createHorizontalStrut(8));
|
||||
huggingFaceModelComboBoxWrapper.add(modelDetailsLabel);
|
||||
var modelComboBoxWrapper = createModelComboBoxWrapper();
|
||||
var huggingFaceModelComboBoxWrapper = createHuggingFaceModelComboBoxWrapper();
|
||||
|
||||
return FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent(CodeGPTBundle.get("settingsConfigurable.shared.model.label"),
|
||||
|
|
@ -278,11 +322,28 @@ public class LlamaModelPreferencesForm {
|
|||
.addComponentToRightColumn(quantizationHelpText)
|
||||
.addComponentToRightColumn(downloadModelActionLinkWrapper)
|
||||
.addComponentToRightColumn(progressLabel)
|
||||
.addComponentToRightColumn(modelActionsWrapper)
|
||||
.addVerticalGap(4)
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel();
|
||||
}
|
||||
|
||||
private JPanel createModelComboBoxWrapper() {
|
||||
var wrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
wrapper.add(modelComboBox);
|
||||
wrapper.add(Box.createHorizontalStrut(8));
|
||||
wrapper.add(helpIcon);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private JPanel createHuggingFaceModelComboBoxWrapper() {
|
||||
var wrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
wrapper.add(huggingFaceModelComboBox);
|
||||
wrapper.add(Box.createHorizontalStrut(8));
|
||||
wrapper.add(modelDetailsLabel);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private String getHuggingFaceModelDetailsHtml(HuggingFaceModel model) {
|
||||
int parameterSize = model.getParameterSize();
|
||||
int quantization = model.getQuantization();
|
||||
|
|
@ -312,20 +373,26 @@ public class LlamaModelPreferencesForm {
|
|||
comboBox.setPreferredSize(new Dimension(280, comboBox.getPreferredSize().height));
|
||||
comboBox.setSelectedItem(llamaModel);
|
||||
initializeModelSizes(llamaModel, llm, modelSizeComboBoxModel);
|
||||
comboBox.addItemListener(e -> {
|
||||
var selectedModel = (LlamaModel) e.getItem();
|
||||
var hfm = selectedModel.getLastExistingModelOrFirst();
|
||||
var modelSize = initializeModelSizes(selectedModel, hfm, modelSizeComboBoxModel);
|
||||
var huggingFaceModels = selectedModel.filterSelectedModelsBySize(modelSize);
|
||||
huggingFaceComboBoxModel.removeAllElements();
|
||||
huggingFaceComboBoxModel.addAll(huggingFaceModels);
|
||||
huggingFaceComboBoxModel.setSelectedItem(hfm);
|
||||
modelSizeComboBox.setEnabled(
|
||||
modelSizeComboBox.getModel().getSize() > 1 && !llamaServerAgent.isServerRunning());
|
||||
});
|
||||
|
||||
comboBox.addItemListener(
|
||||
e -> handleModelSelection(e, modelSizeComboBoxModel, llamaServerAgent));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private void handleModelSelection(
|
||||
ItemEvent e,
|
||||
DefaultComboBoxModel<ModelSize> modelSizeComboBoxModel,
|
||||
LlamaServerAgent llamaServerAgent) {
|
||||
var selectedModel = (LlamaModel) e.getItem();
|
||||
var hfm = selectedModel.getLastExistingModelOrFirst();
|
||||
var modelSize = initializeModelSizes(selectedModel, hfm, modelSizeComboBoxModel);
|
||||
var huggingFaceModels = selectedModel.filterSelectedModelsBySize(modelSize);
|
||||
populateModelComboBoxWithGroups(huggingFaceModels);
|
||||
huggingFaceComboBoxModel.setSelectedItem(hfm);
|
||||
modelSizeComboBox.setEnabled(
|
||||
modelSizeComboBox.getModel().getSize() > 1 && !llamaServerAgent.isServerRunning());
|
||||
}
|
||||
|
||||
private static ModelSize initializeModelSizes(
|
||||
LlamaModel llamaModel,
|
||||
HuggingFaceModel hfm,
|
||||
|
|
@ -333,60 +400,98 @@ public class LlamaModelPreferencesForm {
|
|||
var modelSizes = llamaModel.getSortedUniqueModelSizes();
|
||||
modelSizeComboBoxModel.removeAllElements();
|
||||
modelSizeComboBoxModel.addAll(modelSizes);
|
||||
var selectedModelSize = modelSizes.stream()
|
||||
.filter(ms -> ms.size() == hfm.getParameterSize())
|
||||
.findFirst().orElse(modelSizes.get(0));
|
||||
|
||||
var selectedModelSize = findMatchingModelSize(modelSizes, hfm.getParameterSize())
|
||||
.orElse(modelSizes.get(0));
|
||||
|
||||
modelSizeComboBoxModel.setSelectedItem(selectedModelSize);
|
||||
return selectedModelSize;
|
||||
}
|
||||
|
||||
private static Optional<ModelSize> findMatchingModelSize(List<ModelSize> modelSizes,
|
||||
int parameterSize) {
|
||||
return modelSizes.stream()
|
||||
.filter(ms -> ms.size() == parameterSize)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private ComboBox<ModelSize> createModelSizeComboBox(
|
||||
ComboBoxModel<LlamaModel> llamaModelComboBoxModel,
|
||||
DefaultComboBoxModel<ModelSize> modelSizeComboBoxModel,
|
||||
LlamaServerAgent llamaServerAgent,
|
||||
DefaultComboBoxModel<HuggingFaceModel> huggingFaceComboBoxModel) {
|
||||
LlamaServerAgent llamaServerAgent) {
|
||||
var comboBox = new ComboBox<>(modelSizeComboBoxModel);
|
||||
comboBox.setPreferredSize(modelComboBox.getPreferredSize());
|
||||
comboBox.setSelectedItem(modelSizeComboBoxModel.getSelectedItem());
|
||||
comboBox.setEnabled(
|
||||
modelSizeComboBoxModel.getSize() > 1 && !llamaServerAgent.isServerRunning());
|
||||
comboBox.addItemListener(e -> {
|
||||
var selectedModel = (LlamaModel) llamaModelComboBoxModel.getSelectedItem();
|
||||
var models = selectedModel.filterSelectedModelsBySize(
|
||||
(ModelSize) modelSizeComboBoxModel.getSelectedItem());
|
||||
comboBox.setEnabled(
|
||||
modelSizeComboBoxModel.getSize() > 1 && !llamaServerAgent.isServerRunning());
|
||||
if (!models.isEmpty()) {
|
||||
huggingFaceComboBoxModel.removeAllElements();
|
||||
huggingFaceComboBoxModel.addAll(models);
|
||||
huggingFaceComboBoxModel.setSelectedItem(models.get(0));
|
||||
}
|
||||
});
|
||||
|
||||
comboBox.addItemListener(e -> handleModelSizeSelection(
|
||||
e, llamaModelComboBoxModel, modelSizeComboBoxModel, llamaServerAgent));
|
||||
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private ComboBox<HuggingFaceModel> createModelQuantizationComboBox(
|
||||
DefaultComboBoxModel<HuggingFaceModel> huggingFaceComboBoxModel) {
|
||||
private void handleModelSizeSelection(
|
||||
java.awt.event.ItemEvent e,
|
||||
ComboBoxModel<LlamaModel> llamaModelComboBoxModel,
|
||||
DefaultComboBoxModel<ModelSize> modelSizeComboBoxModel,
|
||||
LlamaServerAgent llamaServerAgent) {
|
||||
var selectedModel = (LlamaModel) llamaModelComboBoxModel.getSelectedItem();
|
||||
if (selectedModel == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedSize = (ModelSize) modelSizeComboBoxModel.getSelectedItem();
|
||||
if (selectedSize == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var models = selectedModel.filterSelectedModelsBySize(selectedSize);
|
||||
modelSizeComboBox.setEnabled(
|
||||
modelSizeComboBoxModel.getSize() > 1 && !llamaServerAgent.isServerRunning());
|
||||
|
||||
if (!models.isEmpty()) {
|
||||
populateModelComboBoxWithGroups(models);
|
||||
huggingFaceComboBoxModel.setSelectedItem(models.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
private ComboBox<Object> createModelQuantizationComboBox() {
|
||||
var comboBox = new ComboBox<>(huggingFaceComboBoxModel);
|
||||
updateFromModelState(comboBox.getItem());
|
||||
comboBox.addItemListener(e -> updateFromModelState((HuggingFaceModel) e.getItem()));
|
||||
comboBox.setRenderer(new DefaultListCellRenderer() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
var item = value instanceof HuggingFaceModel hfm ? hfm.getQuantizationLabel() : value;
|
||||
return super.getListCellRendererComponent(list, item, index, isSelected, cellHasFocus);
|
||||
}
|
||||
});
|
||||
var selectedItem = comboBox.getSelectedItem();
|
||||
if (selectedItem instanceof HuggingFaceModel) {
|
||||
updateFromModelState((HuggingFaceModel) selectedItem);
|
||||
}
|
||||
|
||||
comboBox.addItemListener(this::handleQuantizationSelection);
|
||||
comboBox.setRenderer(new ModelQuantizationRenderer());
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private void handleQuantizationSelection(java.awt.event.ItemEvent e) {
|
||||
var item = e.getItem();
|
||||
if (item instanceof HuggingFaceModel hfm) {
|
||||
updateFromModelState(hfm);
|
||||
} else if (item instanceof String) {
|
||||
SwingUtilities.invokeLater(this::selectFirstAvailableModel);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectFirstAvailableModel() {
|
||||
for (int i = 0; i < huggingFaceComboBoxModel.getSize(); i++) {
|
||||
var item = huggingFaceComboBoxModel.getElementAt(i);
|
||||
if (item instanceof HuggingFaceModel) {
|
||||
huggingFaceModelComboBox.setSelectedItem(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFromModelState(HuggingFaceModel selectedModel) {
|
||||
var modelExists = isModelExists(selectedModel);
|
||||
updateModelHelpTooltip(selectedModel);
|
||||
modelDetailsLabel.setText(getHuggingFaceModelDetailsHtml(selectedModel));
|
||||
modelExistsIcon.setVisible(modelExists);
|
||||
downloadModelActionLinkWrapper.setVisible(!modelExists);
|
||||
updateModelActionsPanel(selectedModel);
|
||||
}
|
||||
|
||||
private TextFieldWithBrowseButton createBrowsableCustomModelTextField(boolean enabled) {
|
||||
|
|
@ -403,7 +508,6 @@ public class LlamaModelPreferencesForm {
|
|||
private AnActionLink createCancelDownloadLink(
|
||||
JBLabel progressLabel,
|
||||
JPanel actionLinkWrapper,
|
||||
DefaultComboBoxModel<HuggingFaceModel> huggingFaceComboBoxModel,
|
||||
ProgressIndicator progressIndicator) {
|
||||
return new AnActionLink(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.cancelDownloadLink.label"),
|
||||
|
|
@ -414,10 +518,7 @@ public class LlamaModelPreferencesForm {
|
|||
configureFieldsForDownloading(false);
|
||||
updateActionLink(
|
||||
actionLinkWrapper,
|
||||
createDownloadModelLink(
|
||||
progressLabel,
|
||||
actionLinkWrapper,
|
||||
huggingFaceComboBoxModel));
|
||||
createDownloadModelLink(progressLabel, actionLinkWrapper));
|
||||
progressIndicator.cancel();
|
||||
});
|
||||
}
|
||||
|
|
@ -426,7 +527,11 @@ public class LlamaModelPreferencesForm {
|
|||
|
||||
private void updateActionLink(JPanel actionLinkWrapper, AnActionLink actionLink) {
|
||||
actionLinkWrapper.removeAll();
|
||||
actionLinkWrapper.add(actionLink, BorderLayout.WEST);
|
||||
var flowPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
flowPanel.add(actionLink);
|
||||
flowPanel.add(Box.createHorizontalStrut(16));
|
||||
flowPanel.add(createOpenFolderLink());
|
||||
actionLinkWrapper.add(flowPanel, BorderLayout.WEST);
|
||||
actionLinkWrapper.revalidate();
|
||||
actionLinkWrapper.repaint();
|
||||
}
|
||||
|
|
@ -437,13 +542,11 @@ public class LlamaModelPreferencesForm {
|
|||
modelComboBox.setEnabled(!downloading);
|
||||
modelSizeComboBox.setEnabled(!downloading);
|
||||
huggingFaceModelComboBox.setEnabled(!downloading);
|
||||
modelExistsIcon.setVisible(!downloading);
|
||||
}
|
||||
|
||||
private AnActionLink createDownloadModelLink(
|
||||
JBLabel progressLabel,
|
||||
JPanel actionLinkWrapper,
|
||||
DefaultComboBoxModel<HuggingFaceModel> huggingFaceComboBoxModel) {
|
||||
JPanel actionLinkWrapper) {
|
||||
return new AnActionLink(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.downloadModelLink.label"),
|
||||
new DownloadModelAction(
|
||||
|
|
@ -451,29 +554,26 @@ public class LlamaModelPreferencesForm {
|
|||
configureFieldsForDownloading(true);
|
||||
updateActionLink(
|
||||
actionLinkWrapper,
|
||||
createCancelDownloadLink(
|
||||
progressLabel,
|
||||
actionLinkWrapper,
|
||||
huggingFaceComboBoxModel,
|
||||
progressIndicator));
|
||||
createCancelDownloadLink(progressLabel, actionLinkWrapper, progressIndicator));
|
||||
}),
|
||||
() -> SwingUtilities.invokeLater(() -> {
|
||||
configureFieldsForDownloading(false);
|
||||
updateActionLink(
|
||||
actionLinkWrapper,
|
||||
createDownloadModelLink(
|
||||
progressLabel,
|
||||
actionLinkWrapper,
|
||||
huggingFaceComboBoxModel));
|
||||
actionLinkWrapper.setVisible(false);
|
||||
LlamaSettings.getCurrentState().setHuggingFaceModel(
|
||||
(HuggingFaceModel) huggingFaceComboBoxModel.getSelectedItem());
|
||||
var downloadedModel = getSelectedModel();
|
||||
if (downloadedModel != null) {
|
||||
LlamaSettings.getCurrentState().setHuggingFaceModel(downloadedModel);
|
||||
updateFromModelState(downloadedModel);
|
||||
}
|
||||
}),
|
||||
(error) -> {
|
||||
throw new RuntimeException(error);
|
||||
},
|
||||
(text) -> SwingUtilities.invokeLater(() -> progressLabel.setText(text)),
|
||||
huggingFaceComboBoxModel), "unknown");
|
||||
getHuggingFaceComboBoxModel()), "unknown");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DefaultComboBoxModel<HuggingFaceModel> getHuggingFaceComboBoxModel() {
|
||||
return (DefaultComboBoxModel<HuggingFaceModel>) (DefaultComboBoxModel<?>) huggingFaceComboBoxModel;
|
||||
}
|
||||
|
||||
private void updateModelHelpTooltip(HuggingFaceModel model) {
|
||||
|
|
@ -488,6 +588,131 @@ public class LlamaModelPreferencesForm {
|
|||
.installOn(helpIcon);
|
||||
}
|
||||
|
||||
private record ModelDetails(double fileSize, double maxRAMRequired) {
|
||||
private void populateModelComboBoxWithGroups(List<HuggingFaceModel> models) {
|
||||
huggingFaceComboBoxModel.removeAllElements();
|
||||
|
||||
var downloadedModels = models.stream()
|
||||
.filter(LlamaSettings::isModelExists)
|
||||
.toList();
|
||||
var notDownloadedModels = models.stream()
|
||||
.filter(model -> !isModelExists(model))
|
||||
.toList();
|
||||
|
||||
if (!downloadedModels.isEmpty()) {
|
||||
huggingFaceComboBoxModel.addElement(GROUP_DOWNLOADED);
|
||||
downloadedModels.forEach(huggingFaceComboBoxModel::addElement);
|
||||
}
|
||||
|
||||
if (!notDownloadedModels.isEmpty()) {
|
||||
huggingFaceComboBoxModel.addElement(GROUP_NOT_DOWNLOADED);
|
||||
notDownloadedModels.forEach(huggingFaceComboBoxModel::addElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateModelActionsPanel(HuggingFaceModel model) {
|
||||
modelActionsWrapper.removeAll();
|
||||
downloadModelActionLinkWrapper.removeAll();
|
||||
|
||||
var flowPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
if (isModelExists(model)) {
|
||||
flowPanel.add(createDeleteModelLink(model));
|
||||
} else {
|
||||
flowPanel.add(createDownloadModelLink(progressLabel, downloadModelActionLinkWrapper));
|
||||
}
|
||||
flowPanel.add(Box.createHorizontalStrut(16));
|
||||
flowPanel.add(createOpenFolderLink());
|
||||
|
||||
downloadModelActionLinkWrapper.setVisible(false);
|
||||
modelActionsWrapper.setVisible(true);
|
||||
modelActionsWrapper.add(flowPanel, BorderLayout.WEST);
|
||||
|
||||
modelActionsWrapper.revalidate();
|
||||
modelActionsWrapper.repaint();
|
||||
downloadModelActionLinkWrapper.revalidate();
|
||||
downloadModelActionLinkWrapper.repaint();
|
||||
}
|
||||
|
||||
private AnActionLink createDeleteModelLink(HuggingFaceModel model) {
|
||||
return new AnActionLink("Delete Model", new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
var modelName = model.getFileName();
|
||||
var result = Messages.showYesNoDialog(
|
||||
"Are you sure you want to delete the model '" + modelName + "'?",
|
||||
"Delete Model",
|
||||
Messages.getQuestionIcon()
|
||||
);
|
||||
|
||||
if (result == Messages.YES) {
|
||||
var modelFile = getLlamaModelsPath().resolve(modelName).toFile();
|
||||
if (modelFile.exists() && modelFile.delete()) {
|
||||
updateFromModelState(model);
|
||||
Messages.showInfoMessage("Model '" + modelName + "' has been deleted.",
|
||||
"Model Deleted");
|
||||
} else {
|
||||
Messages.showErrorDialog("Failed to delete the model file.", "Delete Failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private AnActionLink createOpenFolderLink() {
|
||||
return new AnActionLink("Open in Folder", new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
try {
|
||||
var modelsPath = getLlamaModelsPath().toFile();
|
||||
if (!modelsPath.exists() && !modelsPath.mkdirs()) {
|
||||
Messages.showErrorDialog("Failed to create models directory.", "Error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Desktop.isDesktopSupported()) {
|
||||
Desktop.getDesktop().open(modelsPath);
|
||||
} else {
|
||||
Messages.showErrorDialog("Desktop operations are not supported on this system.",
|
||||
"Error");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Messages.showErrorDialog("Failed to open the models folder: " + ex.getMessage(), "Error");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class ModelQuantizationRenderer extends DefaultListCellRenderer {
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
if (value instanceof String groupHeader) {
|
||||
var label = (JLabel) super.getListCellRendererComponent(list, groupHeader, index, false,
|
||||
false);
|
||||
label.setFont(label.getFont().deriveFont(java.awt.Font.BOLD));
|
||||
label.setEnabled(false);
|
||||
if (index > 0) {
|
||||
label.setBorder(JBUI.Borders.compound(
|
||||
JBUI.Borders.customLine(JBUI.CurrentTheme.Popup.separatorColor(), 1, 0, 0, 0),
|
||||
JBUI.Borders.empty(4, 4)
|
||||
));
|
||||
} else {
|
||||
label.setBorder(JBUI.Borders.empty(4, 4));
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
if (value instanceof HuggingFaceModel hfm) {
|
||||
var item = hfm.getQuantizationLabel();
|
||||
return super.getListCellRendererComponent(list, item, index, isSelected, cellHasFocus);
|
||||
}
|
||||
|
||||
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
}
|
||||
}
|
||||
|
||||
private record ModelDetails(double fileSize, double maxRAMRequired) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
package ee.carlrobert.codegpt.settings.service.llama.form;
|
||||
|
||||
import com.intellij.openapi.ui.panel.ComponentPanelBuilder;
|
||||
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.settings.service.llama.LlamaSettingsState;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class LlamaRequestPreferencesForm {
|
||||
|
||||
private final IntegerField topKField;
|
||||
private final JBTextField topPField;
|
||||
private final JBTextField minPField;
|
||||
private final JBTextField repeatPenaltyField;
|
||||
|
||||
public LlamaRequestPreferencesForm(LlamaSettingsState llamaSettings) {
|
||||
topKField = new IntegerField();
|
||||
topKField.setColumns(12);
|
||||
topKField.setValue(llamaSettings.getTopK());
|
||||
topPField = new JBTextField(12);
|
||||
topPField.setText(String.valueOf(llamaSettings.getTopP()));
|
||||
minPField = new JBTextField(12);
|
||||
minPField.setText(String.valueOf(llamaSettings.getMinP()));
|
||||
repeatPenaltyField = new JBTextField(12);
|
||||
repeatPenaltyField.setText(String.valueOf(llamaSettings.getRepeatPenalty()));
|
||||
}
|
||||
|
||||
public JPanel getForm() {
|
||||
return FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.topK.label"),
|
||||
topKField)
|
||||
.addComponentToRightColumn(
|
||||
createComment("settingsConfigurable.service.llama.topK.comment"))
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.topP.label"),
|
||||
topPField)
|
||||
.addComponentToRightColumn(
|
||||
createComment("settingsConfigurable.service.llama.topP.comment"))
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.minP.label"),
|
||||
minPField)
|
||||
.addComponentToRightColumn(
|
||||
createComment("settingsConfigurable.service.llama.minP.comment"))
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.repeatPenalty.label"),
|
||||
repeatPenaltyField)
|
||||
.addComponentToRightColumn(
|
||||
createComment("settingsConfigurable.service.llama.repeatPenalty.comment"))
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel();
|
||||
}
|
||||
|
||||
public void resetForm(LlamaSettingsState state) {
|
||||
topKField.setValue(state.getTopK());
|
||||
topPField.setText(String.valueOf((state.getTopP())));
|
||||
minPField.setText(String.valueOf((state.getMinP())));
|
||||
repeatPenaltyField.setText(String.valueOf((state.getRepeatPenalty())));
|
||||
}
|
||||
|
||||
public int getTopK() {
|
||||
return topKField.getValue();
|
||||
}
|
||||
|
||||
public double getTopP() {
|
||||
return Double.parseDouble(topPField.getText());
|
||||
}
|
||||
|
||||
public double getMinP() {
|
||||
return Double.parseDouble(minPField.getText());
|
||||
}
|
||||
|
||||
public double getRepeatPenalty() {
|
||||
return Double.parseDouble(repeatPenaltyField.getText());
|
||||
}
|
||||
|
||||
private JLabel createComment(String messageKey) {
|
||||
var comment = ComponentPanelBuilder.createCommentComponent(
|
||||
CodeGPTBundle.get(messageKey), true);
|
||||
comment.setBorder(JBUI.Borders.empty(0, 4));
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,404 +0,0 @@
|
|||
package ee.carlrobert.codegpt.settings.service.llama.form;
|
||||
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.LlamaApiKey;
|
||||
import static ee.carlrobert.codegpt.settings.service.llama.LlamaSettings.isModelExists;
|
||||
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 com.intellij.icons.AllIcons.Actions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.SystemInfoRt;
|
||||
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.codecompletions.InfillPromptTemplate;
|
||||
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.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState;
|
||||
import ee.carlrobert.codegpt.ui.OverlayUtil;
|
||||
import ee.carlrobert.codegpt.ui.UIUtil;
|
||||
import ee.carlrobert.codegpt.ui.UIUtil.RadioButtonWithLayout;
|
||||
import ee.carlrobert.codegpt.ui.URLTextField;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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 JBTextField additionalBuildParametersField;
|
||||
private final JBTextField additionalEnvironmentVariablesField;
|
||||
private final ChatPromptTemplatePanel remotePromptTemplatePanel;
|
||||
private final InfillPromptTemplatePanel infillPromptTemplatePanel;
|
||||
|
||||
public LlamaServerPreferencesForm(LlamaSettingsState settings) {
|
||||
var llamaServerAgent = ApplicationManager.getApplication().getService(LlamaServerAgent.class);
|
||||
var serverRunning = llamaServerAgent.isServerRunning();
|
||||
portField = new PortField(settings.getServerPort());
|
||||
portField.setEnabled(!serverRunning);
|
||||
|
||||
maxTokensField = new IntegerField("max_tokens", 256, 4096);
|
||||
maxTokensField.setColumns(12);
|
||||
maxTokensField.setValue(settings.getContextSize());
|
||||
maxTokensField.setEnabled(!serverRunning);
|
||||
|
||||
threadsField = new IntegerField("threads", 1, 256);
|
||||
threadsField.setColumns(12);
|
||||
threadsField.setValue(settings.getThreads());
|
||||
threadsField.setEnabled(!serverRunning);
|
||||
|
||||
additionalParametersField = new JBTextField(settings.getAdditionalParameters(), 30);
|
||||
additionalParametersField.setEnabled(!serverRunning);
|
||||
|
||||
additionalBuildParametersField = new JBTextField(settings.getAdditionalBuildParameters(), 30);
|
||||
additionalBuildParametersField.setEnabled(!serverRunning);
|
||||
|
||||
additionalEnvironmentVariablesField = new JBTextField(
|
||||
settings.getAdditionalEnvironmentVariables(), 30);
|
||||
additionalEnvironmentVariablesField.setEnabled(!serverRunning);
|
||||
|
||||
baseHostField = new URLTextField(settings.getBaseHost(), 30);
|
||||
apiKeyField = new JBPasswordField();
|
||||
apiKeyField.setColumns(30);
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
var apiKey = CredentialsStore.getCredential(CredentialKey.LlamaApiKey.INSTANCE);
|
||||
SwingUtilities.invokeLater(() -> apiKeyField.setText(apiKey));
|
||||
});
|
||||
|
||||
llamaModelPreferencesForm = new LlamaModelPreferencesForm();
|
||||
runLocalServerRadioButton = new JBRadioButton("Run local server",
|
||||
settings.isRunLocalServer());
|
||||
useExistingServerRadioButton = new JBRadioButton("Use remote server",
|
||||
!settings.isRunLocalServer());
|
||||
|
||||
runLocalServerRadioButton.setEnabled(SystemInfoRt.isUnix);
|
||||
runLocalServerRadioButton.setVisible(SystemInfoRt.isUnix);
|
||||
|
||||
remotePromptTemplatePanel = new ChatPromptTemplatePanel(
|
||||
settings.getRemoteModelPromptTemplate(), true);
|
||||
infillPromptTemplatePanel = new InfillPromptTemplatePanel(
|
||||
settings.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())
|
||||
), SystemInfoRt.isUnix ? (runLocalServerRadioButton.isSelected()
|
||||
? RUN_LOCAL_SERVER_FORM_CARD_CODE
|
||||
: USE_EXISTING_SERVER_FORM_CARD_CODE) : USE_EXISTING_SERVER_FORM_CARD_CODE);
|
||||
}
|
||||
|
||||
public void resetForm(LlamaSettingsState state) {
|
||||
llamaModelPreferencesForm.resetForm(state);
|
||||
|
||||
remotePromptTemplatePanel.setPromptTemplate(state.getLocalModelPromptTemplate()); // ?
|
||||
infillPromptTemplatePanel.setPromptTemplate(state.getLocalModelInfillPromptTemplate());
|
||||
runLocalServerRadioButton.setSelected(state.isRunLocalServer());
|
||||
baseHostField.setText(state.getBaseHost());
|
||||
portField.setNumber(state.getServerPort());
|
||||
maxTokensField.setValue(state.getContextSize());
|
||||
threadsField.setValue(state.getThreads());
|
||||
additionalParametersField.setText(state.getAdditionalParameters());
|
||||
additionalBuildParametersField.setText(state.getAdditionalBuildParameters());
|
||||
additionalEnvironmentVariablesField.setText(state.getAdditionalEnvironmentVariables());
|
||||
remotePromptTemplatePanel.setPromptTemplate(state.getRemoteModelPromptTemplate()); // ?
|
||||
infillPromptTemplatePanel.setPromptTemplate(state.getRemoteModelInfillPromptTemplate());
|
||||
apiKeyField.setText(CredentialsStore.getCredential(LlamaApiKey.INSTANCE));
|
||||
}
|
||||
|
||||
public JComponent createUseExistingServerForm() {
|
||||
var apiKeyFieldPanel = UI.PanelFactory.panel(apiKeyField)
|
||||
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
|
||||
.resizeX(false)
|
||||
.withComment(
|
||||
CodeGPTBundle.get("settingsConfigurable.shared.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"))
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get(
|
||||
"settingsConfigurable.service.llama.additionalBuildParameters.label"),
|
||||
additionalBuildParametersField)
|
||||
.addComponentToRightColumn(
|
||||
createComment(
|
||||
"settingsConfigurable.service.llama.additionalBuildParameters.comment"))
|
||||
.addVerticalGap(4)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get(
|
||||
"settingsConfigurable.service.llama.additionalEnvironmentVariables.label"),
|
||||
additionalEnvironmentVariablesField)
|
||||
.addComponentToRightColumn(
|
||||
createComment(
|
||||
"settingsConfigurable.service.llama.additionalEnvironmentVariables.comment"))
|
||||
.addVerticalGap(4)
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel()))
|
||||
.getPanel());
|
||||
}
|
||||
|
||||
private JButton getServerButton(
|
||||
LlamaServerAgent llamaServerAgent,
|
||||
ServerProgressPanel serverProgressPanel) {
|
||||
llamaServerAgent.setActiveServerProgressPanel(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(),
|
||||
getListOfAdditionalBuildParameters(),
|
||||
getMapOfAdditionalEnvironmentVariables()
|
||||
),
|
||||
serverProgressPanel,
|
||||
() -> {
|
||||
setFormEnabled(false);
|
||||
serverProgressPanel.displayComponent(new JBLabel(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.serverRunning"),
|
||||
Actions.Checked,
|
||||
SwingConstants.LEADING));
|
||||
},
|
||||
(activeServerProgressPanel) -> {
|
||||
setFormEnabled(true);
|
||||
serverButton.setText(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
|
||||
serverButton.setIcon(Actions.Execute);
|
||||
activeServerProgressPanel.displayComponent(new JBLabel(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.progress.serverStopped"),
|
||||
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.displayText(
|
||||
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.displayText(
|
||||
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);
|
||||
additionalBuildParametersField.setEnabled(enabled);
|
||||
additionalEnvironmentVariablesField.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public boolean isRunLocalServer() {
|
||||
return runLocalServerRadioButton.isSelected();
|
||||
}
|
||||
|
||||
public String getBaseHost() {
|
||||
return baseHostField.getText();
|
||||
}
|
||||
|
||||
public int getServerPort() {
|
||||
return portField.getNumber();
|
||||
}
|
||||
|
||||
public LlamaModelPreferencesForm getLlamaModelPreferencesForm() {
|
||||
return llamaModelPreferencesForm;
|
||||
}
|
||||
|
||||
public int getContextSize() {
|
||||
return maxTokensField.getValue();
|
||||
}
|
||||
|
||||
public void setThreads(int threads) {
|
||||
threadsField.setValue(threads);
|
||||
}
|
||||
|
||||
public int getThreads() {
|
||||
return threadsField.getValue();
|
||||
}
|
||||
|
||||
public String getAdditionalParameters() {
|
||||
return additionalParametersField.getText();
|
||||
}
|
||||
|
||||
public List<String> getListOfAdditionalParameters() {
|
||||
return LlamaSettings.getAdditionalParametersList(additionalParametersField.getText());
|
||||
}
|
||||
|
||||
public String getAdditionalBuildParameters() {
|
||||
return additionalBuildParametersField.getText();
|
||||
}
|
||||
|
||||
public List<String> getListOfAdditionalBuildParameters() {
|
||||
return LlamaSettings.getAdditionalParametersList(additionalBuildParametersField.getText());
|
||||
}
|
||||
|
||||
public String getAdditionalEnvironmentVariables() {
|
||||
return additionalEnvironmentVariablesField.getText();
|
||||
}
|
||||
|
||||
public Map<String, String> getMapOfAdditionalEnvironmentVariables() {
|
||||
return LlamaSettings.getAdditionalEnvironmentVariablesMap(
|
||||
additionalEnvironmentVariablesField.getText());
|
||||
}
|
||||
|
||||
public PromptTemplate getPromptTemplate() {
|
||||
var template = isRunLocalServer() ? llamaModelPreferencesForm.getPromptTemplate()
|
||||
: remotePromptTemplatePanel.getPromptTemplate();
|
||||
return template == null ? PromptTemplate.CODE_QWEN : template;
|
||||
}
|
||||
|
||||
public @Nullable String getApiKey() {
|
||||
var apiKey = new String(apiKeyField.getPassword());
|
||||
return apiKey.isEmpty() ? null : apiKey;
|
||||
}
|
||||
|
||||
public InfillPromptTemplate getInfillPromptTemplate() {
|
||||
return infillPromptTemplatePanel.getPromptTemplate();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,83 +1,456 @@
|
|||
package ee.carlrobert.codegpt.settings.service.llama.form;
|
||||
|
||||
import static ee.carlrobert.codegpt.ui.UIUtil.createComment;
|
||||
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
|
||||
|
||||
import com.intellij.ui.TitledSeparator;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.PortField;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.JBTabbedPane;
|
||||
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.AsyncProcessIcon;
|
||||
import com.intellij.util.ui.components.BorderLayoutPanel;
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
import ee.carlrobert.codegpt.settings.service.CodeCompletionConfigurationForm;
|
||||
import ee.carlrobert.codegpt.completions.llama.LlamaServerAgent;
|
||||
import ee.carlrobert.codegpt.completions.llama.LlamaServerStartupParams;
|
||||
import ee.carlrobert.codegpt.completions.llama.SimpleConsolePanel;
|
||||
import ee.carlrobert.codegpt.completions.llama.logging.SettingsFormLoggingStrategy;
|
||||
import ee.carlrobert.codegpt.services.llama.ServerLogsManager;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.FlowLayout;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class LlamaSettingsForm extends JPanel {
|
||||
|
||||
private final LlamaServerPreferencesForm llamaServerPreferencesForm;
|
||||
private final LlamaRequestPreferencesForm llamaRequestPreferencesForm;
|
||||
private final CodeCompletionConfigurationForm codeCompletionConfigurationForm;
|
||||
private static final int SERVER_CONFIG_TAB = 0;
|
||||
private static final int SERVER_LOGS_TAB = 1;
|
||||
private static final int BUILD_OUTPUT_TAB = 2;
|
||||
private static final String SERVER_LOGS_DISABLED_TOOLTIP = "Server must be running to view logs";
|
||||
private static final String BUILD_OUTPUT_DISABLED_TOOLTIP = "Available during build process";
|
||||
|
||||
public LlamaSettingsForm(LlamaSettingsState settings) {
|
||||
llamaServerPreferencesForm = new LlamaServerPreferencesForm(settings);
|
||||
llamaRequestPreferencesForm = new LlamaRequestPreferencesForm(settings);
|
||||
codeCompletionConfigurationForm = new CodeCompletionConfigurationForm(
|
||||
settings.isCodeCompletionsEnabled(),
|
||||
null,
|
||||
null);
|
||||
init();
|
||||
private final LlamaServerAgent serverAgent;
|
||||
private final LlamaSettingsState settingsState;
|
||||
|
||||
private final JBTabbedPane tabbedPane;
|
||||
private final LlamaServerPreferencesForm serverPreferencesForm;
|
||||
private final SimpleConsolePanel serverLogsConsole;
|
||||
private final SimpleConsolePanel buildLogsConsole;
|
||||
private final JPanel serverStatusPanel;
|
||||
private final JBLabel serverStatusLabel;
|
||||
private final AsyncProcessIcon serverStatusSpinner;
|
||||
|
||||
public LlamaSettingsForm(LlamaSettingsState settingsState) {
|
||||
this.settingsState = settingsState;
|
||||
serverAgent = ApplicationManager.getApplication().getService(LlamaServerAgent.class);
|
||||
tabbedPane = new JBTabbedPane();
|
||||
serverStatusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
|
||||
serverStatusLabel = new JBLabel();
|
||||
serverStatusSpinner = new AsyncProcessIcon("server_status_spinner");
|
||||
serverStatusPanel.add(serverStatusSpinner);
|
||||
serverStatusPanel.add(Box.createHorizontalStrut(4));
|
||||
serverStatusPanel.add(serverStatusLabel);
|
||||
serverStatusSpinner.setVisible(false);
|
||||
serverPreferencesForm = new LlamaServerPreferencesForm(settingsState, this);
|
||||
serverLogsConsole = new SimpleConsolePanel();
|
||||
buildLogsConsole = new SimpleConsolePanel();
|
||||
|
||||
updateServerStatus();
|
||||
loadExistingLogs();
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
add(createLocalServerPanel(), BorderLayout.CENTER);
|
||||
|
||||
serverAgent.setSettingsForm(this);
|
||||
}
|
||||
|
||||
private JPanel createLocalServerPanel() {
|
||||
var panel = new BorderLayoutPanel();
|
||||
var modelPreferencesForm = serverPreferencesForm.getLlamaModelPreferencesForm();
|
||||
var modelPanel = new BorderLayoutPanel();
|
||||
modelPanel.add(modelPreferencesForm.getForm(), BorderLayout.CENTER);
|
||||
modelPanel.setBorder(JBUI.Borders.emptyBottom(8));
|
||||
panel.add(modelPanel, BorderLayout.NORTH);
|
||||
|
||||
var serverConfigTab = createServerConfigurationTab();
|
||||
tabbedPane.addTab(CodeGPTBundle.get("llama.ui.tab.serverConfiguration"), AllIcons.General.Settings, serverConfigTab);
|
||||
|
||||
var serverLogsTab = createServerLogsTab();
|
||||
tabbedPane.addTab(CodeGPTBundle.get("llama.ui.tab.serverLogs"), AllIcons.Debugger.Console, serverLogsTab);
|
||||
|
||||
var buildLogsTab = createBuildLogsTab();
|
||||
tabbedPane.addTab(CodeGPTBundle.get("llama.ui.tab.buildOutput"), AllIcons.Actions.Compile, buildLogsTab);
|
||||
|
||||
tabbedPane.addChangeListener(e -> {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
int selectedIndex = tabbedPane.getSelectedIndex();
|
||||
if (selectedIndex == 1) {
|
||||
serverLogsConsole.revalidate();
|
||||
serverLogsConsole.repaint();
|
||||
} else if (selectedIndex == 2) {
|
||||
buildLogsConsole.revalidate();
|
||||
buildLogsConsole.repaint();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
panel.add(tabbedPane, BorderLayout.CENTER);
|
||||
|
||||
setTabState(SERVER_LOGS_TAB, serverAgent.isServerRunning(), SERVER_LOGS_DISABLED_TOOLTIP);
|
||||
setTabState(BUILD_OUTPUT_TAB, serverAgent.isBuildInProgress(), BUILD_OUTPUT_DISABLED_TOOLTIP);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel createServerConfigurationTab() {
|
||||
var serverRunning = serverAgent.isServerRunning();
|
||||
|
||||
var portField = new PortField(serverPreferencesForm.getServerPort());
|
||||
portField.setEnabled(!serverRunning);
|
||||
|
||||
var contextSizeField = new IntegerField("context_size", 256, 4096);
|
||||
contextSizeField.setColumns(12);
|
||||
contextSizeField.setValue(serverPreferencesForm.getContextSize());
|
||||
contextSizeField.setEnabled(!serverRunning);
|
||||
|
||||
var threadsField = new IntegerField("threads", 1, 256);
|
||||
threadsField.setColumns(12);
|
||||
threadsField.setValue(serverPreferencesForm.getThreads());
|
||||
threadsField.setEnabled(!serverRunning);
|
||||
|
||||
var additionalParametersField = new JBTextField(serverPreferencesForm.getAdditionalParameters(),
|
||||
30);
|
||||
additionalParametersField.setEnabled(!serverRunning);
|
||||
|
||||
var additionalBuildParametersField = new JBTextField(
|
||||
serverPreferencesForm.getAdditionalBuildParameters(), 30);
|
||||
additionalBuildParametersField.setEnabled(!serverRunning);
|
||||
|
||||
var additionalEnvironmentVariablesField = new JBTextField(
|
||||
serverPreferencesForm.getAdditionalEnvironmentVariables(), 30);
|
||||
additionalEnvironmentVariablesField.setEnabled(!serverRunning);
|
||||
|
||||
var config = new ServerButtonConfig(
|
||||
portField,
|
||||
contextSizeField,
|
||||
threadsField,
|
||||
additionalParametersField,
|
||||
additionalBuildParametersField,
|
||||
additionalEnvironmentVariablesField
|
||||
);
|
||||
|
||||
var serverButton = createServerButton(config);
|
||||
|
||||
var portPanel = new JPanel();
|
||||
portPanel.setLayout(new BoxLayout(portPanel, BoxLayout.X_AXIS));
|
||||
portPanel.add(portField);
|
||||
portPanel.add(Box.createHorizontalGlue());
|
||||
portPanel.add(serverButton);
|
||||
|
||||
var form = withEmptyLeftBorder(FormBuilder.createFormBuilder()
|
||||
.addVerticalGap(8)
|
||||
.addLabeledComponent(CodeGPTBundle.get("shared.port"), portPanel)
|
||||
.addVerticalGap(8)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.contextSize.label"),
|
||||
contextSizeField)
|
||||
.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"))
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.additionalBuildParameters.label"),
|
||||
additionalBuildParametersField)
|
||||
.addComponentToRightColumn(
|
||||
createComment("settingsConfigurable.service.llama.additionalBuildParameters.comment"))
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get(
|
||||
"settingsConfigurable.service.llama.additionalEnvironmentVariables.label"),
|
||||
additionalEnvironmentVariablesField)
|
||||
.addComponentToRightColumn(
|
||||
createComment(
|
||||
"settingsConfigurable.service.llama.additionalEnvironmentVariables.comment"))
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel());
|
||||
|
||||
var panel = new JPanel(new BorderLayout());
|
||||
panel.add(form, BorderLayout.CENTER);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JButton createServerButton(ServerButtonConfig config) {
|
||||
var serverRunning = serverAgent.isServerRunning();
|
||||
var buildInProgress = serverAgent.isBuildInProgress();
|
||||
var serverButton = new JButton();
|
||||
|
||||
if (serverRunning) {
|
||||
serverButton.setText(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.stopServer.label"));
|
||||
serverButton.setIcon(AllIcons.Actions.Suspend);
|
||||
} else if (buildInProgress) {
|
||||
serverButton.setText(CodeGPTBundle.get("llama.ui.button.stopBuild"));
|
||||
serverButton.setIcon(AllIcons.Actions.Suspend);
|
||||
} else {
|
||||
serverButton.setText(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
|
||||
serverButton.setIcon(AllIcons.Actions.Execute);
|
||||
}
|
||||
|
||||
serverButton.addActionListener(e -> {
|
||||
if (serverAgent.isServerRunning()) {
|
||||
serverAgent.stopAgent();
|
||||
setFieldsEnabled(true, config);
|
||||
serverButton.setText(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
|
||||
serverButton.setIcon(AllIcons.Actions.Execute);
|
||||
} else if (serverAgent.isBuildInProgress()) {
|
||||
serverAgent.stopAgent();
|
||||
setFieldsEnabled(true, config);
|
||||
serverButton.setText(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
|
||||
serverButton.setIcon(AllIcons.Actions.Execute);
|
||||
} else {
|
||||
setTabState(BUILD_OUTPUT_TAB, true, BUILD_OUTPUT_DISABLED_TOOLTIP);
|
||||
tabbedPane.setSelectedIndex(BUILD_OUTPUT_TAB);
|
||||
serverButton.setText(CodeGPTBundle.get("llama.ui.button.stopBuild"));
|
||||
serverButton.setIcon(AllIcons.Actions.Suspend);
|
||||
setFieldsEnabled(false, config);
|
||||
|
||||
logToConsole(CodeGPTBundle.get("llama.process.startingBuild"), false, true);
|
||||
|
||||
var params = new LlamaServerStartupParams(
|
||||
serverPreferencesForm.getLlamaModelPreferencesForm().getActualModelPath(),
|
||||
config.getContextSizeField().getValue(),
|
||||
config.getThreadsField().getValue(),
|
||||
config.getPortField().getNumber(),
|
||||
LlamaSettings.getAdditionalParametersList(
|
||||
config.getAdditionalParametersField().getText()),
|
||||
LlamaSettings.getAdditionalParametersList(
|
||||
config.getAdditionalBuildParametersField().getText()),
|
||||
LlamaSettings.getAdditionalEnvironmentVariablesMap(
|
||||
config.getAdditionalEnvironmentVariablesField().getText())
|
||||
);
|
||||
|
||||
serverAgent.startAgent(
|
||||
params,
|
||||
new SettingsFormLoggingStrategy(this),
|
||||
() -> {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
serverButton.setText(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.stopServer.label"));
|
||||
serverButton.setIcon(AllIcons.Actions.Suspend);
|
||||
setTabState(SERVER_LOGS_TAB, true, SERVER_LOGS_DISABLED_TOOLTIP);
|
||||
setTabState(BUILD_OUTPUT_TAB, false, BUILD_OUTPUT_DISABLED_TOOLTIP);
|
||||
tabbedPane.setSelectedIndex(SERVER_LOGS_TAB);
|
||||
});
|
||||
},
|
||||
() -> {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
setFieldsEnabled(true, config);
|
||||
serverButton.setText(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.startServer.label"));
|
||||
serverButton.setIcon(AllIcons.Actions.Execute);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return serverButton;
|
||||
}
|
||||
|
||||
private void setFieldsEnabled(boolean enabled, ServerButtonConfig config) {
|
||||
config.getPortField().setEnabled(enabled);
|
||||
config.getContextSizeField().setEnabled(enabled);
|
||||
config.getThreadsField().setEnabled(enabled);
|
||||
config.getAdditionalParametersField().setEnabled(enabled);
|
||||
config.getAdditionalBuildParametersField().setEnabled(enabled);
|
||||
config.getAdditionalEnvironmentVariablesField().setEnabled(enabled);
|
||||
}
|
||||
|
||||
private JPanel createBuildLogsTab() {
|
||||
return createLogsTab(buildLogsConsole, false);
|
||||
}
|
||||
|
||||
private JPanel createServerLogsTab() {
|
||||
return createLogsTab(serverLogsConsole, true);
|
||||
}
|
||||
|
||||
private JPanel createLogsTab(Component view, boolean isServerLogs) {
|
||||
var panel = new JPanel(new BorderLayout());
|
||||
panel.add(createLogsToolbar(isServerLogs), BorderLayout.NORTH);
|
||||
|
||||
var scrollPane = new JScrollPane(view);
|
||||
scrollPane.setPreferredSize(JBUI.size(600, 240));
|
||||
panel.add(scrollPane, BorderLayout.CENTER);
|
||||
panel.add(createStatusBar(), BorderLayout.SOUTH);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JComponent createLogsToolbar(boolean isServerLogs) {
|
||||
var actionGroup = new DefaultActionGroup();
|
||||
|
||||
actionGroup.add(new DumbAwareAction(CodeGPTBundle.get("llama.ui.action.clear"), CodeGPTBundle.get("llama.ui.action.clear.description"), AllIcons.Actions.GC) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
var consolePanel = isServerLogs ? serverLogsConsole : buildLogsConsole;
|
||||
consolePanel.clearConsole();
|
||||
}
|
||||
});
|
||||
|
||||
actionGroup.add(new DumbAwareAction(CodeGPTBundle.get("llama.ui.action.scrollToEnd"), CodeGPTBundle.get("llama.ui.action.scrollToEnd.description"),
|
||||
AllIcons.RunConfigurations.Scroll_down) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
var consolePanel = isServerLogs ? serverLogsConsole : buildLogsConsole;
|
||||
consolePanel.setCaretPosition(consolePanel.getDocument().getLength());
|
||||
}
|
||||
});
|
||||
|
||||
var toolbar = ActionManager.getInstance().createActionToolbar("LlamaLogs", actionGroup, true);
|
||||
toolbar.setTargetComponent(this);
|
||||
return toolbar.getComponent();
|
||||
}
|
||||
|
||||
private JPanel createStatusBar() {
|
||||
var statusBar = new JPanel(new BorderLayout());
|
||||
statusBar.setBorder(JBUI.Borders.compound(
|
||||
JBUI.Borders.customLine(JBUI.CurrentTheme.ToolWindow.borderColor(), 1, 0, 0, 0),
|
||||
JBUI.Borders.empty(4)
|
||||
));
|
||||
|
||||
statusBar.add(serverStatusPanel, BorderLayout.WEST);
|
||||
return statusBar;
|
||||
}
|
||||
|
||||
private void loadExistingLogs() {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
var logsManager = ApplicationManager.getApplication().getService(ServerLogsManager.class);
|
||||
var logs = logsManager.getSessionLogs(logsManager.getCurrentSession().getId());
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
for (var log : logs) {
|
||||
boolean isError = log.getMessage().toLowerCase().contains("error") ||
|
||||
log.getMessage().toLowerCase().contains("exception") ||
|
||||
log.getMessage().toLowerCase().contains("failed");
|
||||
serverLogsConsole.appendText(log.getMessage(), isError);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void updateServerStatus() {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (serverAgent.isServerRunning()) {
|
||||
serverStatusLabel.setText(CodeGPTBundle.get("llama.ui.status.running"));
|
||||
serverStatusLabel.setIcon(AllIcons.General.InspectionsOK);
|
||||
serverStatusLabel.setForeground(JBColor.GREEN);
|
||||
serverStatusSpinner.setVisible(false);
|
||||
setTabState(SERVER_LOGS_TAB, true, SERVER_LOGS_DISABLED_TOOLTIP);
|
||||
setTabState(BUILD_OUTPUT_TAB, false, BUILD_OUTPUT_DISABLED_TOOLTIP);
|
||||
} else if (serverAgent.isBuildInProgress()) {
|
||||
serverStatusLabel.setText(CodeGPTBundle.get("llama.ui.status.building"));
|
||||
serverStatusLabel.setIcon(null);
|
||||
serverStatusLabel.setForeground(JBColor.BLUE);
|
||||
serverStatusSpinner.setVisible(true);
|
||||
setTabState(SERVER_LOGS_TAB, false, SERVER_LOGS_DISABLED_TOOLTIP);
|
||||
setTabState(BUILD_OUTPUT_TAB, true, BUILD_OUTPUT_DISABLED_TOOLTIP);
|
||||
} else {
|
||||
serverStatusLabel.setText(CodeGPTBundle.get("llama.ui.status.stopped"));
|
||||
serverStatusLabel.setIcon(AllIcons.General.InspectionsEye);
|
||||
serverStatusLabel.setForeground(JBColor.GRAY);
|
||||
serverStatusSpinner.setVisible(false);
|
||||
setTabState(SERVER_LOGS_TAB, false, SERVER_LOGS_DISABLED_TOOLTIP);
|
||||
setTabState(BUILD_OUTPUT_TAB, false, BUILD_OUTPUT_DISABLED_TOOLTIP);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void refreshServerStatus() {
|
||||
updateServerStatus();
|
||||
}
|
||||
|
||||
public void updateServerStatusWithPhase(String phase) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
serverStatusLabel.setText(CodeGPTBundle.get("llama.ui.status.prefix").replace("{0}", phase));
|
||||
serverStatusLabel.setIcon(null);
|
||||
serverStatusLabel.setForeground(JBColor.BLUE);
|
||||
serverStatusSpinner.setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
public void logToConsole(String message, boolean isError, boolean isBuildLog) {
|
||||
var consolePanel = isBuildLog ? buildLogsConsole : serverLogsConsole;
|
||||
if (consolePanel != null) {
|
||||
consolePanel.appendText(message, isError);
|
||||
}
|
||||
}
|
||||
|
||||
public LlamaSettingsState getCurrentState() {
|
||||
var state = new LlamaSettingsState();
|
||||
state.setTopK(llamaRequestPreferencesForm.getTopK());
|
||||
state.setTopP(llamaRequestPreferencesForm.getTopP());
|
||||
state.setMinP(llamaRequestPreferencesForm.getMinP());
|
||||
state.setRepeatPenalty(llamaRequestPreferencesForm.getRepeatPenalty());
|
||||
|
||||
state.setRemoteModelPromptTemplate(llamaServerPreferencesForm.getPromptTemplate());
|
||||
state.setRemoteModelInfillPromptTemplate(llamaServerPreferencesForm.getInfillPromptTemplate());
|
||||
state.setRunLocalServer(llamaServerPreferencesForm.isRunLocalServer());
|
||||
state.setBaseHost(llamaServerPreferencesForm.getBaseHost());
|
||||
state.setServerPort(llamaServerPreferencesForm.getServerPort());
|
||||
state.setContextSize(llamaServerPreferencesForm.getContextSize());
|
||||
state.setThreads(llamaServerPreferencesForm.getThreads());
|
||||
state.setAdditionalParameters(llamaServerPreferencesForm.getAdditionalParameters());
|
||||
state.setAdditionalBuildParameters(llamaServerPreferencesForm.getAdditionalBuildParameters());
|
||||
state.setServerPort(serverPreferencesForm.getServerPort());
|
||||
state.setContextSize(serverPreferencesForm.getContextSize());
|
||||
state.setThreads(serverPreferencesForm.getThreads());
|
||||
state.setAdditionalParameters(serverPreferencesForm.getAdditionalParameters());
|
||||
state.setAdditionalBuildParameters(serverPreferencesForm.getAdditionalBuildParameters());
|
||||
state.setAdditionalEnvironmentVariables(
|
||||
llamaServerPreferencesForm.getAdditionalEnvironmentVariables());
|
||||
serverPreferencesForm.getAdditionalEnvironmentVariables());
|
||||
|
||||
var modelPreferencesForm = llamaServerPreferencesForm.getLlamaModelPreferencesForm();
|
||||
state.setTopK(settingsState.getTopK());
|
||||
state.setTopP(settingsState.getTopP());
|
||||
state.setMinP(settingsState.getMinP());
|
||||
state.setRepeatPenalty(settingsState.getRepeatPenalty());
|
||||
|
||||
var modelPreferencesForm = serverPreferencesForm.getLlamaModelPreferencesForm();
|
||||
state.setCustomLlamaModelPath(modelPreferencesForm.getCustomLlamaModelPath());
|
||||
state.setHuggingFaceModel(modelPreferencesForm.getSelectedModel());
|
||||
state.setUseCustomModel(modelPreferencesForm.isUseCustomLlamaModel());
|
||||
state.setHuggingFaceModel(modelPreferencesForm.getSelectedModel());
|
||||
state.setLocalModelPromptTemplate(modelPreferencesForm.getPromptTemplate());
|
||||
state.setLocalModelInfillPromptTemplate(modelPreferencesForm.getInfillPromptTemplate());
|
||||
state.setCodeCompletionsEnabled(codeCompletionConfigurationForm.isCodeCompletionsEnabled());
|
||||
|
||||
state.setCodeCompletionsEnabled(settingsState.isCodeCompletionsEnabled());
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public void resetForm() {
|
||||
var state = LlamaSettings.getCurrentState();
|
||||
llamaServerPreferencesForm.resetForm(state);
|
||||
llamaRequestPreferencesForm.resetForm(state);
|
||||
codeCompletionConfigurationForm.setCodeCompletionsEnabled(state.isCodeCompletionsEnabled());
|
||||
serverPreferencesForm.resetForm(settingsState);
|
||||
}
|
||||
|
||||
public LlamaServerPreferencesForm getLlamaServerPreferencesForm() {
|
||||
return llamaServerPreferencesForm;
|
||||
public void resetForm(LlamaSettingsState newState) {
|
||||
serverPreferencesForm.resetForm(newState);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setLayout(new BorderLayout());
|
||||
add(FormBuilder.createFormBuilder()
|
||||
.addComponent(new TitledSeparator("Code Completions"))
|
||||
.addComponent(withEmptyLeftBorder(codeCompletionConfigurationForm.getForm()))
|
||||
.addComponent(new TitledSeparator(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.llama.serverPreferences.title")))
|
||||
.addComponent(llamaServerPreferencesForm.getForm())
|
||||
.addComponent(new TitledSeparator("Request Preferences"))
|
||||
.addComponent(withEmptyLeftBorder(llamaRequestPreferencesForm.getForm()))
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel());
|
||||
private void setTabState(int tabIndex, boolean enabled, String disabledTooltip) {
|
||||
tabbedPane.setEnabledAt(tabIndex, enabled);
|
||||
tabbedPane.setToolTipTextAt(tabIndex, enabled ? null : disabledTooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package ee.carlrobert.codegpt.settings.service.llama.form;
|
||||
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.ui.AsyncProcessIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class ServerProgressPanel extends JPanel {
|
||||
|
||||
private final JBLabel label = new JBLabel();
|
||||
private final AsyncProcessIcon loadingSpinner = new AsyncProcessIcon("sign_in_spinner");
|
||||
|
||||
public void displayText(String text) {
|
||||
label.setText(text);
|
||||
removeAll();
|
||||
add(loadingSpinner);
|
||||
add(label);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void displayComponent(JComponent component) {
|
||||
removeAll();
|
||||
add(component);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
|
@ -286,10 +286,6 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
}
|
||||
|
||||
private String getLlamaCppPresentationText() {
|
||||
var llamaSettingState = LlamaSettings.getCurrentState();
|
||||
if (!llamaSettingState.isRunLocalServer()) {
|
||||
return format("Remote %s", llamaSettingState.getRemoteModelPromptTemplate());
|
||||
}
|
||||
return getSelectedHuggingFace();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue