mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-12 14:10:29 +00:00
Merge remote-tracking branch 'origin/master' into platform/2024.1
This commit is contained in:
commit
8883200817
82 changed files with 2555 additions and 645 deletions
|
|
@ -9,15 +9,15 @@ dependencies {
|
|||
implementation("io.github.bonede:tree-sitter-dockerfile:0.1.2")
|
||||
implementation("io.github.bonede:tree-sitter-dart:master")
|
||||
implementation("io.github.bonede:tree-sitter-css:0.20.0")
|
||||
implementation("io.github.bonede:tree-sitter-cpp:0.20.3")
|
||||
implementation("io.github.bonede:tree-sitter-cpp:0.22.0")
|
||||
implementation("io.github.bonede:tree-sitter-c-sharp:0.20.0")
|
||||
implementation("io.github.bonede:tree-sitter-fortran:master")
|
||||
implementation("io.github.bonede:tree-sitter-gitattributes:0.1.3")
|
||||
implementation("io.github.bonede:tree-sitter-go:0.20.0")
|
||||
implementation("io.github.bonede:tree-sitter-go:0.21.0")
|
||||
implementation("io.github.bonede:tree-sitter-graphql:master")
|
||||
implementation("io.github.bonede:tree-sitter-html:0.19.0")
|
||||
implementation("io.github.bonede:tree-sitter-html:0.20.2")
|
||||
implementation("io.github.bonede:tree-sitter-javascript:0.20.1")
|
||||
implementation("io.github.bonede:tree-sitter-json:0.20.1")
|
||||
implementation("io.github.bonede:tree-sitter-json:0.21.0")
|
||||
implementation("io.github.bonede:tree-sitter-kotlin:0.3.1")
|
||||
implementation("io.github.bonede:tree-sitter-latex:0.3.0")
|
||||
implementation("io.github.bonede:tree-sitter-lua:2.1.3")
|
||||
|
|
@ -25,16 +25,16 @@ dependencies {
|
|||
implementation("io.github.bonede:tree-sitter-markdown:0.7.1")
|
||||
implementation("io.github.bonede:tree-sitter-objc:main")
|
||||
implementation("io.github.bonede:tree-sitter-perl:0.4.0")
|
||||
implementation("io.github.bonede:tree-sitter-ruby:0.19.0")
|
||||
implementation("io.github.bonede:tree-sitter-rust:0.20.4")
|
||||
implementation("io.github.bonede:tree-sitter-scala:0.20.2")
|
||||
implementation("io.github.bonede:tree-sitter-ruby:0.20.1")
|
||||
implementation("io.github.bonede:tree-sitter-rust:0.21.0")
|
||||
implementation("io.github.bonede:tree-sitter-scala:0.21.0")
|
||||
implementation("io.github.bonede:tree-sitter-scss:1.0.0")
|
||||
implementation("io.github.bonede:tree-sitter-svelte:0.11.0")
|
||||
implementation("io.github.bonede:tree-sitter-swift:0.3.6")
|
||||
implementation("io.github.bonede:tree-sitter-yaml:0.5.0")
|
||||
implementation("io.github.bonede:tree-sitter-java:0.20.2")
|
||||
implementation("io.github.bonede:tree-sitter-python:0.20.4")
|
||||
implementation("io.github.bonede:tree-sitter-php:0.20.0")
|
||||
implementation("io.github.bonede:tree-sitter-typescript:0.20.3")
|
||||
implementation("io.github.bonede:tree-sitter-java:0.21.0")
|
||||
implementation("io.github.bonede:tree-sitter-python:0.21.0")
|
||||
implementation("io.github.bonede:tree-sitter-php:0.22.2")
|
||||
implementation("io.github.bonede:tree-sitter-typescript:0.20.6")
|
||||
implementation("io.github.bonede:tree-sitter-query:0.1.0")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,18 +3,18 @@ analytics = "3.0.0"
|
|||
assertj = "3.25.3"
|
||||
changelog = "2.2.0"
|
||||
checkstyle = "10.15.0"
|
||||
commons-text = "1.11.0"
|
||||
commons-text = "1.12.0"
|
||||
flexmark = "0.64.8"
|
||||
gradle-intellij-plugin-version = "1.17.3"
|
||||
gson = "2.10.1"
|
||||
jackson = "2.17.0"
|
||||
jackson = "2.17.1"
|
||||
jsoup = "1.17.2"
|
||||
jtokkit = "1.0.0"
|
||||
junit = "5.10.2"
|
||||
kotlin = "1.9.23"
|
||||
llm-client = "0.7.2"
|
||||
kotlin = "1.9.24"
|
||||
llm-client = "0.8.1"
|
||||
okio = "3.9.0"
|
||||
tree-sitter = "0.22.2"
|
||||
tree-sitter = "0.22.5"
|
||||
|
||||
[libraries]
|
||||
analytics = { module = "com.rudderstack.sdk.java.analytics:analytics", version.ref = "analytics" }
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 7dbdba5690ca61b3ee8c92cfac8e7e251042e787
|
||||
Subproject commit 46e12c4692a37bdd31a0432fc5153d7d22bc7f72
|
||||
|
|
@ -8,14 +8,18 @@ public final class Icons {
|
|||
public static final Icon Default = IconLoader.getIcon("/icons/codegpt.svg", Icons.class);
|
||||
public static final Icon DefaultSmall =
|
||||
IconLoader.getIcon("/icons/codegpt-small.svg", Icons.class);
|
||||
public static final Icon CodeGPTModel =
|
||||
IconLoader.getIcon("/icons/codegpt-model.svg", Icons.class);
|
||||
public static final Icon Anthropic = IconLoader.getIcon("/icons/anthropic.svg", Icons.class);
|
||||
public static final Icon Azure = IconLoader.getIcon("/icons/azure.svg", Icons.class);
|
||||
public static final Icon Google = IconLoader.getIcon("/icons/google.svg", Icons.class);
|
||||
public static final Icon Llama = IconLoader.getIcon("/icons/llama.svg", Icons.class);
|
||||
public static final Icon OpenAI = IconLoader.getIcon("/icons/openai.svg", Icons.class);
|
||||
public static final Icon Send = IconLoader.getIcon("/icons/send.svg", Icons.class);
|
||||
public static final Icon Sparkle = IconLoader.getIcon("/icons/sparkle.svg", Icons.class);
|
||||
public static final Icon You = IconLoader.getIcon("/icons/you.svg", Icons.class);
|
||||
public static final Icon YouSmall = IconLoader.getIcon("/icons/you_small.png", Icons.class);
|
||||
public static final Icon Ollama = IconLoader.getIcon("/icons/ollama.svg", Icons.class);
|
||||
public static final Icon User = IconLoader.getIcon("/icons/user.svg", Icons.class);
|
||||
public static final Icon Upload = IconLoader.getIcon("/icons/upload.svg", Icons.class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.intellij.openapi.actionSystem.AnAction;
|
|||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettingsConfigurable;
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceConfigurable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class OpenSettingsAction extends AnAction {
|
||||
|
|
@ -18,7 +18,6 @@ public class OpenSettingsAction extends AnAction {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
ShowSettingsUtil.getInstance()
|
||||
.showSettingsDialog(e.getProject(), GeneralSettingsConfigurable.class);
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(e.getProject(), ServiceConfigurable.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
package ee.carlrobert.codegpt.completions;
|
||||
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import ee.carlrobert.codegpt.CodeGPTPlugin;
|
||||
import ee.carlrobert.codegpt.completions.you.YouUserManager;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
|
||||
import ee.carlrobert.codegpt.settings.advanced.AdvancedSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import ee.carlrobert.llm.client.anthropic.ClaudeClient;
|
||||
import ee.carlrobert.llm.client.azure.AzureClient;
|
||||
import ee.carlrobert.llm.client.azure.AzureCompletionRequestParams;
|
||||
import ee.carlrobert.llm.client.codegpt.CodeGPTClient;
|
||||
import ee.carlrobert.llm.client.google.GoogleClient;
|
||||
import ee.carlrobert.llm.client.llama.LlamaClient;
|
||||
import ee.carlrobert.llm.client.ollama.OllamaClient;
|
||||
import ee.carlrobert.llm.client.openai.OpenAIClient;
|
||||
import ee.carlrobert.llm.client.you.UTMParameters;
|
||||
import ee.carlrobert.llm.client.you.YouClient;
|
||||
|
|
@ -21,12 +27,13 @@ import java.net.Proxy;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.Credentials;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CompletionClientProvider {
|
||||
|
||||
private static @Nullable String getCredential(CredentialKey key) {
|
||||
return CredentialsStore.INSTANCE.getCredential(key);
|
||||
public static CodeGPTClient getCodeGPTClient() {
|
||||
return new CodeGPTClient(
|
||||
getCredential(CredentialKey.CODEGPT_API_KEY),
|
||||
getDefaultClientBuilder());
|
||||
}
|
||||
|
||||
public static OpenAIClient getOpenAIClient() {
|
||||
|
|
@ -92,6 +99,22 @@ public class CompletionClientProvider {
|
|||
return builder.build(getDefaultClientBuilder());
|
||||
}
|
||||
|
||||
public static OllamaClient getOllamaClient() {
|
||||
var host = ApplicationManager.getApplication()
|
||||
.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.getHost();
|
||||
return new OllamaClient.Builder()
|
||||
.setHost(host)
|
||||
.build(getDefaultClientBuilder());
|
||||
}
|
||||
|
||||
|
||||
public static GoogleClient getGoogleClient() {
|
||||
return new GoogleClient.Builder(getCredential(CredentialKey.GOOGLE_API_KEY))
|
||||
.build(getDefaultClientBuilder());
|
||||
}
|
||||
|
||||
public static OkHttpClient.Builder getDefaultClientBuilder() {
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||
var advancedSettings = AdvancedSettings.getCurrentState();
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ import ee.carlrobert.codegpt.settings.service.ServiceType;
|
|||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceChatCompletionSettingsState;
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceState;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettings;
|
||||
import ee.carlrobert.codegpt.telemetry.core.configuration.TelemetryConfiguration;
|
||||
|
|
@ -40,7 +40,15 @@ import ee.carlrobert.llm.client.anthropic.completion.ClaudeCompletionRequest;
|
|||
import ee.carlrobert.llm.client.anthropic.completion.ClaudeCompletionStandardMessage;
|
||||
import ee.carlrobert.llm.client.anthropic.completion.ClaudeMessageImageContent;
|
||||
import ee.carlrobert.llm.client.anthropic.completion.ClaudeMessageTextContent;
|
||||
import ee.carlrobert.llm.client.google.completion.GoogleCompletionContent;
|
||||
import ee.carlrobert.llm.client.google.completion.GoogleCompletionRequest;
|
||||
import ee.carlrobert.llm.client.google.completion.GoogleContentPart;
|
||||
import ee.carlrobert.llm.client.google.completion.GoogleContentPart.Blob;
|
||||
import ee.carlrobert.llm.client.google.completion.GoogleGenerationConfig;
|
||||
import ee.carlrobert.llm.client.google.models.GoogleModel;
|
||||
import ee.carlrobert.llm.client.llama.completion.LlamaCompletionRequest;
|
||||
import ee.carlrobert.llm.client.ollama.completion.request.OllamaChatCompletionMessage;
|
||||
import ee.carlrobert.llm.client.ollama.completion.request.OllamaChatCompletionRequest;
|
||||
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
|
||||
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionDetailedMessage;
|
||||
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionMessage;
|
||||
|
|
@ -56,6 +64,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
|
@ -116,7 +125,8 @@ public class CompletionRequestProvider {
|
|||
|
||||
public static Request buildCustomOpenAICompletionRequest(String system, String context) {
|
||||
return buildCustomOpenAIChatCompletionRequest(
|
||||
ApplicationManager.getApplication().getService(CustomServiceState.class)
|
||||
ApplicationManager.getApplication().getService(CustomServiceSettings.class)
|
||||
.getState()
|
||||
.getChatCompletionSettings(),
|
||||
List.of(
|
||||
new OpenAIChatCompletionStandardMessage("system", system),
|
||||
|
|
@ -124,18 +134,23 @@ public class CompletionRequestProvider {
|
|||
true);
|
||||
}
|
||||
|
||||
public static Request buildCustomOpenAICompletionRequest(String input) {
|
||||
public static Request buildCustomOpenAICompletionRequest(String context, String url,
|
||||
Map<String, String> headers, Map<String, Object> body, String credential) {
|
||||
var usedSettings = new CustomServiceChatCompletionSettingsState();
|
||||
usedSettings.setBody(body);
|
||||
usedSettings.setHeaders(headers);
|
||||
usedSettings.setUrl(url);
|
||||
return buildCustomOpenAIChatCompletionRequest(
|
||||
ApplicationManager.getApplication().getService(CustomServiceSettings.class)
|
||||
.getState()
|
||||
.getChatCompletionSettings(),
|
||||
List.of(new OpenAIChatCompletionStandardMessage("user", input)),
|
||||
true);
|
||||
usedSettings,
|
||||
List.of(new OpenAIChatCompletionStandardMessage("user", context)),
|
||||
true,
|
||||
credential);
|
||||
}
|
||||
|
||||
public static Request buildCustomOpenAILookupCompletionRequest(String context) {
|
||||
return buildCustomOpenAIChatCompletionRequest(
|
||||
ApplicationManager.getApplication().getService(CustomServiceState.class)
|
||||
ApplicationManager.getApplication().getService(CustomServiceSettings.class)
|
||||
.getState()
|
||||
.getChatCompletionSettings(),
|
||||
List.of(
|
||||
new OpenAIChatCompletionStandardMessage(
|
||||
|
|
@ -205,19 +220,29 @@ public class CompletionRequestProvider {
|
|||
@Nullable String model,
|
||||
CallParameters callParameters) {
|
||||
var configuration = ConfigurationSettings.getCurrentState();
|
||||
return new OpenAIChatCompletionRequest.Builder(buildMessages(model, callParameters))
|
||||
return new OpenAIChatCompletionRequest.Builder(buildOpenAIMessages(model, callParameters))
|
||||
.setModel(model)
|
||||
.setMaxTokens(configuration.getMaxTokens())
|
||||
.setStream(true)
|
||||
.setTemperature(configuration.getTemperature()).build();
|
||||
}
|
||||
|
||||
public GoogleCompletionRequest buildGoogleChatCompletionRequest(
|
||||
@Nullable String model,
|
||||
CallParameters callParameters) {
|
||||
var configuration = ConfigurationSettings.getCurrentState();
|
||||
return new GoogleCompletionRequest.Builder(buildGoogleMessages(model, callParameters))
|
||||
.generationConfig(new GoogleGenerationConfig.Builder()
|
||||
.maxOutputTokens(configuration.getMaxTokens())
|
||||
.temperature(configuration.getTemperature()).build()).build();
|
||||
}
|
||||
|
||||
public Request buildCustomOpenAIChatCompletionRequest(
|
||||
CustomServiceChatCompletionSettingsState settings,
|
||||
CallParameters callParameters) {
|
||||
return buildCustomOpenAIChatCompletionRequest(
|
||||
settings,
|
||||
buildMessages(callParameters),
|
||||
buildOpenAIMessages(callParameters),
|
||||
true);
|
||||
}
|
||||
|
||||
|
|
@ -225,8 +250,16 @@ public class CompletionRequestProvider {
|
|||
CustomServiceChatCompletionSettingsState settings,
|
||||
List<OpenAIChatCompletionMessage> messages,
|
||||
boolean streamRequest) {
|
||||
return buildCustomOpenAIChatCompletionRequest(settings, messages, streamRequest,
|
||||
CredentialsStore.getCredential(CUSTOM_SERVICE_API_KEY));
|
||||
}
|
||||
|
||||
private static Request buildCustomOpenAIChatCompletionRequest(
|
||||
CustomServiceChatCompletionSettingsState settings,
|
||||
List<OpenAIChatCompletionMessage> messages,
|
||||
boolean streamRequest,
|
||||
String credential) {
|
||||
var requestBuilder = new Request.Builder().url(requireNonNull(settings.getUrl()).trim());
|
||||
var credential = CredentialsStore.INSTANCE.getCredential(CUSTOM_SERVICE_API_KEY);
|
||||
for (var entry : settings.getHeaders().entrySet()) {
|
||||
String value = entry.getValue();
|
||||
if (credential != null && value.contains("$CUSTOM_SERVICE_API_KEY")) {
|
||||
|
|
@ -294,7 +327,68 @@ public class CompletionRequestProvider {
|
|||
return request;
|
||||
}
|
||||
|
||||
private List<OpenAIChatCompletionMessage> buildMessages(CallParameters callParameters) {
|
||||
public OllamaChatCompletionRequest buildOllamaChatCompletionRequest(
|
||||
CallParameters callParameters
|
||||
) {
|
||||
var settings = ApplicationManager.getApplication().getService(OllamaSettings.class).getState();
|
||||
return new OllamaChatCompletionRequest
|
||||
.Builder(settings.getModel(), buildOllamaMessages(callParameters))
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<OllamaChatCompletionMessage> buildOllamaMessages(CallParameters callParameters) {
|
||||
var message = callParameters.getMessage();
|
||||
var messages = new ArrayList<OllamaChatCompletionMessage>();
|
||||
if (callParameters.getConversationType() == ConversationType.DEFAULT) {
|
||||
String systemPrompt = ConfigurationSettings.getCurrentState().getSystemPrompt();
|
||||
messages.add(new OllamaChatCompletionMessage("system", systemPrompt, null));
|
||||
}
|
||||
if (callParameters.getConversationType() == ConversationType.FIX_COMPILE_ERRORS) {
|
||||
messages.add(
|
||||
new OllamaChatCompletionMessage("system", FIX_COMPILE_ERRORS_SYSTEM_PROMPT, null)
|
||||
);
|
||||
}
|
||||
|
||||
for (var prevMessage : conversation.getMessages()) {
|
||||
if (callParameters.isRetry() && prevMessage.getId().equals(message.getId())) {
|
||||
break;
|
||||
}
|
||||
var prevMessageImageFilePath = prevMessage.getImageFilePath();
|
||||
if (prevMessageImageFilePath != null && !prevMessageImageFilePath.isEmpty()) {
|
||||
try {
|
||||
var imageFilePath = Path.of(prevMessageImageFilePath);
|
||||
var imageBytes = Files.readAllBytes(imageFilePath);
|
||||
var imageBase64 = Base64.getEncoder().encodeToString(imageBytes);
|
||||
messages.add(
|
||||
new OllamaChatCompletionMessage(
|
||||
"user", prevMessage.getPrompt(), List.of(imageBase64)
|
||||
)
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
messages.add(
|
||||
new OllamaChatCompletionMessage("user", prevMessage.getPrompt(), null)
|
||||
);
|
||||
}
|
||||
messages.add(
|
||||
new OllamaChatCompletionMessage("assistant", prevMessage.getResponse(), null)
|
||||
);
|
||||
}
|
||||
|
||||
if (callParameters.getImageMediaType() != null && callParameters.getImageData().length > 0) {
|
||||
var imageBase64 = Base64.getEncoder().encodeToString(callParameters.getImageData());
|
||||
messages.add(
|
||||
new OllamaChatCompletionMessage("user", message.getPrompt(), List.of(imageBase64))
|
||||
);
|
||||
} else {
|
||||
messages.add(new OllamaChatCompletionMessage("user", message.getPrompt(), null));
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
private List<OpenAIChatCompletionMessage> buildOpenAIMessages(CallParameters callParameters) {
|
||||
var message = callParameters.getMessage();
|
||||
var messages = new ArrayList<OpenAIChatCompletionMessage>();
|
||||
if (callParameters.getConversationType() == ConversationType.DEFAULT) {
|
||||
|
|
@ -326,7 +420,9 @@ public class CompletionRequestProvider {
|
|||
} else {
|
||||
messages.add(new OpenAIChatCompletionStandardMessage("user", prevMessage.getPrompt()));
|
||||
}
|
||||
messages.add(new OpenAIChatCompletionStandardMessage("assistant", prevMessage.getResponse()));
|
||||
messages.add(
|
||||
new OpenAIChatCompletionStandardMessage("assistant", prevMessage.getResponse())
|
||||
);
|
||||
}
|
||||
|
||||
if (callParameters.getImageMediaType() != null && callParameters.getImageData().length > 0) {
|
||||
|
|
@ -342,10 +438,10 @@ public class CompletionRequestProvider {
|
|||
return messages;
|
||||
}
|
||||
|
||||
private List<OpenAIChatCompletionMessage> buildMessages(
|
||||
private List<OpenAIChatCompletionMessage> buildOpenAIMessages(
|
||||
@Nullable String model,
|
||||
CallParameters callParameters) {
|
||||
var messages = buildMessages(callParameters);
|
||||
var messages = buildOpenAIMessages(callParameters);
|
||||
|
||||
if (model == null
|
||||
|| GeneralSettings.getCurrentState().getSelectedService() == ServiceType.YOU) {
|
||||
|
|
@ -368,6 +464,83 @@ public class CompletionRequestProvider {
|
|||
return tryReducingMessagesOrThrow(messages, totalUsage, modelMaxTokens);
|
||||
}
|
||||
|
||||
private List<GoogleCompletionContent> buildGoogleMessages(CallParameters callParameters) {
|
||||
var message = callParameters.getMessage();
|
||||
var messages = new ArrayList<GoogleCompletionContent>();
|
||||
// Gemini API does not support direct 'system' prompts:
|
||||
// see https://www.reddit.com/r/Bard/comments/1b90i8o/does_gemini_have_a_system_prompt_option_while/
|
||||
if (callParameters.getConversationType() == ConversationType.DEFAULT) {
|
||||
String systemPrompt = ConfigurationSettings.getCurrentState().getSystemPrompt();
|
||||
messages.add(new GoogleCompletionContent("user", List.of(systemPrompt)));
|
||||
messages.add(new GoogleCompletionContent("model", List.of("Understood.")));
|
||||
}
|
||||
if (callParameters.getConversationType() == ConversationType.FIX_COMPILE_ERRORS) {
|
||||
messages.add(
|
||||
new GoogleCompletionContent("user", List.of(FIX_COMPILE_ERRORS_SYSTEM_PROMPT)));
|
||||
messages.add(new GoogleCompletionContent("model", List.of("Understood.")));
|
||||
}
|
||||
|
||||
for (var prevMessage : conversation.getMessages()) {
|
||||
if (callParameters.isRetry() && prevMessage.getId().equals(message.getId())) {
|
||||
break;
|
||||
}
|
||||
var prevMessageImageFilePath = prevMessage.getImageFilePath();
|
||||
if (prevMessageImageFilePath != null && !prevMessageImageFilePath.isEmpty()) {
|
||||
try {
|
||||
var imageFilePath = Path.of(prevMessageImageFilePath);
|
||||
var imageData = Files.readAllBytes(imageFilePath);
|
||||
var imageMediaType = FileUtil.getImageMediaType(imageFilePath.getFileName().toString());
|
||||
messages.add(new GoogleCompletionContent(
|
||||
List.of(
|
||||
new GoogleContentPart(null, new Blob(imageMediaType, imageData)),
|
||||
new GoogleContentPart(prevMessage.getPrompt())), "user"));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
messages.add(new GoogleCompletionContent("user", List.of(prevMessage.getPrompt())));
|
||||
}
|
||||
messages.add(new GoogleCompletionContent("model", List.of(prevMessage.getResponse())));
|
||||
}
|
||||
|
||||
if (callParameters.getImageMediaType() != null && callParameters.getImageData().length > 0) {
|
||||
messages.add(new GoogleCompletionContent(
|
||||
List.of(
|
||||
new GoogleContentPart(null,
|
||||
new Blob(callParameters.getImageMediaType(), callParameters.getImageData())),
|
||||
new GoogleContentPart(message.getPrompt())), "user"));
|
||||
} else {
|
||||
messages.add(new GoogleCompletionContent("user", List.of(message.getPrompt())));
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
private List<GoogleCompletionContent> buildGoogleMessages(
|
||||
@Nullable String model,
|
||||
CallParameters callParameters) {
|
||||
var messages = buildGoogleMessages(callParameters);
|
||||
|
||||
if (model == null) {
|
||||
return messages;
|
||||
}
|
||||
|
||||
int totalUsage = messages.parallelStream()
|
||||
.mapToInt(message -> encodingManager.countMessageTokens(message.getRole(),
|
||||
String.join(",", message.getParts().stream().map(GoogleContentPart::getText).toList())))
|
||||
.sum() + ConfigurationSettings.getCurrentState().getMaxTokens();
|
||||
int modelMaxTokens;
|
||||
try {
|
||||
modelMaxTokens = GoogleModel.findByCode(model).getMaxTokens();
|
||||
|
||||
if (totalUsage <= modelMaxTokens) {
|
||||
return messages;
|
||||
}
|
||||
} catch (NoSuchElementException ex) {
|
||||
return messages;
|
||||
}
|
||||
return tryReducingGoogleMessagesOrThrow(messages, totalUsage, modelMaxTokens);
|
||||
}
|
||||
|
||||
private List<OpenAIChatCompletionMessage> tryReducingMessagesOrThrow(
|
||||
List<OpenAIChatCompletionMessage> messages,
|
||||
int totalUsage,
|
||||
|
|
@ -393,4 +566,29 @@ public class CompletionRequestProvider {
|
|||
|
||||
return messages.stream().filter(Objects::nonNull).toList();
|
||||
}
|
||||
|
||||
private List<GoogleCompletionContent> tryReducingGoogleMessagesOrThrow(
|
||||
List<GoogleCompletionContent> messages,
|
||||
int totalUsage,
|
||||
int modelMaxTokens) {
|
||||
if (!ConversationsState.getInstance().discardAllTokenLimits) {
|
||||
if (!conversation.isDiscardTokenLimit()) {
|
||||
throw new TotalUsageExceededException();
|
||||
}
|
||||
}
|
||||
|
||||
// skip the system prompt
|
||||
for (int i = 1; i < messages.size(); i++) {
|
||||
if (totalUsage <= modelMaxTokens) {
|
||||
break;
|
||||
}
|
||||
|
||||
var message = messages.get(i);
|
||||
totalUsage -= encodingManager.countMessageTokens(message.getRole(),
|
||||
String.join(",", message.getParts().stream().map(GoogleContentPart::getText).toList()));
|
||||
messages.set(i, null);
|
||||
}
|
||||
|
||||
return messages.stream().filter(Objects::nonNull).toList();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package ee.carlrobert.codegpt.completions;
|
||||
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.ANTHROPIC;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.AZURE;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.CUSTOM_OPENAI;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
|
||||
|
|
@ -10,8 +8,6 @@ import static ee.carlrobert.codegpt.settings.service.ServiceType.YOU;
|
|||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import ee.carlrobert.codegpt.codecompletions.CodeCompletionRequestFactory;
|
||||
import ee.carlrobert.codegpt.codecompletions.InfillRequestDetails;
|
||||
import ee.carlrobert.codegpt.completions.llama.LlamaModel;
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
|
|
@ -21,16 +17,25 @@ import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
|
|||
import ee.carlrobert.codegpt.settings.service.ServiceType;
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.google.GoogleSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.google.GoogleSettingsState;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import ee.carlrobert.llm.client.DeserializationUtil;
|
||||
import ee.carlrobert.llm.client.anthropic.completion.ClaudeCompletionRequest;
|
||||
import ee.carlrobert.llm.client.anthropic.completion.ClaudeCompletionStandardMessage;
|
||||
import ee.carlrobert.llm.client.google.completion.GoogleCompletionContent;
|
||||
import ee.carlrobert.llm.client.google.completion.GoogleCompletionRequest;
|
||||
import ee.carlrobert.llm.client.google.completion.GoogleGenerationConfig;
|
||||
import ee.carlrobert.llm.client.llama.completion.LlamaCompletionRequest;
|
||||
import ee.carlrobert.llm.client.ollama.completion.request.OllamaChatCompletionMessage;
|
||||
import ee.carlrobert.llm.client.ollama.completion.request.OllamaChatCompletionRequest;
|
||||
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionEventSourceListener;
|
||||
import ee.carlrobert.llm.client.openai.completion.OpenAITextCompletionEventSourceListener;
|
||||
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionRequest;
|
||||
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionRequest.Builder;
|
||||
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionStandardMessage;
|
||||
import ee.carlrobert.llm.client.openai.completion.response.OpenAIChatCompletionResponse;
|
||||
import ee.carlrobert.llm.client.openai.completion.response.OpenAIChatCompletionResponseChoice;
|
||||
|
|
@ -77,8 +82,18 @@ public final class CompletionRequestService {
|
|||
public EventSource getChatCompletionAsync(
|
||||
CallParameters callParameters,
|
||||
CompletionEventListener<String> eventListener) {
|
||||
var application = ApplicationManager.getApplication();
|
||||
var requestProvider = new CompletionRequestProvider(callParameters.getConversation());
|
||||
return switch (GeneralSettings.getCurrentState().getSelectedService()) {
|
||||
case CODEGPT -> CompletionClientProvider.getCodeGPTClient().getChatCompletionAsync(
|
||||
requestProvider.buildOpenAIChatCompletionRequest(
|
||||
application.getService(CodeGPTServiceSettings.class)
|
||||
.getState()
|
||||
.getChatCompletionSettings()
|
||||
.getModel(),
|
||||
callParameters),
|
||||
eventListener
|
||||
);
|
||||
case OPENAI -> CompletionClientProvider.getOpenAIClient().getChatCompletionAsync(
|
||||
requestProvider.buildOpenAIChatCompletionRequest(
|
||||
OpenAISettings.getCurrentState().getModel(),
|
||||
|
|
@ -86,8 +101,7 @@ public final class CompletionRequestService {
|
|||
eventListener);
|
||||
case CUSTOM_OPENAI -> getCustomOpenAIChatCompletionAsync(
|
||||
requestProvider.buildCustomOpenAIChatCompletionRequest(
|
||||
ApplicationManager.getApplication()
|
||||
.getService(CustomServiceSettings.class)
|
||||
application.getService(CustomServiceSettings.class)
|
||||
.getState()
|
||||
.getChatCompletionSettings(),
|
||||
callParameters),
|
||||
|
|
@ -106,27 +120,18 @@ public final class CompletionRequestService {
|
|||
callParameters.getMessage(),
|
||||
callParameters.getConversationType()),
|
||||
eventListener);
|
||||
};
|
||||
}
|
||||
|
||||
public EventSource getCodeCompletionAsync(
|
||||
InfillRequestDetails requestDetails,
|
||||
CompletionEventListener<String> eventListener) {
|
||||
var httpClient = CompletionClientProvider.getDefaultClientBuilder().build();
|
||||
return switch (GeneralSettings.getCurrentState().getSelectedService()) {
|
||||
case OPENAI -> CompletionClientProvider.getOpenAIClient()
|
||||
.getCompletionAsync(
|
||||
CodeCompletionRequestFactory.buildOpenAIRequest(requestDetails),
|
||||
eventListener);
|
||||
case CUSTOM_OPENAI -> EventSources.createFactory(httpClient).newEventSource(
|
||||
CodeCompletionRequestFactory.buildCustomRequest(requestDetails),
|
||||
new OpenAITextCompletionEventSourceListener(eventListener));
|
||||
case LLAMA_CPP -> CompletionClientProvider.getLlamaClient()
|
||||
.getChatCompletionAsync(
|
||||
CodeCompletionRequestFactory.buildLlamaRequest(requestDetails),
|
||||
eventListener);
|
||||
default ->
|
||||
throw new IllegalArgumentException("Code completion not supported for selected service");
|
||||
case OLLAMA -> CompletionClientProvider.getOllamaClient().getChatCompletionAsync(
|
||||
requestProvider.buildOllamaChatCompletionRequest(callParameters),
|
||||
eventListener);
|
||||
case GOOGLE -> {
|
||||
var settings = application.getService(GoogleSettings.class).getState();
|
||||
yield CompletionClientProvider.getGoogleClient().getChatCompletionAsync(
|
||||
requestProvider.buildGoogleChatCompletionRequest(
|
||||
settings.getModel(),
|
||||
callParameters),
|
||||
settings.getModel(),
|
||||
eventListener);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -135,13 +140,17 @@ public final class CompletionRequestService {
|
|||
String gitDiff,
|
||||
CompletionEventListener<String> eventListener) {
|
||||
var configuration = ConfigurationSettings.getCurrentState();
|
||||
var openaiRequest = new OpenAIChatCompletionRequest.Builder(List.of(
|
||||
var openaiRequest = new Builder(List.of(
|
||||
new OpenAIChatCompletionStandardMessage("system", systemPrompt),
|
||||
new OpenAIChatCompletionStandardMessage("user", gitDiff)))
|
||||
.setModel(OpenAISettings.getCurrentState().getModel())
|
||||
.build();
|
||||
var selectedService = GeneralSettings.getCurrentState().getSelectedService();
|
||||
switch (selectedService) {
|
||||
case CODEGPT:
|
||||
CompletionClientProvider.getCodeGPTClient()
|
||||
.getChatCompletionAsync(openaiRequest, eventListener);
|
||||
break;
|
||||
case OPENAI:
|
||||
CompletionClientProvider.getOpenAIClient()
|
||||
.getChatCompletionAsync(openaiRequest, eventListener);
|
||||
|
|
@ -191,6 +200,35 @@ public final class CompletionRequestService {
|
|||
.setRepeat_penalty(settings.getRepeatPenalty())
|
||||
.build(), eventListener);
|
||||
break;
|
||||
case OLLAMA:
|
||||
var model = ApplicationManager.getApplication()
|
||||
.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.getModel();
|
||||
var request = new OllamaChatCompletionRequest.Builder(
|
||||
model,
|
||||
List.of(
|
||||
new OllamaChatCompletionMessage("system", systemPrompt, null),
|
||||
new OllamaChatCompletionMessage("user", gitDiff, null)
|
||||
)
|
||||
).build();
|
||||
CompletionClientProvider.getOllamaClient().getChatCompletionAsync(request, eventListener);
|
||||
break;
|
||||
case GOOGLE:
|
||||
GoogleSettingsState state = ApplicationManager.getApplication()
|
||||
.getService(GoogleSettings.class).getState();
|
||||
CompletionClientProvider.getGoogleClient()
|
||||
.getChatCompletionAsync(new GoogleCompletionRequest.Builder(
|
||||
List.of(
|
||||
new GoogleCompletionContent("user", List.of(systemPrompt)),
|
||||
new GoogleCompletionContent("model", List.of("Understood.")),
|
||||
new GoogleCompletionContent("user", List.of(gitDiff))
|
||||
))
|
||||
.generationConfig(new GoogleGenerationConfig.Builder()
|
||||
.maxOutputTokens(configuration.getMaxTokens())
|
||||
.temperature(configuration.getTemperature()).build())
|
||||
.build(), state.getModel(), eventListener);
|
||||
break;
|
||||
default:
|
||||
LOG.debug("Unknown service: {}", selectedService);
|
||||
break;
|
||||
|
|
@ -226,19 +264,16 @@ public final class CompletionRequestService {
|
|||
}
|
||||
|
||||
public static boolean isRequestAllowed(ServiceType serviceType) {
|
||||
if (serviceType == OPENAI
|
||||
&& CredentialsStore.INSTANCE.isCredentialSet(CredentialKey.OPENAI_API_KEY)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var azureCredentialKey = AzureSettings.getCurrentState().isUseAzureApiKeyAuthentication()
|
||||
? CredentialKey.AZURE_OPENAI_API_KEY
|
||||
: CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN;
|
||||
if (serviceType == AZURE && CredentialsStore.INSTANCE.isCredentialSet(azureCredentialKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return List.of(LLAMA_CPP, ANTHROPIC, CUSTOM_OPENAI).contains(serviceType);
|
||||
return switch (serviceType) {
|
||||
case OPENAI -> CredentialsStore.INSTANCE.isCredentialSet(CredentialKey.OPENAI_API_KEY);
|
||||
case AZURE -> CredentialsStore.INSTANCE.isCredentialSet(
|
||||
AzureSettings.getCurrentState().isUseAzureApiKeyAuthentication()
|
||||
? CredentialKey.AZURE_OPENAI_API_KEY
|
||||
: CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN);
|
||||
case CODEGPT, CUSTOM_OPENAI, ANTHROPIC, LLAMA_CPP, OLLAMA -> true;
|
||||
case YOU -> false;
|
||||
case GOOGLE -> CredentialsStore.INSTANCE.isCredentialSet(CredentialKey.GOOGLE_API_KEY);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,67 +7,138 @@ import java.net.URL;
|
|||
|
||||
public enum HuggingFaceModel {
|
||||
|
||||
CODE_LLAMA_7B_Q3(7, 3, "CodeLlama-7B-Instruct-GGUF"),
|
||||
CODE_LLAMA_7B_Q4(7, 4, "CodeLlama-7B-Instruct-GGUF"),
|
||||
CODE_LLAMA_7B_Q5(7, 5, "CodeLlama-7B-Instruct-GGUF"),
|
||||
CODE_LLAMA_13B_Q3(13, 3, "CodeLlama-13B-Instruct-GGUF"),
|
||||
CODE_LLAMA_13B_Q4(13, 4, "CodeLlama-13B-Instruct-GGUF"),
|
||||
CODE_LLAMA_13B_Q5(13, 5, "CodeLlama-13B-Instruct-GGUF"),
|
||||
CODE_LLAMA_34B_Q3(34, 3, "CodeLlama-34B-Instruct-GGUF"),
|
||||
CODE_LLAMA_34B_Q4(34, 4, "CodeLlama-34B-Instruct-GGUF"),
|
||||
CODE_LLAMA_34B_Q5(34, 5, "CodeLlama-34B-Instruct-GGUF"),
|
||||
CODE_LLAMA_7B_Q3(7, 3, "CodeLlama-7B-Instruct-GGUF", "codellama-7b-instruct.Q3_K_M.gguf"),
|
||||
CODE_LLAMA_7B_Q4(7, 4, "CodeLlama-7B-Instruct-GGUF", "codellama-7b-instruct.Q4_K_M.gguf"),
|
||||
CODE_LLAMA_7B_Q5(7, 5, "CodeLlama-7B-Instruct-GGUF", "codellama-7b-instruct.Q5_K_M.gguf"),
|
||||
CODE_LLAMA_13B_Q3(13, 3, "CodeLlama-13B-Instruct-GGUF", "codellama-13b-instruct.Q3_K_M.gguf"),
|
||||
CODE_LLAMA_13B_Q4(13, 4, "CodeLlama-13B-Instruct-GGUF", "codellama-13b-instruct.Q4_K_M.gguf"),
|
||||
CODE_LLAMA_13B_Q5(13, 5, "CodeLlama-13B-Instruct-GGUF", "codellama-13b-instruct.Q5_K_M.gguf"),
|
||||
CODE_LLAMA_34B_Q3(34, 3, "CodeLlama-34B-Instruct-GGUF", "codellama-34b-instruct.Q3_K_M.gguf"),
|
||||
CODE_LLAMA_34B_Q4(34, 4, "CodeLlama-34B-Instruct-GGUF", "codellama-34b-instruct.Q4_K_M.gguf"),
|
||||
CODE_LLAMA_34B_Q5(34, 5, "CodeLlama-34B-Instruct-GGUF", "codellama-34b-instruct.Q5_K_M.gguf"),
|
||||
|
||||
CODE_BOOGA_34B_Q3(34, 3, "CodeBooga-34B-v0.1-GGUF"),
|
||||
CODE_BOOGA_34B_Q4(34, 4, "CodeBooga-34B-v0.1-GGUF"),
|
||||
CODE_BOOGA_34B_Q5(34, 5, "CodeBooga-34B-v0.1-GGUF"),
|
||||
CODE_BOOGA_34B_Q3(34, 3, "CodeBooga-34B-v0.1-GGUF", "codebooga-34b-v0.1.Q3_K_M.gguf"),
|
||||
CODE_BOOGA_34B_Q4(34, 4, "CodeBooga-34B-v0.1-GGUF", "codebooga-34b-v0.1.Q4_K_M.gguf"),
|
||||
CODE_BOOGA_34B_Q5(34, 5, "CodeBooga-34B-v0.1-GGUF", "codebooga-34b-v0.1.Q5_K_M.gguf"),
|
||||
|
||||
DEEPSEEK_CODER_1_3B_Q3(1, 3, "deepseek-coder-1.3b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_1_3B_Q4(1, 4, "deepseek-coder-1.3b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_1_3B_Q5(1, 5, "deepseek-coder-1.3b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_6_7B_Q3(7, 3, "deepseek-coder-6.7b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_6_7B_Q4(7, 4, "deepseek-coder-6.7b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_6_7B_Q5(7, 5, "deepseek-coder-6.7b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_33B_Q3(33, 3, "deepseek-coder-33b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_33B_Q4(33, 4, "deepseek-coder-33b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_33B_Q5(33, 5, "deepseek-coder-33b-instruct-GGUF"),
|
||||
DEEPSEEK_CODER_1_3B_Q3(1, 3, "deepseek-coder-1.3b-instruct-GGUF",
|
||||
"deepseek-coder-1.3b-instruct.Q3_K_M.gguf", 0.705),
|
||||
DEEPSEEK_CODER_1_3B_Q4(1, 4, "deepseek-coder-1.3b-instruct-GGUF",
|
||||
"deepseek-coder-1.3b-instruct.Q4_K_M.gguf", 0.874),
|
||||
DEEPSEEK_CODER_1_3B_Q5(1, 5, "deepseek-coder-1.3b-instruct-GGUF",
|
||||
"deepseek-coder-1.3b-instruct.Q5_K_M.gguf", 1.0),
|
||||
DEEPSEEK_CODER_6_7B_Q3(7, 3, "deepseek-coder-6.7b-instruct-GGUF",
|
||||
"deepseek-coder-6.7b-instruct.Q3_K_M.gguf"),
|
||||
DEEPSEEK_CODER_6_7B_Q4(7, 4, "deepseek-coder-6.7b-instruct-GGUF",
|
||||
"deepseek-coder-6.7b-instruct.Q4_K_M.gguf"),
|
||||
DEEPSEEK_CODER_6_7B_Q5(7, 5, "deepseek-coder-6.7b-instruct-GGUF",
|
||||
"deepseek-coder-6.7b-instruct.Q5_K_M.gguf"),
|
||||
DEEPSEEK_CODER_33B_Q3(33, 3, "deepseek-coder-33b-instruct-GGUF",
|
||||
"deepseek-coder-33b-instruct.Q3_K_M.gguf", 16.1),
|
||||
DEEPSEEK_CODER_33B_Q4(33, 4, "deepseek-coder-33b-instruct-GGUF",
|
||||
"deepseek-coder-33b-instruct.Q4_K_M.gguf", 19.9),
|
||||
DEEPSEEK_CODER_33B_Q5(33, 5, "deepseek-coder-33b-instruct-GGUF",
|
||||
"deepseek-coder-33b-instruct.Q5_K_M.gguf", 23.5),
|
||||
|
||||
PHIND_CODE_LLAMA_34B_Q3(34, 3, "Phind-CodeLlama-34B-v2-GGUF"),
|
||||
PHIND_CODE_LLAMA_34B_Q4(34, 4, "Phind-CodeLlama-34B-v2-GGUF"),
|
||||
PHIND_CODE_LLAMA_34B_Q5(34, 5, "Phind-CodeLlama-34B-v2-GGUF"),
|
||||
PHIND_CODE_LLAMA_34B_Q3(34, 3, "Phind-CodeLlama-34B-v2-GGUF",
|
||||
"phind-codellama-34b-v2.Q3_K_M.gguf"),
|
||||
PHIND_CODE_LLAMA_34B_Q4(34, 4, "Phind-CodeLlama-34B-v2-GGUF",
|
||||
"phind-codellama-34b-v2.Q4_K_M.gguf"),
|
||||
PHIND_CODE_LLAMA_34B_Q5(34, 5, "Phind-CodeLlama-34B-v2-GGUF",
|
||||
"phind-codellama-34b-v2.Q5_K_M.gguf"),
|
||||
|
||||
WIZARD_CODER_PYTHON_7B_Q3(7, 3, "WizardCoder-Python-7B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_7B_Q4(7, 4, "WizardCoder-Python-7B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_7B_Q5(7, 5, "WizardCoder-Python-7B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_13B_Q3(13, 3, "WizardCoder-Python-13B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_13B_Q4(13, 4, "WizardCoder-Python-13B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_13B_Q5(13, 5, "WizardCoder-Python-13B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_34B_Q3(34, 3, "WizardCoder-Python-34B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_34B_Q4(34, 4, "WizardCoder-Python-34B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_34B_Q5(34, 5, "WizardCoder-Python-34B-V1.0-GGUF"),
|
||||
WIZARD_CODER_PYTHON_7B_Q3(7, 3, "WizardCoder-Python-7B-V1.0-GGUF",
|
||||
"wizardcoder-python-7b-v1.0.Q3_K_M.gguf"),
|
||||
WIZARD_CODER_PYTHON_7B_Q4(7, 4, "WizardCoder-Python-7B-V1.0-GGUF",
|
||||
"wizardcoder-python-7b-v1.0.Q4_K_M.gguf"),
|
||||
WIZARD_CODER_PYTHON_7B_Q5(7, 5, "WizardCoder-Python-7B-V1.0-GGUF",
|
||||
"wizardcoder-python-7b-v1.0.Q5_K_M.gguf"),
|
||||
WIZARD_CODER_PYTHON_13B_Q3(13, 3, "WizardCoder-Python-13B-V1.0-GGUF",
|
||||
"wizardcoder-python-13b-v1.0.Q3_K_M.gguf"),
|
||||
WIZARD_CODER_PYTHON_13B_Q4(13, 4, "WizardCoder-Python-13B-V1.0-GGUF",
|
||||
"wizardcoder-python-13b-v1.0.Q4_K_M.gguf"),
|
||||
WIZARD_CODER_PYTHON_13B_Q5(13, 5, "WizardCoder-Python-13B-V1.0-GGUF",
|
||||
"wizardcoder-python-13b-v1.0.Q5_K_M.gguf"),
|
||||
WIZARD_CODER_PYTHON_34B_Q3(34, 3, "WizardCoder-Python-34B-V1.0-GGUF",
|
||||
"wizardcoder-python-34b-v1.0.Q3_K_M.gguf"),
|
||||
WIZARD_CODER_PYTHON_34B_Q4(34, 4, "WizardCoder-Python-34B-V1.0-GGUF",
|
||||
"wizardcoder-python-34b-v1.0.Q4_K_M.gguf"),
|
||||
WIZARD_CODER_PYTHON_34B_Q5(34, 5, "WizardCoder-Python-34B-V1.0-GGUF",
|
||||
"wizardcoder-python-34b-v1.0.Q5_K_M.gguf"),
|
||||
|
||||
LLAMA_3_8B_IQ3_M(8, 3, "Meta-Llama-3-8B-Instruct-IQ3_M.gguf", "lmstudio-community"),
|
||||
LLAMA_3_8B_Q4_K_M(8, 4, "Meta-Llama-3-8B-Instruct-Q4_K_M.gguf", "lmstudio-community"),
|
||||
LLAMA_3_8B_Q5_K_M(8, 5, "Meta-Llama-3-8B-Instruct-Q5_K_M.gguf", "lmstudio-community"),
|
||||
LLAMA_3_8B_Q6_K(8, 6, "Meta-Llama-3-8B-Instruct-Q6_K.gguf", "lmstudio-community"),
|
||||
LLAMA_3_8B_Q8_0(8, 8, "Meta-Llama-3-8B-Instruct-Q8_0.gguf", "lmstudio-community"),
|
||||
LLAMA_3_70B_IQ1(70, 1, "Meta-Llama-3-70B-Instruct-IQ1_M.gguf", "lmstudio-community"),
|
||||
LLAMA_3_70B_IQ2_XS(70, 2, "Meta-Llama-3-70B-Instruct-IQ2_XS.gguf", "lmstudio-community"),
|
||||
LLAMA_3_70B_Q4_K_M(70, 4, "Meta-Llama-3-70B-Instruct-Q4_K_M.gguf", "lmstudio-community");
|
||||
LLAMA_3_8B_IQ3_M(8, 3, "Meta-Llama-3-8B-Instruct-GGUF", "Meta-Llama-3-8B-Instruct-IQ3_M.gguf",
|
||||
"lmstudio-community", 3.78),
|
||||
LLAMA_3_8B_Q4_K_M(8, 4, "Meta-Llama-3-8B-Instruct-GGUF", "Meta-Llama-3-8B-Instruct-Q4_K_M.gguf",
|
||||
"lmstudio-community", 4.92),
|
||||
LLAMA_3_8B_Q5_K_M(8, 5, "Meta-Llama-3-8B-Instruct-GGUF", "Meta-Llama-3-8B-Instruct-Q5_K_M.gguf",
|
||||
"lmstudio-community", 5.73),
|
||||
LLAMA_3_8B_Q6_K(8, 6, "Meta-Llama-3-8B-Instruct-GGUF", "Meta-Llama-3-8B-Instruct-Q6_K.gguf",
|
||||
"lmstudio-community", 6.6),
|
||||
LLAMA_3_8B_Q8_0(8, 8, "Meta-Llama-3-8B-Instruct-GGUF", "Meta-Llama-3-8B-Instruct-Q8_0.gguf",
|
||||
"lmstudio-community", 8.54),
|
||||
LLAMA_3_70B_IQ1(70, 1, "Meta-Llama-3-70B-Instruct-GGUF", "Meta-Llama-3-70B-Instruct-IQ1_M.gguf",
|
||||
"lmstudio-community", 16.8),
|
||||
LLAMA_3_70B_IQ2_XS(70, 2, "Meta-Llama-3-70B-Instruct-GGUF",
|
||||
"Meta-Llama-3-70B-Instruct-IQ2_XS.gguf", "lmstudio-community", 21.1),
|
||||
LLAMA_3_70B_Q4_K_M(70, 4, "Meta-Llama-3-70B-Instruct-GGUF",
|
||||
"Meta-Llama-3-70B-Instruct-Q4_K_M.gguf", "lmstudio-community", 42.5),
|
||||
|
||||
PHI_3_3_8B_4K_IQ4_NL(4, 4, "Phi-3-mini-4k-instruct-GGUF", "Phi-3-mini-4k-instruct-IQ4_NL.gguf",
|
||||
"lmstudio-community", 2.18),
|
||||
PHI_3_3_8B_4K_Q5_K_M(4, 5, "Phi-3-mini-4k-instruct-GGUF", "Phi-3-mini-4k-instruct-Q5_K_M.gguf",
|
||||
"lmstudio-community", 2.64),
|
||||
PHI_3_3_8B_4K_Q6_K(4, 6, "Phi-3-mini-4k-instruct-GGUF", "Phi-3-mini-4k-instruct-Q6_K.gguf",
|
||||
"lmstudio-community", 3.14),
|
||||
PHI_3_3_8B_4K_Q8_0(4, 8, "Phi-3-mini-4k-instruct-GGUF", "Phi-3-mini-4k-instruct-Q8_0.gguf",
|
||||
"lmstudio-community", 4.06),
|
||||
PHI_3_3_8B_4K_FP16(4, 16, "Phi-3-mini-4k-instruct-GGUF", "Phi-3-mini-4k-instruct-fp16.gguf",
|
||||
"lmstudio-community", 7.64),
|
||||
|
||||
CODE_GEMMA_7B_Q3_K_L(7, 3, "codegemma-1.1-7b-it-GGUF", "codegemma-1.1-7b-it-Q3_K_L.gguf",
|
||||
"lmstudio-community", 4.71),
|
||||
CODE_GEMMA_7B_Q4_K_M(7, 4, "codegemma-1.1-7b-it-GGUF", "codegemma-1.1-7b-it-Q4_K_M.gguf",
|
||||
"lmstudio-community", 5.33),
|
||||
CODE_GEMMA_7B_Q5_K_M(7, 5, "codegemma-1.1-7b-it-GGUF", "codegemma-1.1-7b-it-Q5_K_M.gguf",
|
||||
"lmstudio-community", 6.14),
|
||||
CODE_GEMMA_7B_Q6_K(7, 6, "codegemma-1.1-7b-it-GGUF", "codegemma-1.1-7b-it-Q6_K.gguf",
|
||||
"lmstudio-community", 7.01),
|
||||
CODE_GEMMA_7B_Q8_0(7, 8, "codegemma-1.1-7b-it-GGUF", "codegemma-1.1-7b-it-Q8_0.gguf",
|
||||
"lmstudio-community", 9.08),
|
||||
|
||||
CODE_QWEN_1_5_7B_Q3_K_M(7, 3, "Qwen_-_CodeQwen1.5-7B-Chat-gguf",
|
||||
"CodeQwen1.5-7B-Chat.Q3_K_M.gguf", "RichardErkhov", 3.81),
|
||||
CODE_QWEN_1_5_7B_Q4_K_M(7, 4, "Qwen_-_CodeQwen1.5-7B-Chat-gguf",
|
||||
"CodeQwen1.5-7B-Chat.Q4_K_M.gguf", "RichardErkhov", 4.74),
|
||||
CODE_QWEN_1_5_7B_Q5_K_M(7, 5, "Qwen_-_CodeQwen1.5-7B-Chat-gguf",
|
||||
"CodeQwen1.5-7B-Chat.Q5_K_M.gguf", "RichardErkhov", 5.43),
|
||||
CODE_QWEN_1_5_7B_Q6_K(7, 6, "Qwen_-_CodeQwen1.5-7B-Chat-gguf",
|
||||
"CodeQwen1.5-7B-Chat.Q6_K.gguf", "RichardErkhov", 6.38),
|
||||
;
|
||||
|
||||
private final int parameterSize;
|
||||
private final int quantization;
|
||||
private final String modelName;
|
||||
private final String directory;
|
||||
private final String fileName;
|
||||
private final String user;
|
||||
private final Double downloadSize; // in GB
|
||||
|
||||
HuggingFaceModel(int parameterSize, int quantization, String modelName) {
|
||||
this(parameterSize, quantization, modelName, "TheBloke");
|
||||
HuggingFaceModel(int parameterSize, int quantization, String directory, String fileName) {
|
||||
this(parameterSize, quantization, directory, fileName, "TheBloke", null);
|
||||
}
|
||||
|
||||
HuggingFaceModel(int parameterSize, int quantization, String modelName, String user) {
|
||||
HuggingFaceModel(int parameterSize, int quantization, String directory, String fileName,
|
||||
Double downloadSize) {
|
||||
this(parameterSize, quantization, directory, fileName, "TheBloke", downloadSize);
|
||||
}
|
||||
|
||||
HuggingFaceModel(int parameterSize, int quantization, String directory, String fileName,
|
||||
String user, Double downloadSize) {
|
||||
this.parameterSize = parameterSize;
|
||||
this.quantization = quantization;
|
||||
this.modelName = modelName;
|
||||
this.directory = directory;
|
||||
this.fileName = fileName;
|
||||
this.user = user;
|
||||
this.downloadSize = downloadSize;
|
||||
}
|
||||
|
||||
public int getParameterSize() {
|
||||
|
|
@ -82,17 +153,18 @@ public enum HuggingFaceModel {
|
|||
return name();
|
||||
}
|
||||
|
||||
public Double getDownloadSize() {
|
||||
return downloadSize;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
if ("TheBloke".equals(user)) {
|
||||
return modelName.toLowerCase().replace("-gguf", format(".Q%d_K_M.gguf", quantization));
|
||||
}
|
||||
return modelName;
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public URL getFileURL() {
|
||||
try {
|
||||
return new URL(
|
||||
"https://huggingface.co/%s/%s/resolve/main/%s".formatted(user, getDirectory(), getFileName()));
|
||||
"https://huggingface.co/%s/%s/resolve/main/%s".formatted(user, directory, fileName));
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
|
@ -100,22 +172,13 @@ public enum HuggingFaceModel {
|
|||
|
||||
public URL getHuggingFaceURL() {
|
||||
try {
|
||||
return new URL("https://huggingface.co/%s/%s".formatted(user, getDirectory()));
|
||||
return new URL("https://huggingface.co/%s/%s".formatted(user, directory));
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDirectory() {
|
||||
if ("lmstudio-community".equals(user)) {
|
||||
// Meta-Llama-3-8B-Instruct-Q4_K_M.gguf -> Meta-Llama-3-8B-Instruct-GGUF
|
||||
return modelName.replaceFirst("-[^.-]+\\.gguf$", "-GGUF");
|
||||
}
|
||||
return modelName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public String getQuantizationLabel() {
|
||||
return format("%d-bit precision", quantization);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public enum LlamaModel {
|
|||
+ "support for large input contexts, and zero-shot instruction following ability for "
|
||||
+ "programming tasks.",
|
||||
PromptTemplate.LLAMA,
|
||||
InfillPromptTemplate.LLAMA,
|
||||
InfillPromptTemplate.CODE_LLAMA,
|
||||
List.of(
|
||||
HuggingFaceModel.CODE_LLAMA_7B_Q3,
|
||||
HuggingFaceModel.CODE_LLAMA_7B_Q4,
|
||||
|
|
@ -99,7 +99,52 @@ public enum LlamaModel {
|
|||
HuggingFaceModel.LLAMA_3_8B_Q8_0,
|
||||
HuggingFaceModel.LLAMA_3_70B_IQ1,
|
||||
HuggingFaceModel.LLAMA_3_70B_IQ2_XS,
|
||||
HuggingFaceModel.LLAMA_3_70B_Q4_K_M));
|
||||
HuggingFaceModel.LLAMA_3_70B_Q4_K_M)),
|
||||
PHI_3(
|
||||
"Phi-3 Mini",
|
||||
"Phi-3 Mini is a 3.8B parameters, lightweight, state-of-the-art open model. "
|
||||
+ "When assessed against benchmarks testing common sense, language understanding, math, "
|
||||
+ "code, long context and logical reasoning, Phi-3 Mini-4K-Instruct showcased a robust "
|
||||
+ "and state-of-the-art performance among models with less than 13 billion parameters.",
|
||||
PromptTemplate.PHI_3,
|
||||
List.of(
|
||||
HuggingFaceModel.PHI_3_3_8B_4K_IQ4_NL,
|
||||
HuggingFaceModel.PHI_3_3_8B_4K_Q5_K_M,
|
||||
HuggingFaceModel.PHI_3_3_8B_4K_Q6_K,
|
||||
HuggingFaceModel.PHI_3_3_8B_4K_Q8_0,
|
||||
HuggingFaceModel.PHI_3_3_8B_4K_FP16)),
|
||||
CODE_GEMMA(
|
||||
"CodeGemma Instruct",
|
||||
"CodeGemma Instruct is the first in a series of coding models released by Google. "
|
||||
+ "As an instruct model, it specializes in being asked coding related questions, but can "
|
||||
+ "also function as an autocomplete/fill-in-middle model for tools like co-pilot.\n"
|
||||
+ "This model is perfect for general coding questions or code generation.",
|
||||
PromptTemplate.CODE_GEMMA,
|
||||
InfillPromptTemplate.CODE_GEMMA,
|
||||
List.of(
|
||||
HuggingFaceModel.CODE_GEMMA_7B_Q3_K_L,
|
||||
HuggingFaceModel.CODE_GEMMA_7B_Q4_K_M,
|
||||
HuggingFaceModel.CODE_GEMMA_7B_Q5_K_M,
|
||||
HuggingFaceModel.CODE_GEMMA_7B_Q6_K,
|
||||
HuggingFaceModel.CODE_GEMMA_7B_Q8_0)),
|
||||
CODE_QWEN(
|
||||
"CodeQwen1.5", """
|
||||
A specialized codeLLM built upon the Qwen1.5 language model. \
|
||||
CodeQwen1.5-7B has been pretrained with around 3 trillion tokens of code-related data. \
|
||||
It supports an extensive repertoire of 92 programming languages, and it exhibits \
|
||||
exceptional capacity in long-context understanding and generation with the ability to \
|
||||
process information of 64K tokens. In terms of performance, CodeQwen1.5 demonstrates \
|
||||
impressive capabilities in basic code generation, long-context modelling, code editing \
|
||||
and SQL. We believe this model can significantly enhance developer productivity and \
|
||||
streamline software development workflows within diverse technological environments.""",
|
||||
PromptTemplate.CODE_QWEN,
|
||||
InfillPromptTemplate.CODE_QWEN,
|
||||
List.of(
|
||||
HuggingFaceModel.CODE_QWEN_1_5_7B_Q3_K_M,
|
||||
HuggingFaceModel.CODE_QWEN_1_5_7B_Q4_K_M,
|
||||
HuggingFaceModel.CODE_QWEN_1_5_7B_Q5_K_M,
|
||||
HuggingFaceModel.CODE_QWEN_1_5_7B_Q6_K)),
|
||||
;
|
||||
|
||||
private final String label;
|
||||
private final String description;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,67 @@ public enum PromptTemplate {
|
|||
.toString();
|
||||
}
|
||||
},
|
||||
PHI_3("Phi-3 Mini", List.of("<|end|>")) {
|
||||
@Override
|
||||
public String buildPrompt(String systemPrompt, String userPrompt, List<Message> history) {
|
||||
StringBuilder prompt = new StringBuilder();
|
||||
|
||||
for (Message message : history) {
|
||||
prompt.append("<|user|>\n")
|
||||
.append(message.getPrompt())
|
||||
.append("<|end|>\n<|assistant|>\n")
|
||||
.append(message.getResponse())
|
||||
.append("<|end|>\n");
|
||||
}
|
||||
|
||||
return prompt.append("<|user|>\n")
|
||||
.append(userPrompt)
|
||||
.append("<|end|>\n<|assistant|>")
|
||||
.toString();
|
||||
}
|
||||
},
|
||||
CODE_GEMMA("CodeGemma Instruct") {
|
||||
@Override
|
||||
public String buildPrompt(String systemPrompt, String userPrompt, List<Message> history) {
|
||||
StringBuilder prompt = new StringBuilder();
|
||||
|
||||
for (Message message : history) {
|
||||
prompt.append("<start_of_turn>user\n")
|
||||
.append(message.getPrompt())
|
||||
.append("<end_of_turn>\n<start_of_turn>model\n")
|
||||
.append(message.getResponse()).append("<end_of_turn>\n");
|
||||
}
|
||||
|
||||
return prompt.append("<start_of_turn>user\n")
|
||||
.append(userPrompt)
|
||||
.append("<end_of_turn>\n<start_of_turn>model\n")
|
||||
.toString();
|
||||
}
|
||||
},
|
||||
CODE_QWEN("CodeQwen1.5", List.of("<|endoftext|>")) {
|
||||
@Override
|
||||
public String buildPrompt(String systemPrompt, String userPrompt, List<Message> history) {
|
||||
StringBuilder prompt = new StringBuilder();
|
||||
|
||||
if (systemPrompt != null && !systemPrompt.isBlank()) {
|
||||
prompt.append("<|im_start|>system\n")
|
||||
.append(systemPrompt)
|
||||
.append("<|im_end|>\n");
|
||||
}
|
||||
|
||||
for (Message message : history) {
|
||||
prompt.append("<|im_start|>user\n")
|
||||
.append(message.getPrompt())
|
||||
.append("<|im_end|>\n<|im_start|>assistant\n")
|
||||
.append(message.getResponse()).append("<|im_end|>\n");
|
||||
}
|
||||
|
||||
return prompt.append("<|im_start|>user\n")
|
||||
.append(userPrompt)
|
||||
.append("<|im_end|>\n<|im_start|>assistant\n")
|
||||
.toString();
|
||||
}
|
||||
},
|
||||
ALPACA("Alpaca/Vicuna") {
|
||||
@Override
|
||||
public String buildPrompt(String systemPrompt, String userPrompt, List<Message> history) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class Conversation {
|
|||
}
|
||||
|
||||
public void setMessages(List<Message> messages) {
|
||||
this.messages = messages;
|
||||
this.messages = new ArrayList<>(messages);
|
||||
}
|
||||
|
||||
public String getClientCode() {
|
||||
|
|
@ -77,7 +77,7 @@ public class Conversation {
|
|||
}
|
||||
|
||||
public void removeMessage(UUID messageId) {
|
||||
setMessages(messages.stream()
|
||||
messages = new ArrayList<>(messages.stream()
|
||||
.filter(message -> !message.getId().equals(messageId))
|
||||
.toList());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ import ee.carlrobert.codegpt.settings.GeneralSettings;
|
|||
import ee.carlrobert.codegpt.settings.service.ServiceType;
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.google.GoogleSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -186,7 +189,12 @@ public final class ConversationService {
|
|||
}
|
||||
|
||||
private static String getModelForSelectedService(ServiceType serviceType) {
|
||||
var application = ApplicationManager.getApplication();
|
||||
return switch (serviceType) {
|
||||
case CODEGPT -> application.getService(CodeGPTServiceSettings.class)
|
||||
.getState()
|
||||
.getChatCompletionSettings()
|
||||
.getModel();
|
||||
case OPENAI -> OpenAISettings.getCurrentState().getModel();
|
||||
case CUSTOM_OPENAI -> "CustomService";
|
||||
case ANTHROPIC -> AnthropicSettings.getCurrentState().getModel();
|
||||
|
|
@ -195,9 +203,15 @@ public final class ConversationService {
|
|||
case LLAMA_CPP -> {
|
||||
var llamaSettings = LlamaSettings.getCurrentState();
|
||||
yield llamaSettings.isUseCustomModel()
|
||||
? llamaSettings.getCustomLlamaModelPath()
|
||||
: llamaSettings.getHuggingFaceModel().getCode();
|
||||
? llamaSettings.getCustomLlamaModelPath()
|
||||
: llamaSettings.getHuggingFaceModel().getCode();
|
||||
}
|
||||
case OLLAMA -> application.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.getModel();
|
||||
case GOOGLE -> application.getService(GoogleSettings.class)
|
||||
.getState()
|
||||
.getModel();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ import ee.carlrobert.codegpt.conversations.Conversation;
|
|||
import ee.carlrobert.codegpt.settings.service.ServiceType;
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.google.GoogleSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
|
@ -69,10 +72,18 @@ public class GeneralSettings implements PersistentStateComponent<GeneralSettings
|
|||
if ("you.chat.completion".equals(clientCode)) {
|
||||
state.setSelectedService(ServiceType.YOU);
|
||||
}
|
||||
if ("ollama.chat.completion".equals(clientCode)) {
|
||||
state.setSelectedService(ServiceType.OLLAMA);
|
||||
}
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
switch (state.getSelectedService()) {
|
||||
case CODEGPT:
|
||||
return ApplicationManager.getApplication().getService(CodeGPTServiceSettings.class)
|
||||
.getState()
|
||||
.getCodeCompletionSettings()
|
||||
.getModel();
|
||||
case OPENAI:
|
||||
return OpenAISettings.getCurrentState().getModel();
|
||||
case ANTHROPIC:
|
||||
|
|
@ -98,6 +109,16 @@ public class GeneralSettings implements PersistentStateComponent<GeneralSettings
|
|||
llamaModel.getLabel(),
|
||||
huggingFaceModel.getParameterSize(),
|
||||
huggingFaceModel.getQuantization());
|
||||
case OLLAMA:
|
||||
return ApplicationManager.getApplication()
|
||||
.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.getModel();
|
||||
case GOOGLE:
|
||||
return ApplicationManager.getApplication()
|
||||
.getService(GoogleSettings.class)
|
||||
.getState()
|
||||
.getModel();
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,121 +1,26 @@
|
|||
package ee.carlrobert.codegpt.settings;
|
||||
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.ANTHROPIC;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.AZURE;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.CUSTOM_OPENAI;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.YOU;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import com.intellij.util.ui.FormBuilder;
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType;
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettingsForm;
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettingsForm;
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceForm;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.form.LlamaSettingsForm;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettingsForm;
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettingsForm;
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Insets;
|
||||
import java.util.Arrays;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class GeneralSettingsComponent {
|
||||
|
||||
private final JPanel mainPanel;
|
||||
private final JBTextField displayNameField;
|
||||
private final ComboBox<ServiceType> serviceComboBox;
|
||||
private final OpenAISettingsForm openAISettingsForm;
|
||||
private final CustomServiceForm customConfigurationSettingsForm;
|
||||
private final AnthropicSettingsForm anthropicSettingsForm;
|
||||
private final AzureSettingsForm azureSettingsForm;
|
||||
private final YouSettingsForm youSettingsForm;
|
||||
private final LlamaSettingsForm llamaSettingsForm;
|
||||
|
||||
public GeneralSettingsComponent(Disposable parentDisposable, GeneralSettings settings) {
|
||||
public GeneralSettingsComponent(GeneralSettings settings) {
|
||||
displayNameField = new JBTextField(settings.getState().getDisplayName(), 20);
|
||||
openAISettingsForm = new OpenAISettingsForm(OpenAISettings.getCurrentState());
|
||||
customConfigurationSettingsForm = new CustomServiceForm();
|
||||
anthropicSettingsForm = new AnthropicSettingsForm(AnthropicSettings.getCurrentState());
|
||||
azureSettingsForm = new AzureSettingsForm(AzureSettings.getCurrentState());
|
||||
youSettingsForm = new YouSettingsForm(YouSettings.getCurrentState(), parentDisposable);
|
||||
llamaSettingsForm = new LlamaSettingsForm(LlamaSettings.getCurrentState());
|
||||
|
||||
var cardLayout = new DynamicCardLayout();
|
||||
var cards = new JPanel(cardLayout);
|
||||
cards.add(openAISettingsForm.getForm(), OPENAI.getCode());
|
||||
cards.add(customConfigurationSettingsForm.getForm(), CUSTOM_OPENAI.getCode());
|
||||
cards.add(anthropicSettingsForm.getForm(), ANTHROPIC.getCode());
|
||||
cards.add(azureSettingsForm.getForm(), AZURE.getCode());
|
||||
cards.add(youSettingsForm, YOU.getCode());
|
||||
cards.add(llamaSettingsForm, LLAMA_CPP.getCode());
|
||||
var serviceComboBoxModel = new DefaultComboBoxModel<ServiceType>();
|
||||
serviceComboBoxModel.addAll(Arrays.stream(ServiceType.values()).toList());
|
||||
serviceComboBox = new ComboBox<>(serviceComboBoxModel);
|
||||
serviceComboBox.setSelectedItem(OPENAI);
|
||||
serviceComboBox.setPreferredSize(displayNameField.getPreferredSize());
|
||||
serviceComboBox.addItemListener(e ->
|
||||
cardLayout.show(cards, ((ServiceType) e.getItem()).getCode()));
|
||||
mainPanel = FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.displayName.label"),
|
||||
displayNameField)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.label"),
|
||||
serviceComboBox)
|
||||
.addComponent(cards)
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel();
|
||||
}
|
||||
|
||||
public OpenAISettingsForm getOpenAISettingsForm() {
|
||||
return openAISettingsForm;
|
||||
}
|
||||
|
||||
public CustomServiceForm getCustomConfigurationSettingsForm() {
|
||||
return customConfigurationSettingsForm;
|
||||
}
|
||||
|
||||
public AnthropicSettingsForm getAnthropicSettingsForm() {
|
||||
return anthropicSettingsForm;
|
||||
}
|
||||
|
||||
public AzureSettingsForm getAzureSettingsForm() {
|
||||
return azureSettingsForm;
|
||||
}
|
||||
|
||||
public LlamaSettingsForm getLlamaSettingsForm() {
|
||||
return llamaSettingsForm;
|
||||
}
|
||||
|
||||
public YouSettingsForm getYouSettingsForm() {
|
||||
return youSettingsForm;
|
||||
}
|
||||
|
||||
public ServiceType getSelectedService() {
|
||||
return serviceComboBox.getItem();
|
||||
}
|
||||
|
||||
public void setSelectedService(ServiceType serviceType) {
|
||||
serviceComboBox.setSelectedItem(serviceType);
|
||||
}
|
||||
|
||||
public JPanel getPanel() {
|
||||
return mainPanel;
|
||||
return FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.displayName.label"),
|
||||
displayNameField)
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel();
|
||||
}
|
||||
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
|
|
@ -129,38 +34,4 @@ public class GeneralSettingsComponent {
|
|||
public void setDisplayName(String displayName) {
|
||||
displayNameField.setText(displayName);
|
||||
}
|
||||
|
||||
public void resetForms() {
|
||||
openAISettingsForm.resetForm();
|
||||
customConfigurationSettingsForm.resetForm();
|
||||
anthropicSettingsForm.resetForm();
|
||||
azureSettingsForm.resetForm();
|
||||
youSettingsForm.resetForm();
|
||||
llamaSettingsForm.resetForm();
|
||||
}
|
||||
|
||||
static class DynamicCardLayout extends CardLayout {
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent) {
|
||||
Component current = findVisibleComponent(parent);
|
||||
if (current != null) {
|
||||
Insets insets = parent.getInsets();
|
||||
Dimension preferredSize = current.getPreferredSize();
|
||||
preferredSize.width += insets.left + insets.right;
|
||||
preferredSize.height += insets.top + insets.bottom;
|
||||
return preferredSize;
|
||||
}
|
||||
return super.preferredLayoutSize(parent);
|
||||
}
|
||||
|
||||
private Component findVisibleComponent(Container parent) {
|
||||
for (Component comp : parent.getComponents()) {
|
||||
if (comp.isVisible()) {
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +1,13 @@
|
|||
package ee.carlrobert.codegpt.settings;
|
||||
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.ANTHROPIC_API_KEY;
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN;
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_OPENAI_API_KEY;
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CUSTOM_SERVICE_API_KEY;
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.LLAMA_API_KEY;
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
import ee.carlrobert.codegpt.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettingsForm;
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettingsForm;
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceForm;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.form.LlamaSettingsForm;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettingsForm;
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettingsForm;
|
||||
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.ChatToolWindowContentManager;
|
||||
import ee.carlrobert.codegpt.util.ApplicationUtil;
|
||||
import javax.swing.JComponent;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class GeneralSettingsConfigurable implements Configurable {
|
||||
|
||||
private Disposable parentDisposable;
|
||||
|
||||
private GeneralSettingsComponent component;
|
||||
|
||||
@Nls(capitalization = Nls.Capitalization.Title)
|
||||
|
|
@ -51,111 +24,23 @@ public class GeneralSettingsConfigurable implements Configurable {
|
|||
@Nullable
|
||||
@Override
|
||||
public JComponent createComponent() {
|
||||
var settings = GeneralSettings.getInstance();
|
||||
parentDisposable = Disposer.newDisposable();
|
||||
component = new GeneralSettingsComponent(parentDisposable, settings);
|
||||
component = new GeneralSettingsComponent(GeneralSettings.getInstance());
|
||||
return component.getPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
var settings = GeneralSettings.getCurrentState();
|
||||
|
||||
return !component.getDisplayName().equals(settings.getDisplayName())
|
||||
|| component.getSelectedService() != settings.getSelectedService()
|
||||
|| OpenAISettings.getInstance().isModified(component.getOpenAISettingsForm())
|
||||
|| component.getCustomConfigurationSettingsForm().isModified()
|
||||
|| AnthropicSettings.getInstance().isModified(component.getAnthropicSettingsForm())
|
||||
|| AzureSettings.getInstance().isModified(component.getAzureSettingsForm())
|
||||
|| YouSettings.getInstance().isModified(component.getYouSettingsForm())
|
||||
|| LlamaSettings.getInstance().isModified(component.getLlamaSettingsForm());
|
||||
return !component.getDisplayName().equals(settings.getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
var settings = GeneralSettings.getCurrentState();
|
||||
settings.setDisplayName(component.getDisplayName());
|
||||
settings.setSelectedService(component.getSelectedService());
|
||||
|
||||
var openAISettingsForm = component.getOpenAISettingsForm();
|
||||
applyOpenAISettings(openAISettingsForm);
|
||||
applyCustomOpenAISettings(component.getCustomConfigurationSettingsForm());
|
||||
applyAnthropicSettings(component.getAnthropicSettingsForm());
|
||||
applyAzureSettings(component.getAzureSettingsForm());
|
||||
applyYouSettings(component.getYouSettingsForm());
|
||||
applyLlamaSettings(component.getLlamaSettingsForm());
|
||||
|
||||
var serviceChanged = component.getSelectedService() != settings.getSelectedService();
|
||||
var modelChanged = !OpenAISettings.getCurrentState().getModel()
|
||||
.equals(openAISettingsForm.getModel());
|
||||
if (serviceChanged || modelChanged) {
|
||||
resetActiveTab();
|
||||
if (serviceChanged) {
|
||||
TelemetryAction.SETTINGS_CHANGED.createActionMessage()
|
||||
.property("service", component.getSelectedService().getCode().toLowerCase())
|
||||
.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyOpenAISettings(OpenAISettingsForm form) {
|
||||
CredentialsStore.INSTANCE.setCredential(OPENAI_API_KEY, form.getApiKey());
|
||||
OpenAISettings.getInstance().loadState(form.getCurrentState());
|
||||
}
|
||||
|
||||
private void applyCustomOpenAISettings(CustomServiceForm form) {
|
||||
CredentialsStore.INSTANCE.setCredential(CUSTOM_SERVICE_API_KEY, form.getApiKey());
|
||||
form.applyChanges();
|
||||
}
|
||||
|
||||
private void applyLlamaSettings(LlamaSettingsForm form) {
|
||||
CredentialsStore.INSTANCE.setCredential(
|
||||
LLAMA_API_KEY,
|
||||
form.getLlamaServerPreferencesForm().getApiKey());
|
||||
|
||||
LlamaSettings.getInstance().loadState(form.getCurrentState());
|
||||
}
|
||||
|
||||
private void applyYouSettings(YouSettingsForm form) {
|
||||
YouSettings.getInstance().loadState(form.getCurrentState());
|
||||
}
|
||||
|
||||
private void applyAnthropicSettings(AnthropicSettingsForm form) {
|
||||
CredentialsStore.INSTANCE.setCredential(ANTHROPIC_API_KEY, form.getApiKey());
|
||||
AnthropicSettings.getInstance().loadState(form.getCurrentState());
|
||||
}
|
||||
|
||||
private void applyAzureSettings(AzureSettingsForm form) {
|
||||
AzureSettings.getInstance().loadState(form.getCurrentState());
|
||||
CredentialsStore.INSTANCE.setCredential(AZURE_OPENAI_API_KEY, form.getApiKey());
|
||||
CredentialsStore.INSTANCE.setCredential(
|
||||
AZURE_ACTIVE_DIRECTORY_TOKEN,
|
||||
form.getActiveDirectoryToken());
|
||||
GeneralSettings.getCurrentState().setDisplayName(component.getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
var settings = GeneralSettings.getCurrentState();
|
||||
component.setDisplayName(settings.getDisplayName());
|
||||
component.setSelectedService(settings.getSelectedService());
|
||||
component.resetForms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeUIResources() {
|
||||
if (parentDisposable != null) {
|
||||
Disposer.dispose(parentDisposable);
|
||||
}
|
||||
component = null;
|
||||
}
|
||||
|
||||
private void resetActiveTab() {
|
||||
ConversationsState.getInstance().setCurrentConversation(null);
|
||||
var project = ApplicationUtil.findCurrentProject();
|
||||
if (project == null) {
|
||||
throw new RuntimeException("Could not find current project.");
|
||||
}
|
||||
|
||||
project.getService(ChatToolWindowContentManager.class).resetAll();
|
||||
component.setDisplayName(GeneralSettings.getCurrentState().getDisplayName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import ee.carlrobert.codegpt.settings.service.ServiceType;
|
|||
public class GeneralSettingsState {
|
||||
|
||||
private String displayName = "";
|
||||
private ServiceType selectedService = ServiceType.OPENAI;
|
||||
private ServiceType selectedService = ServiceType.CODEGPT;
|
||||
|
||||
public String getDisplayName() {
|
||||
if (displayName == null || displayName.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -190,7 +190,12 @@ public class ConfigurationComponent {
|
|||
private JPanel createTablePanel() {
|
||||
return ToolbarDecorator.createDecorator(table)
|
||||
.setPreferredSize(new Dimension(table.getPreferredSize().width, 140))
|
||||
.setAddAction(anActionButton -> getModel().addRow(new Object[]{"", ""}))
|
||||
.setAddAction(anActionButton -> {
|
||||
getModel().addRow(new Object[]{"", ""});
|
||||
int lastRowIndex = getModel().getRowCount() - 1;
|
||||
table.changeSelection(lastRowIndex, 0, false, false);
|
||||
table.editCellAt(lastRowIndex, 0);
|
||||
})
|
||||
.setRemoveAction(anActionButton -> getModel().removeRow(table.getSelectedRow()))
|
||||
.disableUpAction()
|
||||
.disableDownAction()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.intellij.openapi.Disposable;
|
|||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
import ee.carlrobert.codegpt.actions.editor.EditorActionsUtil;
|
||||
import javax.swing.JComponent;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -39,6 +40,7 @@ public class ConfigurationConfigurable implements Configurable {
|
|||
@Override
|
||||
public void apply() {
|
||||
ConfigurationSettings.getInstance().loadState(component.getCurrentFormState());
|
||||
EditorActionsUtil.refreshActions();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@ package ee.carlrobert.codegpt.settings.service;
|
|||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
|
||||
public enum ServiceType {
|
||||
CODEGPT("CODEGPT", "service.codegpt.title", "codegpt.chat.completion"),
|
||||
OPENAI("OPENAI", "service.openai.title", "chat.completion"),
|
||||
CUSTOM_OPENAI("CUSTOM_OPENAI", "service.custom.openai.title", "custom.openai.chat.completion"),
|
||||
ANTHROPIC("ANTHROPIC", "service.anthropic.title", "anthropic.chat.completion"),
|
||||
AZURE("AZURE", "service.azure.title", "azure.chat.completion"),
|
||||
GOOGLE("GOOGLE", "service.google.title", "google.chat.completion"),
|
||||
YOU("YOU", "service.you.title", "you.chat.completion"),
|
||||
LLAMA_CPP("LLAMA_CPP", "service.llama.title", "llama.chat.completion");
|
||||
LLAMA_CPP("LLAMA_CPP", "service.llama.title", "llama.chat.completion"),
|
||||
OLLAMA("OLLAMA", "service.ollama.title", "ollama.chat.completion");
|
||||
|
||||
private final String code;
|
||||
private final String label;
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@ import com.intellij.openapi.application.ApplicationManager;
|
|||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@State(name = "CodeGPT_AnthropicSettings", storages = @Storage("CodeGPT_AnthropicSettings.xml"))
|
||||
|
|
@ -32,11 +29,4 @@ public class AnthropicSettings implements PersistentStateComponent<AnthropicSett
|
|||
public static AnthropicSettings getInstance() {
|
||||
return ApplicationManager.getApplication().getService(AnthropicSettings.class);
|
||||
}
|
||||
|
||||
public boolean isModified(AnthropicSettingsForm form) {
|
||||
return !form.getCurrentState().equals(state)
|
||||
|| !StringUtils.equals(
|
||||
form.getApiKey(),
|
||||
CredentialsStore.INSTANCE.getCredential(CredentialKey.ANTHROPIC_API_KEY));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
package ee.carlrobert.codegpt.settings.service.anthropic;
|
||||
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.ANTHROPIC_API_KEY;
|
||||
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
|
||||
|
||||
import com.intellij.ui.TitledSeparator;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.ui.components.JBPasswordField;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import com.intellij.util.ui.FormBuilder;
|
||||
|
|
@ -12,6 +11,7 @@ import ee.carlrobert.codegpt.CodeGPTBundle;
|
|||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.ui.UIUtil;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AnthropicSettingsForm {
|
||||
|
|
@ -23,15 +23,17 @@ public class AnthropicSettingsForm {
|
|||
public AnthropicSettingsForm(AnthropicSettingsState settings) {
|
||||
apiKeyField = new JBPasswordField();
|
||||
apiKeyField.setColumns(30);
|
||||
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(ANTHROPIC_API_KEY));
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
var apiKey = CredentialsStore.getCredential(ANTHROPIC_API_KEY);
|
||||
SwingUtilities.invokeLater(() -> apiKeyField.setText(apiKey));
|
||||
});
|
||||
apiVersionField = new JBTextField(settings.getApiVersion(), 35);
|
||||
modelField = new JBTextField(settings.getModel(), 35);
|
||||
}
|
||||
|
||||
public JPanel getForm() {
|
||||
return FormBuilder.createFormBuilder()
|
||||
.addComponent(new TitledSeparator(CodeGPTBundle.get("shared.configuration")))
|
||||
.addComponent(withEmptyLeftBorder(UI.PanelFactory.grid()
|
||||
.addComponent(UI.PanelFactory.grid()
|
||||
.add(UI.PanelFactory.panel(apiKeyField)
|
||||
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
|
||||
.resizeX(false)
|
||||
|
|
@ -49,7 +51,7 @@ public class AnthropicSettingsForm {
|
|||
.withComment(CodeGPTBundle.get(
|
||||
"settingsConfigurable.service.anthropic.model.comment"))
|
||||
.resizeX(false))
|
||||
.createPanel()))
|
||||
.createPanel())
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel();
|
||||
}
|
||||
|
|
@ -63,7 +65,7 @@ public class AnthropicSettingsForm {
|
|||
|
||||
public void resetForm() {
|
||||
var state = AnthropicSettings.getCurrentState();
|
||||
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(ANTHROPIC_API_KEY));
|
||||
apiKeyField.setText(CredentialsStore.getCredential(ANTHROPIC_API_KEY));
|
||||
apiVersionField.setText(state.getApiVersion());
|
||||
modelField.setText(state.getModel());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
package ee.carlrobert.codegpt.settings.service.azure;
|
||||
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN;
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_OPENAI_API_KEY;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@State(name = "CodeGPT_AzureSettings_210", storages = @Storage("CodeGPT_AzureSettings_210.xml"))
|
||||
|
|
@ -34,14 +29,4 @@ public class AzureSettings implements PersistentStateComponent<AzureSettingsStat
|
|||
public static AzureSettings getInstance() {
|
||||
return ApplicationManager.getApplication().getService(AzureSettings.class);
|
||||
}
|
||||
|
||||
public boolean isModified(AzureSettingsForm form) {
|
||||
return !form.getCurrentState().equals(state)
|
||||
|| !StringUtils.equals(
|
||||
form.getActiveDirectoryToken(),
|
||||
CredentialsStore.INSTANCE.getCredential(AZURE_ACTIVE_DIRECTORY_TOKEN))
|
||||
|| !StringUtils.equals(
|
||||
form.getApiKey(),
|
||||
CredentialsStore.INSTANCE.getCredential(AZURE_OPENAI_API_KEY));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package ee.carlrobert.codegpt.settings.service.azure;
|
|||
|
||||
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.ui.TitledSeparator;
|
||||
import com.intellij.ui.components.JBPasswordField;
|
||||
import com.intellij.ui.components.JBRadioButton;
|
||||
|
|
@ -15,6 +16,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AzureSettingsForm {
|
||||
|
|
@ -38,16 +40,20 @@ public class AzureSettingsForm {
|
|||
settings.isUseAzureActiveDirectoryAuthentication());
|
||||
azureApiKeyField = new JBPasswordField();
|
||||
azureApiKeyField.setColumns(30);
|
||||
azureApiKeyField.setText(
|
||||
CredentialsStore.INSTANCE.getCredential(CredentialKey.AZURE_OPENAI_API_KEY));
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
var apiKey = CredentialsStore.getCredential(CredentialKey.AZURE_OPENAI_API_KEY);
|
||||
SwingUtilities.invokeLater(() -> azureApiKeyField.setText(apiKey));
|
||||
});
|
||||
azureApiKeyFieldPanel = UI.PanelFactory.panel(azureApiKeyField)
|
||||
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
|
||||
.resizeX(false)
|
||||
.createPanel();
|
||||
azureActiveDirectoryTokenField = new JBPasswordField();
|
||||
azureActiveDirectoryTokenField.setColumns(30);
|
||||
azureActiveDirectoryTokenField.setText(
|
||||
CredentialsStore.INSTANCE.getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN));
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
var apiKey = CredentialsStore.getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN);
|
||||
SwingUtilities.invokeLater(() -> azureActiveDirectoryTokenField.setText(apiKey));
|
||||
});
|
||||
azureActiveDirectoryTokenFieldPanel = UI.PanelFactory.panel(azureActiveDirectoryTokenField)
|
||||
.withLabel(CodeGPTBundle.get("settingsConfigurable.service.azure.bearerToken.label"))
|
||||
.resizeX(false)
|
||||
|
|
@ -119,10 +125,9 @@ public class AzureSettingsForm {
|
|||
|
||||
public void resetForm() {
|
||||
var state = AzureSettings.getCurrentState();
|
||||
azureApiKeyField.setText(
|
||||
CredentialsStore.INSTANCE.getCredential(CredentialKey.AZURE_OPENAI_API_KEY));
|
||||
azureApiKeyField.setText(CredentialsStore.getCredential(CredentialKey.AZURE_OPENAI_API_KEY));
|
||||
azureActiveDirectoryTokenField.setText(
|
||||
CredentialsStore.INSTANCE.getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN));
|
||||
CredentialsStore.getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN));
|
||||
useAzureApiKeyAuthenticationRadioButton.setSelected(state.isUseAzureApiKeyAuthentication());
|
||||
useAzureActiveDirectoryAuthenticationRadioButton.setSelected(
|
||||
state.isUseAzureActiveDirectoryAuthentication());
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ import java.util.Map.Entry;
|
|||
import javax.swing.JPanel;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
class CustomServiceFormTabbedPane extends JBTabbedPane {
|
||||
public class CustomServiceFormTabbedPane extends JBTabbedPane {
|
||||
|
||||
private final JBTable headersTable;
|
||||
private final JBTable bodyTable;
|
||||
|
||||
CustomServiceFormTabbedPane(Map<String, String> headers, Map<String, ?> body) {
|
||||
public CustomServiceFormTabbedPane(Map<String, String> headers, Map<String, ?> body) {
|
||||
headersTable = new JBTable(
|
||||
new DefaultTableModel(toArray(headers),
|
||||
new Object[]{"Key", "Value"}));
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import com.intellij.openapi.application.ApplicationManager;
|
|||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate;
|
||||
import ee.carlrobert.codegpt.completions.HuggingFaceModel;
|
||||
import ee.carlrobert.codegpt.completions.llama.LlamaModel;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.form.LlamaSettingsForm;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
|
@ -25,12 +28,32 @@ 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_LLAMA_7B_Q4);
|
||||
}
|
||||
if (this.state.getRemoteModelInfillPromptTemplate() == null) {
|
||||
this.state.setRemoteModelInfillPromptTemplate(InfillPromptTemplate.CODE_LLAMA);
|
||||
}
|
||||
if (this.state.getLocalModelPromptTemplate() == null) {
|
||||
this.state.setLocalModelInfillPromptTemplate(InfillPromptTemplate.CODE_LLAMA);
|
||||
}
|
||||
}
|
||||
|
||||
public static LlamaSettingsState getCurrentState() {
|
||||
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;
|
||||
}
|
||||
|
||||
public static LlamaSettings getInstance() {
|
||||
return ApplicationManager.getApplication().getService(LlamaSettings.class);
|
||||
}
|
||||
|
|
@ -39,6 +62,6 @@ public class LlamaSettings implements PersistentStateComponent<LlamaSettingsStat
|
|||
return !form.getCurrentState().equals(state)
|
||||
|| !StringUtils.equals(
|
||||
form.getLlamaServerPreferencesForm().getApiKey(),
|
||||
CredentialsStore.INSTANCE.getCredential(LLAMA_API_KEY));
|
||||
CredentialsStore.getCredential(LLAMA_API_KEY));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ public class LlamaSettingsState {
|
|||
private HuggingFaceModel huggingFaceModel = HuggingFaceModel.CODE_LLAMA_7B_Q4;
|
||||
private PromptTemplate localModelPromptTemplate = PromptTemplate.LLAMA;
|
||||
private PromptTemplate remoteModelPromptTemplate = PromptTemplate.LLAMA;
|
||||
private InfillPromptTemplate localModelInfillPromptTemplate = InfillPromptTemplate.LLAMA;
|
||||
private InfillPromptTemplate remoteModelInfillPromptTemplate = InfillPromptTemplate.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;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package ee.carlrobert.codegpt.settings.service.llama.form;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
import com.intellij.icons.AllIcons.Actions;
|
||||
import com.intellij.icons.AllIcons.General;
|
||||
|
|
@ -32,6 +33,7 @@ import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
|||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.io.File;
|
||||
|
|
@ -40,6 +42,8 @@ import javax.swing.Box;
|
|||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
@ -105,7 +109,7 @@ public class LlamaModelPreferencesForm {
|
|||
huggingFaceComboBoxModel),
|
||||
BorderLayout.WEST);
|
||||
modelDetailsLabel = new JBLabel();
|
||||
huggingFaceModelComboBox = createHuggingFaceComboBox(
|
||||
huggingFaceModelComboBox = createModelQuantizationComboBox(
|
||||
huggingFaceComboBoxModel,
|
||||
modelExistsIcon,
|
||||
modelDetailsLabel,
|
||||
|
|
@ -291,15 +295,15 @@ public class LlamaModelPreferencesForm {
|
|||
int parameterSize = model.getParameterSize();
|
||||
int quantization = model.getQuantization();
|
||||
|
||||
if (!modelDetailsMap.containsKey(parameterSize)) {
|
||||
var details = modelDetailsMap.getOrDefault(parameterSize, emptyMap()).get(quantization);
|
||||
if (details == null && model.getDownloadSize() == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
ModelDetails details = modelDetailsMap.get(parameterSize).get(quantization);
|
||||
if (details == null) {
|
||||
return "";
|
||||
return format("<html>"
|
||||
+ "<p style=\"margin: 0\"><small>File Size: <strong>%.2f GB</strong></small></p>"
|
||||
+ "</html>", model.getDownloadSize());
|
||||
}
|
||||
|
||||
return format("<html>"
|
||||
+ "<p style=\"margin: 0\"><small>File Size: <strong>%.2f GB</strong></small></p>"
|
||||
+ "<p style=\"margin: 0\"><small>Max RAM Required: <strong>%.2f GB</strong></small></p>"
|
||||
|
|
@ -364,7 +368,7 @@ public class LlamaModelPreferencesForm {
|
|||
return comboBox;
|
||||
}
|
||||
|
||||
private ComboBox<HuggingFaceModel> createHuggingFaceComboBox(
|
||||
private ComboBox<HuggingFaceModel> createModelQuantizationComboBox(
|
||||
DefaultComboBoxModel<HuggingFaceModel> huggingFaceComboBoxModel,
|
||||
JBLabel modelExistsIcon,
|
||||
JBLabel modelDetailsLabel,
|
||||
|
|
@ -379,6 +383,17 @@ public class LlamaModelPreferencesForm {
|
|||
modelExistsIcon.setVisible(modelExists);
|
||||
downloadModelActionLinkWrapper.setVisible(!modelExists);
|
||||
});
|
||||
comboBox.setRenderer(new DefaultListCellRenderer() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
Object item = value;
|
||||
if (item instanceof HuggingFaceModel) {
|
||||
item = ((HuggingFaceModel) item).getQuantizationLabel();
|
||||
}
|
||||
return super.getListCellRendererComponent(list, item, index, isSelected, cellHasFocus);
|
||||
}
|
||||
});
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ 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.LlamaSettingsState;
|
||||
import ee.carlrobert.codegpt.ui.OverlayUtil;
|
||||
import ee.carlrobert.codegpt.ui.UIUtil;
|
||||
|
|
@ -40,6 +41,7 @@ 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 {
|
||||
|
|
@ -86,7 +88,10 @@ public class LlamaServerPreferencesForm {
|
|||
baseHostField = new JBTextField(settings.getBaseHost(), 30);
|
||||
apiKeyField = new JBPasswordField();
|
||||
apiKeyField.setColumns(30);
|
||||
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(LLAMA_API_KEY));
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
var apiKey = CredentialsStore.getCredential(CredentialKey.LLAMA_API_KEY);
|
||||
SwingUtilities.invokeLater(() -> apiKeyField.setText(apiKey));
|
||||
});
|
||||
|
||||
llamaModelPreferencesForm = new LlamaModelPreferencesForm();
|
||||
runLocalServerRadioButton = new JBRadioButton("Run local server",
|
||||
|
|
@ -131,7 +136,7 @@ public class LlamaServerPreferencesForm {
|
|||
additionalBuildParametersField.setText(state.getAdditionalBuildParameters());
|
||||
remotePromptTemplatePanel.setPromptTemplate(state.getRemoteModelPromptTemplate()); // ?
|
||||
infillPromptTemplatePanel.setPromptTemplate(state.getRemoteModelInfillPromptTemplate());
|
||||
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(LLAMA_API_KEY));
|
||||
apiKeyField.setText(CredentialsStore.getCredential(LLAMA_API_KEY));
|
||||
}
|
||||
|
||||
public JComponent createUseExistingServerForm() {
|
||||
|
|
@ -189,17 +194,17 @@ public class LlamaServerPreferencesForm {
|
|||
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"))
|
||||
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)
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel()))
|
||||
|
|
@ -354,9 +359,9 @@ public class LlamaServerPreferencesForm {
|
|||
|
||||
public List<String> getListOfAdditionalParameters() {
|
||||
return Arrays.stream(additionalParametersField.getText().split(","))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isBlank())
|
||||
.toList();
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isBlank())
|
||||
.toList();
|
||||
}
|
||||
|
||||
public String getAdditionalBuildParameters() {
|
||||
|
|
@ -365,9 +370,9 @@ public class LlamaServerPreferencesForm {
|
|||
|
||||
public List<String> getListOfAdditionalBuildParameters() {
|
||||
return Arrays.stream(additionalBuildParametersField.getText().split(","))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isBlank())
|
||||
.toList();
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isBlank())
|
||||
.toList();
|
||||
}
|
||||
|
||||
public PromptTemplate getPromptTemplate() {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ public class LlamaSettingsForm extends JPanel {
|
|||
llamaRequestPreferencesForm = new LlamaRequestPreferencesForm(settings);
|
||||
codeCompletionConfigurationForm = new CodeCompletionConfigurationForm(
|
||||
settings.isCodeCompletionsEnabled(),
|
||||
settings.getCodeCompletionMaxTokens());
|
||||
settings.getCodeCompletionMaxTokens(),
|
||||
null);
|
||||
init();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
package ee.carlrobert.codegpt.settings.service.openai;
|
||||
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@State(name = "CodeGPT_OpenAISettings_210", storages = @Storage("CodeGPT_OpenAISettings_210.xml"))
|
||||
|
|
@ -33,11 +29,4 @@ public class OpenAISettings implements PersistentStateComponent<OpenAISettingsSt
|
|||
public static OpenAISettings getInstance() {
|
||||
return ApplicationManager.getApplication().getService(OpenAISettings.class);
|
||||
}
|
||||
|
||||
public boolean isModified(OpenAISettingsForm form) {
|
||||
return !form.getCurrentState().equals(state)
|
||||
|| !StringUtils.equals(
|
||||
form.getApiKey(),
|
||||
CredentialsStore.INSTANCE.getCredential(OPENAI_API_KEY));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package ee.carlrobert.codegpt.settings.service.openai;
|
|||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY;
|
||||
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.ui.EnumComboBoxModel;
|
||||
import com.intellij.ui.TitledSeparator;
|
||||
|
|
@ -12,10 +13,12 @@ import com.intellij.util.ui.FormBuilder;
|
|||
import com.intellij.util.ui.UI;
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
|
||||
import ee.carlrobert.codegpt.settings.service.CodeCompletionConfigurationForm;
|
||||
import ee.carlrobert.codegpt.ui.UIUtil;
|
||||
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class OpenAISettingsForm {
|
||||
|
|
@ -28,7 +31,10 @@ public class OpenAISettingsForm {
|
|||
public OpenAISettingsForm(OpenAISettingsState settings) {
|
||||
apiKeyField = new JBPasswordField();
|
||||
apiKeyField.setColumns(30);
|
||||
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(OPENAI_API_KEY));
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
var apiKey = CredentialsStore.getCredential(CredentialKey.OPENAI_API_KEY);
|
||||
SwingUtilities.invokeLater(() -> apiKeyField.setText(apiKey));
|
||||
});
|
||||
organizationField = new JBTextField(settings.getOrganization(), 30);
|
||||
completionModelComboBox = new ComboBox<>(
|
||||
new EnumComboBoxModel<>(OpenAIChatCompletionModel.class));
|
||||
|
|
@ -36,7 +42,8 @@ public class OpenAISettingsForm {
|
|||
OpenAIChatCompletionModel.findByCode(settings.getModel()));
|
||||
codeCompletionConfigurationForm = new CodeCompletionConfigurationForm(
|
||||
settings.isCodeCompletionsEnabled(),
|
||||
settings.getCodeCompletionMaxTokens());
|
||||
settings.getCodeCompletionMaxTokens(),
|
||||
null);
|
||||
}
|
||||
|
||||
public JPanel getForm() {
|
||||
|
|
@ -57,10 +64,10 @@ public class OpenAISettingsForm {
|
|||
.createPanel();
|
||||
|
||||
return FormBuilder.createFormBuilder()
|
||||
.addComponent(new TitledSeparator(CodeGPTBundle.get("shared.codeCompletions")))
|
||||
.addComponent(withEmptyLeftBorder(codeCompletionConfigurationForm.getForm()))
|
||||
.addComponent(new TitledSeparator(CodeGPTBundle.get("shared.configuration")))
|
||||
.addComponent(withEmptyLeftBorder(configurationGrid))
|
||||
.addComponent(new TitledSeparator(CodeGPTBundle.get("shared.codeCompletions")))
|
||||
.addComponent(withEmptyLeftBorder(codeCompletionConfigurationForm.getForm()))
|
||||
.addComponentFillVertically(new JPanel(), 0)
|
||||
.getPanel();
|
||||
}
|
||||
|
|
@ -87,7 +94,7 @@ public class OpenAISettingsForm {
|
|||
|
||||
public void resetForm() {
|
||||
var state = OpenAISettings.getCurrentState();
|
||||
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(OPENAI_API_KEY));
|
||||
apiKeyField.setText(CredentialsStore.getCredential(OPENAI_API_KEY));
|
||||
completionModelComboBox.setSelectedItem(
|
||||
OpenAIChatCompletionModel.findByCode(state.getModel()));
|
||||
organizationField.setText(state.getOrganization());
|
||||
|
|
|
|||
|
|
@ -29,8 +29,4 @@ public class YouSettings implements PersistentStateComponent<YouSettingsState> {
|
|||
public static YouSettings getInstance() {
|
||||
return ApplicationManager.getApplication().getService(YouSettings.class);
|
||||
}
|
||||
|
||||
public boolean isModified(YouSettingsForm form) {
|
||||
return !form.getCurrentState().equals(state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package ee.carlrobert.codegpt.settings.service.you;
|
||||
|
||||
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.YOU_ACCOUNT_PASSWORD;
|
||||
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.ui.ComponentValidator;
|
||||
import com.intellij.openapi.ui.ValidationInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
|
|
@ -53,7 +53,10 @@ public class YouSettingsForm extends JPanel {
|
|||
passwordField = new JBPasswordField();
|
||||
passwordField.setColumns(25);
|
||||
if (!settings.getEmail().isEmpty()) {
|
||||
passwordField.setText(CredentialsStore.INSTANCE.getCredential(YOU_ACCOUNT_PASSWORD));
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
var apiKey = CredentialsStore.getCredential(CredentialKey.YOU_ACCOUNT_PASSWORD);
|
||||
SwingUtilities.invokeLater(() -> passwordField.setText(apiKey));
|
||||
});
|
||||
}
|
||||
signInButton = new JButton(CodeGPTBundle.get("settingsConfigurable.service.you.signIn.label"));
|
||||
signUpTextPane = createSignUpTextPane();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,13 @@ package ee.carlrobert.codegpt.toolwindow.chat.ui;
|
|||
|
||||
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
|
||||
import com.intellij.openapi.roots.ui.componentsList.layout.VerticalStackLayout;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType;
|
||||
import ee.carlrobert.codegpt.ui.UIUtil;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
@ -21,6 +28,22 @@ public class ChatToolWindowScrollablePanel extends ScrollablePanel {
|
|||
public void displayLandingView(JComponent landingView) {
|
||||
clearAll();
|
||||
add(landingView);
|
||||
if (GeneralSettings.getCurrentState().getSelectedService() == ServiceType.CODEGPT
|
||||
&& !CredentialsStore.INSTANCE.isCredentialSet(CredentialKey.CODEGPT_API_KEY)) {
|
||||
|
||||
var panel = new ResponsePanel()
|
||||
.addContent(UIUtil.createTextPane("""
|
||||
<html>
|
||||
<p style="margin-top: 4px; margin-bottom: 4px;">
|
||||
It looks like you haven't configured your API key yet. Visit the <a href="https://codegpt.carlrobert.ee/account">CodeGPT settings</a> to do so.
|
||||
</p>
|
||||
<p style="margin-top: 4px; margin-bottom: 4px;">
|
||||
Don't have an account? <a href="https://codegpt.carlrobert.ee/signin">Sign up</a> for free access to all open-source models.
|
||||
</p>
|
||||
</html>""", false, UIUtil::handleHyperlinkClicked));
|
||||
panel.setBorder(JBUI.Borders.customLine(JBColor.border(), 1, 0, 0, 0));
|
||||
add(panel);
|
||||
}
|
||||
}
|
||||
|
||||
public ResponsePanel getMessageResponsePanel(UUID messageId) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package ee.carlrobert.codegpt.toolwindow.chat.ui.textarea;
|
||||
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.CODEGPT;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.CUSTOM_OPENAI;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.OLLAMA;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.YOU;
|
||||
import static ee.carlrobert.llm.client.codegpt.CodeGPTAvailableModels.AVAILABLE_CHAT_MODELS;
|
||||
import static java.lang.String.format;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread;
|
||||
|
|
@ -18,15 +21,17 @@ import ee.carlrobert.codegpt.Icons;
|
|||
import ee.carlrobert.codegpt.completions.llama.LlamaModel;
|
||||
import ee.carlrobert.codegpt.completions.you.YouUserManager;
|
||||
import ee.carlrobert.codegpt.completions.you.auth.SignedOutNotifier;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore;
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings;
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettingsState;
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType;
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettingsState;
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettingsState;
|
||||
import ee.carlrobert.llm.client.codegpt.CodeGPTModel;
|
||||
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
|
||||
import ee.carlrobert.llm.client.you.completion.YouCompletionCustomModel;
|
||||
import ee.carlrobert.llm.client.you.completion.YouCompletionMode;
|
||||
|
|
@ -38,15 +43,9 @@ import org.jetbrains.annotations.NotNull;
|
|||
public class ModelComboBoxAction extends ComboBoxAction {
|
||||
|
||||
private final Runnable onModelChange;
|
||||
private final GeneralSettingsState settings;
|
||||
private final OpenAISettingsState openAISettings;
|
||||
private final YouSettingsState youSettings;
|
||||
|
||||
public ModelComboBoxAction(Runnable onModelChange, ServiceType selectedService) {
|
||||
this.onModelChange = onModelChange;
|
||||
settings = GeneralSettings.getCurrentState();
|
||||
openAISettings = OpenAISettings.getCurrentState();
|
||||
youSettings = YouSettings.getCurrentState();
|
||||
updateTemplatePresentation(selectedService);
|
||||
|
||||
subscribeToYouSignedOutTopic(ApplicationManager.getApplication().getMessageBus().connect());
|
||||
|
|
@ -66,18 +65,28 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
return button;
|
||||
}
|
||||
|
||||
private AnAction[] getCodeGPTModelActions(Presentation presentation) {
|
||||
var apiKey = CredentialsStore.getCredential(CredentialKey.CODEGPT_API_KEY);
|
||||
return AVAILABLE_CHAT_MODELS.stream()
|
||||
.map(model -> {
|
||||
var enabled = "codellama/CodeLlama-13b-Instruct-hf".equals(model.getCode())
|
||||
|| (apiKey != null && !apiKey.isEmpty());
|
||||
return createCodeGPTModelAction(model, enabled, presentation);
|
||||
})
|
||||
.toArray(AnAction[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull DefaultActionGroup createPopupActionGroup(JComponent button) {
|
||||
var presentation = ((ComboBoxButton) button).getPresentation();
|
||||
var actionGroup = new DefaultActionGroup();
|
||||
actionGroup.addSeparator("CodeGPT");
|
||||
actionGroup.addAll(getCodeGPTModelActions(presentation));
|
||||
actionGroup.addSeparator("OpenAI");
|
||||
List.of(
|
||||
OpenAIChatCompletionModel.GPT_4_VISION_PREVIEW,
|
||||
OpenAIChatCompletionModel.GPT_4_0125_128k,
|
||||
OpenAIChatCompletionModel.GPT_3_5_0125_16k,
|
||||
OpenAIChatCompletionModel.GPT_4_32k,
|
||||
OpenAIChatCompletionModel.GPT_4,
|
||||
OpenAIChatCompletionModel.GPT_3_5)
|
||||
OpenAIChatCompletionModel.GPT_3_5_0125_16k)
|
||||
.forEach(model -> actionGroup.add(createOpenAIModelAction(model, presentation)));
|
||||
actionGroup.addSeparator("Custom OpenAI Service");
|
||||
actionGroup.add(createModelAction(
|
||||
|
|
@ -103,6 +112,19 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
getLlamaCppPresentationText(),
|
||||
Icons.Llama,
|
||||
presentation));
|
||||
actionGroup.addSeparator("Ollama");
|
||||
ApplicationManager.getApplication()
|
||||
.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.getAvailableModels()
|
||||
.forEach(model ->
|
||||
actionGroup.add(createOllamaModelAction(model, presentation)));
|
||||
actionGroup.addSeparator();
|
||||
actionGroup.add(createModelAction(
|
||||
ServiceType.GOOGLE,
|
||||
"Google (Gemini)",
|
||||
Icons.Google,
|
||||
presentation));
|
||||
|
||||
if (YouUserManager.getInstance().isSubscribed()) {
|
||||
actionGroup.addSeparator("You.com");
|
||||
|
|
@ -144,20 +166,33 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
}
|
||||
|
||||
private void updateTemplatePresentation(ServiceType selectedService) {
|
||||
var application = ApplicationManager.getApplication();
|
||||
var templatePresentation = getTemplatePresentation();
|
||||
switch (selectedService) {
|
||||
case CODEGPT:
|
||||
var model = application.getService(CodeGPTServiceSettings.class)
|
||||
.getState()
|
||||
.getChatCompletionSettings()
|
||||
.getModel();
|
||||
var modelName = AVAILABLE_CHAT_MODELS.stream()
|
||||
.filter(it -> it.getCode().equals(model))
|
||||
.map(CodeGPTModel::getName)
|
||||
.findFirst().orElse("Unknown");
|
||||
templatePresentation.setIcon(Icons.CodeGPTModel);
|
||||
templatePresentation.setText(modelName);
|
||||
break;
|
||||
case OPENAI:
|
||||
templatePresentation.setIcon(Icons.OpenAI);
|
||||
templatePresentation.setText(
|
||||
OpenAIChatCompletionModel.findByCode(openAISettings.getModel()).getDescription());
|
||||
OpenAIChatCompletionModel.findByCode(OpenAISettings.getCurrentState().getModel())
|
||||
.getDescription());
|
||||
break;
|
||||
case CUSTOM_OPENAI:
|
||||
templatePresentation.setIcon(Icons.OpenAI);
|
||||
templatePresentation.setText(
|
||||
ApplicationManager.getApplication().getService(CustomServiceSettings.class)
|
||||
.getState()
|
||||
.getTemplate()
|
||||
.getProviderName());
|
||||
templatePresentation.setText(application.getService(CustomServiceSettings.class)
|
||||
.getState()
|
||||
.getTemplate()
|
||||
.getProviderName());
|
||||
break;
|
||||
case ANTHROPIC:
|
||||
templatePresentation.setIcon(Icons.Anthropic);
|
||||
|
|
@ -168,18 +203,30 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
templatePresentation.setText("Azure OpenAI");
|
||||
break;
|
||||
case YOU:
|
||||
var settings = YouSettings.getCurrentState();
|
||||
templatePresentation.setIcon(Icons.YouSmall);
|
||||
templatePresentation.setText(
|
||||
youSettings.getChatMode() == YouCompletionMode.CUSTOM
|
||||
? youSettings.getCustomModel().getDescription()
|
||||
: youSettings.getChatMode().getDescription()
|
||||
settings.getChatMode() == YouCompletionMode.CUSTOM
|
||||
? settings.getCustomModel().getDescription()
|
||||
: settings.getChatMode().getDescription()
|
||||
);
|
||||
break;
|
||||
case LLAMA_CPP:
|
||||
templatePresentation.setText(getLlamaCppPresentationText());
|
||||
templatePresentation.setIcon(Icons.Llama);
|
||||
break;
|
||||
case OLLAMA:
|
||||
templatePresentation.setIcon(Icons.Ollama);
|
||||
templatePresentation.setText(application.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.getModel());
|
||||
break;
|
||||
case GOOGLE:
|
||||
templatePresentation.setText("Google (Gemini)");
|
||||
templatePresentation.setIcon(Icons.Google);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,12 +276,73 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
String label,
|
||||
Icon icon,
|
||||
Presentation comboBoxPresentation) {
|
||||
settings.setSelectedService(serviceType);
|
||||
GeneralSettings.getCurrentState().setSelectedService(serviceType);
|
||||
comboBoxPresentation.setIcon(icon);
|
||||
comboBoxPresentation.setText(label);
|
||||
onModelChange.run();
|
||||
}
|
||||
|
||||
private AnAction createCodeGPTModelAction(CodeGPTModel model, boolean enabled,
|
||||
Presentation comboBoxPresentation) {
|
||||
return new DumbAwareAction(model.getName(), "", Icons.CodeGPTModel) {
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent event) {
|
||||
var presentation = event.getPresentation();
|
||||
presentation.setEnabled(
|
||||
enabled && !presentation.getText().equals(comboBoxPresentation.getText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
ApplicationManager.getApplication().getService(CodeGPTServiceSettings.class)
|
||||
.getState()
|
||||
.getChatCompletionSettings()
|
||||
.setModel(model.getCode());
|
||||
handleModelChange(
|
||||
CODEGPT,
|
||||
model.getName(),
|
||||
Icons.OpenAI,
|
||||
comboBoxPresentation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ActionUpdateThread getActionUpdateThread() {
|
||||
return ActionUpdateThread.BGT;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private AnAction createOllamaModelAction(
|
||||
String model,
|
||||
Presentation comboBoxPresentation
|
||||
) {
|
||||
return new DumbAwareAction(model, "", Icons.Ollama) {
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent event) {
|
||||
var presentation = event.getPresentation();
|
||||
presentation.setEnabled(!presentation.getText().equals(comboBoxPresentation.getText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
ApplicationManager.getApplication()
|
||||
.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.setModel(model);
|
||||
handleModelChange(
|
||||
OLLAMA,
|
||||
model,
|
||||
Icons.Ollama,
|
||||
comboBoxPresentation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ActionUpdateThread getActionUpdateThread() {
|
||||
return ActionUpdateThread.BGT;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private AnAction createOpenAIModelAction(
|
||||
OpenAIChatCompletionModel model,
|
||||
Presentation comboBoxPresentation) {
|
||||
|
|
@ -249,7 +357,7 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
openAISettings.setModel(model.getCode());
|
||||
OpenAISettings.getCurrentState().setModel(model.getCode());
|
||||
handleModelChange(
|
||||
OPENAI,
|
||||
model.getDescription(),
|
||||
|
|
@ -278,7 +386,7 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
youSettings.setChatMode(mode);
|
||||
YouSettings.getCurrentState().setChatMode(mode);
|
||||
handleModelChange(
|
||||
YOU,
|
||||
mode.getDescription(),
|
||||
|
|
@ -307,8 +415,9 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
youSettings.setCustomModel(model);
|
||||
youSettings.setChatMode(YouCompletionMode.CUSTOM);
|
||||
var settings = YouSettings.getCurrentState();
|
||||
settings.setCustomModel(model);
|
||||
settings.setChatMode(YouCompletionMode.CUSTOM);
|
||||
handleModelChange(
|
||||
YOU,
|
||||
model.getDescription(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package ee.carlrobert.codegpt.toolwindow.chat.ui.textarea;
|
||||
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.ANTHROPIC;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.OLLAMA;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
|
||||
import static ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel.GPT_4_VISION_PREVIEW;
|
||||
|
||||
|
|
@ -192,6 +193,7 @@ public class UserPromptTextArea extends JPanel {
|
|||
}));
|
||||
var selectedService = GeneralSettings.getCurrentState().getSelectedService();
|
||||
if (selectedService == ANTHROPIC
|
||||
|| selectedService == OLLAMA
|
||||
|| (selectedService == OPENAI
|
||||
&& GPT_4_VISION_PREVIEW.getCode().equals(OpenAISettings.getCurrentState().getModel()))) {
|
||||
iconsPanel.add(new IconActionButton(new AttachImageAction()));
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ public class ModelIconLabel extends JBLabel {
|
|||
if ("llama.chat.completion".equals(clientCode)) {
|
||||
setIcon(Icons.Llama);
|
||||
}
|
||||
if ("google.chat.completion".equals(clientCode)) {
|
||||
setIcon(Icons.Google);
|
||||
}
|
||||
setText(formatModelName(modelCode));
|
||||
setFont(JBFont.small());
|
||||
setHorizontalAlignment(SwingConstants.LEADING);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ class CodeGPTProjectActivity : ProjectActivity {
|
|||
|
||||
override suspend fun execute(project: Project) {
|
||||
EditorActionsUtil.refreshActions()
|
||||
CredentialsStore.loadAll()
|
||||
|
||||
if (YouUserManager.getInstance().authenticationResponse == null) {
|
||||
handleYouServiceAuthenticationAsync()
|
||||
|
|
|
|||
|
|
@ -4,57 +4,69 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread
|
|||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import ee.carlrobert.codegpt.codecompletions.CodeCompletionService
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType.*
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings
|
||||
|
||||
abstract class CodeCompletionFeatureToggleActions(
|
||||
private val enableFeatureAction: Boolean
|
||||
) : DumbAwareAction() {
|
||||
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
GeneralSettings.getCurrentState().selectedService
|
||||
.takeIf { it in listOf(OPENAI, CUSTOM_OPENAI, LLAMA_CPP) }
|
||||
?.also { selectedService ->
|
||||
if (OPENAI == selectedService) {
|
||||
OpenAISettings.getCurrentState().isCodeCompletionsEnabled = enableFeatureAction
|
||||
} else if (CUSTOM_OPENAI == selectedService) {
|
||||
service<CustomServiceSettings>().state.codeCompletionSettings.codeCompletionsEnabled =
|
||||
enableFeatureAction
|
||||
} else {
|
||||
LlamaSettings.getCurrentState().isCodeCompletionsEnabled = enableFeatureAction
|
||||
}
|
||||
when (GeneralSettings.getCurrentState().selectedService) {
|
||||
CODEGPT ->
|
||||
service<CodeGPTServiceSettings>().state.codeCompletionSettings.codeCompletionsEnabled
|
||||
|
||||
OPENAI ->
|
||||
OpenAISettings.getCurrentState().isCodeCompletionsEnabled = enableFeatureAction
|
||||
|
||||
LLAMA_CPP ->
|
||||
LlamaSettings.getCurrentState().isCodeCompletionsEnabled = enableFeatureAction
|
||||
|
||||
OLLAMA -> service<OllamaSettings>().state.codeCompletionsEnabled = enableFeatureAction
|
||||
CUSTOM_OPENAI -> service<CustomServiceSettings>().state
|
||||
.codeCompletionSettings
|
||||
.codeCompletionsEnabled = enableFeatureAction
|
||||
|
||||
ANTHROPIC,
|
||||
AZURE,
|
||||
YOU,
|
||||
GOOGLE,
|
||||
null -> { /* no-op for these services */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val selectedService = GeneralSettings.getCurrentState().selectedService
|
||||
val codeCompletionEnabled = isCodeCompletionsEnabled(selectedService)
|
||||
e.presentation.isEnabled = codeCompletionEnabled != enableFeatureAction
|
||||
e.presentation.isVisible =
|
||||
e.presentation.isEnabled && listOf(OPENAI, CUSTOM_OPENAI, LLAMA_CPP).contains(
|
||||
selectedService
|
||||
)
|
||||
val codeCompletionEnabled =
|
||||
service<CodeCompletionService>().isCodeCompletionsEnabled(selectedService)
|
||||
e.presentation.isVisible = codeCompletionEnabled != enableFeatureAction
|
||||
e.presentation.isEnabled = when (selectedService) {
|
||||
CODEGPT,
|
||||
OPENAI,
|
||||
CUSTOM_OPENAI,
|
||||
LLAMA_CPP,
|
||||
OLLAMA -> true
|
||||
|
||||
ANTHROPIC,
|
||||
AZURE,
|
||||
YOU,
|
||||
GOOGLE,
|
||||
null -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.BGT
|
||||
}
|
||||
|
||||
private fun isCodeCompletionsEnabled(serviceType: ServiceType): Boolean {
|
||||
return when (serviceType) {
|
||||
OPENAI -> OpenAISettings.getCurrentState().isCodeCompletionsEnabled
|
||||
CUSTOM_OPENAI -> service<CustomServiceSettings>().state.codeCompletionSettings.codeCompletionsEnabled
|
||||
LLAMA_CPP -> LlamaSettings.getCurrentState().isCodeCompletionsEnabled
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EnableCompletionsAction : CodeCompletionFeatureToggleActions(true)
|
||||
|
||||
class DisableCompletionsAction : CodeCompletionFeatureToggleActions(false)
|
||||
class DisableCompletionsAction : CodeCompletionFeatureToggleActions(false)
|
||||
|
|
|
|||
|
|
@ -7,11 +7,15 @@ import ee.carlrobert.codegpt.completions.llama.LlamaModel
|
|||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.settings.configuration.Placeholder
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings
|
||||
import ee.carlrobert.llm.client.llama.completion.LlamaCompletionRequest
|
||||
import ee.carlrobert.llm.client.ollama.completion.request.OllamaCompletionRequest
|
||||
import ee.carlrobert.llm.client.ollama.completion.request.OllamaParameters
|
||||
import ee.carlrobert.llm.client.openai.completion.request.OpenAITextCompletionRequest
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.Request
|
||||
|
|
@ -20,6 +24,18 @@ import java.nio.charset.StandardCharsets
|
|||
|
||||
object CodeCompletionRequestFactory {
|
||||
|
||||
@JvmStatic
|
||||
fun buildCodeGPTRequest(details: InfillRequestDetails): OpenAITextCompletionRequest {
|
||||
val settings = service<CodeGPTServiceSettings>().state.codeCompletionSettings
|
||||
return OpenAITextCompletionRequest.Builder(details.prefix)
|
||||
.setSuffix(details.suffix)
|
||||
.setStream(true)
|
||||
.setModel(settings.model)
|
||||
.setMaxTokens(settings.maxTokens)
|
||||
.setTemperature(0.4)
|
||||
.build()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun buildOpenAIRequest(details: InfillRequestDetails): OpenAITextCompletionRequest {
|
||||
return OpenAITextCompletionRequest.Builder(details.prefix)
|
||||
|
|
@ -33,17 +49,36 @@ object CodeCompletionRequestFactory {
|
|||
@JvmStatic
|
||||
fun buildCustomRequest(details: InfillRequestDetails): Request {
|
||||
val settings = service<CustomServiceSettings>().state.codeCompletionSettings
|
||||
val requestBuilder = Request.Builder().url(settings.url!!)
|
||||
val credential = getCredential(CredentialKey.CUSTOM_SERVICE_API_KEY)
|
||||
for (entry in settings.headers.entries) {
|
||||
return buildCustomRequest(
|
||||
details,
|
||||
settings.url!!,
|
||||
settings.headers,
|
||||
settings.body,
|
||||
settings.infillTemplate,
|
||||
credential
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun buildCustomRequest(
|
||||
details: InfillRequestDetails,
|
||||
url: String,
|
||||
headers: Map<String, String>,
|
||||
body: Map<String, Any>,
|
||||
infillTemplate: InfillPromptTemplate,
|
||||
credential: String?
|
||||
): Request {
|
||||
val requestBuilder = Request.Builder().url(url)
|
||||
for (entry in headers.entries) {
|
||||
var value = entry.value
|
||||
if (credential != null && value.contains("\$CUSTOM_SERVICE_API_KEY")) {
|
||||
value = value.replace("\$CUSTOM_SERVICE_API_KEY", credential)
|
||||
}
|
||||
requestBuilder.addHeader(entry.key, value)
|
||||
}
|
||||
val transformedBody = settings.body.entries.associate { (key, value) ->
|
||||
key to transformValue(value, settings.infillTemplate, details)
|
||||
val transformedBody = body.entries.associate { (key, value) ->
|
||||
key to transformValue(value, infillTemplate, details)
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -71,6 +106,22 @@ object CodeCompletionRequestFactory {
|
|||
.build()
|
||||
}
|
||||
|
||||
fun buildOllamaRequest(details: InfillRequestDetails): OllamaCompletionRequest {
|
||||
val settings = service<OllamaSettings>().state
|
||||
return OllamaCompletionRequest.Builder(
|
||||
settings.model,
|
||||
settings.fimTemplate.buildPrompt(details.prefix, details.suffix)
|
||||
)
|
||||
.setOptions(
|
||||
OllamaParameters.Builder()
|
||||
.stop(settings.fimTemplate.stopTokens)
|
||||
.numPredict(settings.codeCompletionMaxTokens)
|
||||
.build()
|
||||
)
|
||||
.setRaw(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun getLlamaInfillPromptTemplate(settings: LlamaSettingsState): InfillPromptTemplate {
|
||||
if (!settings.isRunLocalServer) {
|
||||
return settings.remoteModelInfillPromptTemplate
|
||||
|
|
@ -94,4 +145,4 @@ object CodeCompletionRequestFactory {
|
|||
else -> value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package ee.carlrobert.codegpt.codecompletions
|
||||
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import ee.carlrobert.codegpt.codecompletions.CodeCompletionRequestFactory.buildCodeGPTRequest
|
||||
import ee.carlrobert.codegpt.codecompletions.CodeCompletionRequestFactory.buildCustomRequest
|
||||
import ee.carlrobert.codegpt.codecompletions.CodeCompletionRequestFactory.buildLlamaRequest
|
||||
import ee.carlrobert.codegpt.codecompletions.CodeCompletionRequestFactory.buildOpenAIRequest
|
||||
import ee.carlrobert.codegpt.completions.CompletionClientProvider
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType.*
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings
|
||||
import ee.carlrobert.llm.client.openai.completion.OpenAITextCompletionEventSourceListener
|
||||
import ee.carlrobert.llm.completion.CompletionEventListener
|
||||
import okhttp3.sse.EventSource
|
||||
import okhttp3.sse.EventSources.createFactory
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
class CodeCompletionService {
|
||||
|
||||
fun isCodeCompletionsEnabled(selectedService: ServiceType): Boolean =
|
||||
when (selectedService) {
|
||||
CODEGPT -> service<CodeGPTServiceSettings>().state.codeCompletionSettings.codeCompletionsEnabled
|
||||
OPENAI -> OpenAISettings.getCurrentState().isCodeCompletionsEnabled
|
||||
CUSTOM_OPENAI -> service<CustomServiceSettings>().state.codeCompletionSettings.codeCompletionsEnabled
|
||||
LLAMA_CPP -> LlamaSettings.isCodeCompletionsPossible()
|
||||
OLLAMA -> service<OllamaSettings>().state.codeCompletionsEnabled
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun getCodeCompletionAsync(
|
||||
requestDetails: InfillRequestDetails,
|
||||
eventListener: CompletionEventListener<String>
|
||||
): EventSource =
|
||||
when (val selectedService = GeneralSettings.getCurrentState().selectedService) {
|
||||
CODEGPT -> CompletionClientProvider.getCodeGPTClient()
|
||||
.getCompletionAsync(buildCodeGPTRequest(requestDetails), eventListener)
|
||||
|
||||
OPENAI -> CompletionClientProvider.getOpenAIClient()
|
||||
.getCompletionAsync(buildOpenAIRequest(requestDetails), eventListener)
|
||||
|
||||
CUSTOM_OPENAI -> createFactory(
|
||||
CompletionClientProvider.getDefaultClientBuilder().build()
|
||||
).newEventSource(
|
||||
buildCustomRequest(requestDetails),
|
||||
OpenAITextCompletionEventSourceListener(eventListener)
|
||||
)
|
||||
|
||||
LLAMA_CPP -> CompletionClientProvider.getLlamaClient()
|
||||
.getChatCompletionAsync(buildLlamaRequest(requestDetails), eventListener)
|
||||
|
||||
else -> throw IllegalArgumentException("Code completion not supported for ${selectedService.name}")
|
||||
}
|
||||
}
|
||||
|
|
@ -16,11 +16,12 @@ import com.intellij.openapi.application.EDT
|
|||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import ee.carlrobert.codegpt.CodeGPTKeys
|
||||
import ee.carlrobert.codegpt.completions.CompletionRequestService
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings
|
||||
import ee.carlrobert.codegpt.ui.OverlayUtil.showNotification
|
||||
import ee.carlrobert.llm.client.openai.completion.ErrorDetails
|
||||
|
|
@ -48,7 +49,8 @@ class CodeGPTInlineCompletionProvider : InlineCompletionProvider {
|
|||
get() = CodeCompletionSuggestionUpdateAdapter()
|
||||
|
||||
override suspend fun getSuggestion(request: InlineCompletionRequest): InlineCompletionSingleSuggestion {
|
||||
if (request.editor.project == null) {
|
||||
val project = request.editor.project
|
||||
if (project == null) {
|
||||
logger.error("Could not find project")
|
||||
return InlineCompletionSingleSuggestion.build(elements = emptyFlow())
|
||||
}
|
||||
|
|
@ -58,7 +60,7 @@ class CodeGPTInlineCompletionProvider : InlineCompletionProvider {
|
|||
InfillRequestDetails.fromInlineCompletionRequest(request)
|
||||
}
|
||||
currentCall.set(
|
||||
CompletionRequestService.getInstance().getCodeCompletionAsync(
|
||||
project.service<CodeCompletionService>().getCodeCompletionAsync(
|
||||
infillRequest,
|
||||
CodeCompletionEventListener {
|
||||
val inlineText = it.takeWhile { message -> message != '\n' }.toString()
|
||||
|
|
@ -80,10 +82,16 @@ class CodeGPTInlineCompletionProvider : InlineCompletionProvider {
|
|||
override fun isEnabled(event: InlineCompletionEvent): Boolean {
|
||||
val selectedService = GeneralSettings.getCurrentState().selectedService
|
||||
val codeCompletionsEnabled = when (selectedService) {
|
||||
ServiceType.CODEGPT -> service<CodeGPTServiceSettings>().state.codeCompletionSettings.codeCompletionsEnabled
|
||||
ServiceType.OPENAI -> OpenAISettings.getCurrentState().isCodeCompletionsEnabled
|
||||
ServiceType.CUSTOM_OPENAI -> service<CustomServiceSettings>().state.codeCompletionSettings.codeCompletionsEnabled
|
||||
ServiceType.LLAMA_CPP -> LlamaSettings.getCurrentState().isCodeCompletionsEnabled
|
||||
else -> false
|
||||
ServiceType.OLLAMA -> service<OllamaSettings>().state.codeCompletionsEnabled
|
||||
ServiceType.ANTHROPIC,
|
||||
ServiceType.AZURE,
|
||||
ServiceType.YOU,
|
||||
ServiceType.GOOGLE,
|
||||
null -> false
|
||||
}
|
||||
return event is InlineCompletionEvent.DocumentChange && codeCompletionsEnabled
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,24 @@ enum class InfillPromptTemplate(val label: String, val stopTokens: List<String>?
|
|||
return "<|fim_prefix|> $prefix <|fim_suffix|>$suffix <|fim_middle|>"
|
||||
}
|
||||
},
|
||||
LLAMA("Llama", listOf("<EOT>")) {
|
||||
CODE_LLAMA("Code Llama", listOf("<EOT>")) {
|
||||
override fun buildPrompt(prefix: String, suffix: String): String {
|
||||
return "<PRE> $prefix <SUF>$suffix <MID>"
|
||||
}
|
||||
},
|
||||
CODE_GEMMA(
|
||||
"CodeGemma Instruct",
|
||||
listOf("<|file_separator|>", "<|fim_prefix|>", "<|fim_suffix|>", "<|fim_middle|>", "<eos>")
|
||||
) {
|
||||
override fun buildPrompt(prefix: String, suffix: String): String {
|
||||
return "<|fim_prefix|>$prefix<|fim_suffix|>$suffix<|fim_middle|>"
|
||||
}
|
||||
},
|
||||
CODE_QWEN("CodeQwen1.5", listOf("<|endoftext|>")) {
|
||||
override fun buildPrompt(prefix: String, suffix: String): String {
|
||||
return "<fim_prefix>$prefix<fim_suffix>$suffix<fim_middle>"
|
||||
}
|
||||
},
|
||||
STABILITY("Stability AI", listOf("<|endoftext|>")) {
|
||||
override fun buildPrompt(prefix: String, suffix: String): String {
|
||||
return "<fim_prefix>$prefix<fim_suffix>$suffix<fim_middle>"
|
||||
|
|
|
|||
|
|
@ -3,30 +3,27 @@ package ee.carlrobert.codegpt.credentials
|
|||
import com.intellij.credentialStore.CredentialAttributes
|
||||
import com.intellij.credentialStore.generateServiceName
|
||||
import com.intellij.ide.passwordSafe.PasswordSafe
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
|
||||
|
||||
object CredentialsStore {
|
||||
|
||||
private val credentialsMap = mutableMapOf<CredentialKey, String?>()
|
||||
|
||||
fun loadAll() {
|
||||
CredentialKey.values().forEach {
|
||||
val credentialAttributes = CredentialAttributes(generateServiceName("CodeGPT", it.name))
|
||||
val password = PasswordSafe.instance.getPassword(credentialAttributes)
|
||||
|
||||
// Avoid calling setCredential here since it will persist
|
||||
// the password back into the PasswordSafe unnecessarily.
|
||||
credentialsMap[it] = password
|
||||
}
|
||||
@JvmStatic
|
||||
@RequiresBackgroundThread
|
||||
fun getCredential(key: CredentialKey): String? = credentialsMap.getOrPut(key) {
|
||||
PasswordSafe.instance.getPassword(
|
||||
CredentialAttributes(generateServiceName("CodeGPT", key.name))
|
||||
) ?: ""
|
||||
}
|
||||
|
||||
fun getCredential(key: CredentialKey): String? = credentialsMap[key]
|
||||
|
||||
fun setCredential(key: CredentialKey, password: String?) {
|
||||
val prevPassword = credentialsMap[key]
|
||||
credentialsMap[key] = password
|
||||
|
||||
if (prevPassword != password) {
|
||||
val credentialAttributes = CredentialAttributes(generateServiceName("CodeGPT", key.name))
|
||||
val credentialAttributes =
|
||||
CredentialAttributes(generateServiceName("CodeGPT", key.name))
|
||||
PasswordSafe.instance.setPassword(credentialAttributes, password)
|
||||
}
|
||||
}
|
||||
|
|
@ -34,12 +31,14 @@ object CredentialsStore {
|
|||
fun isCredentialSet(key: CredentialKey): Boolean = !getCredential(key).isNullOrEmpty()
|
||||
|
||||
enum class CredentialKey {
|
||||
CODEGPT_API_KEY,
|
||||
OPENAI_API_KEY,
|
||||
CUSTOM_SERVICE_API_KEY,
|
||||
ANTHROPIC_API_KEY,
|
||||
AZURE_OPENAI_API_KEY,
|
||||
AZURE_ACTIVE_DIRECTORY_TOKEN,
|
||||
YOU_ACCOUNT_PASSWORD,
|
||||
LLAMA_API_KEY
|
||||
LLAMA_API_KEY,
|
||||
GOOGLE_API_KEY
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package ee.carlrobert.codegpt.settings.service
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.ANTHROPIC_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings
|
||||
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettingsForm
|
||||
import javax.swing.JComponent
|
||||
|
||||
class AnthropicServiceConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: AnthropicSettingsForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: Anthropic Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = AnthropicSettingsForm(service<AnthropicSettings>().state)
|
||||
return component.form
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.getCurrentState() != service<AnthropicSettings>().state
|
||||
|| component.getApiKey() != getCredential(ANTHROPIC_API_KEY)
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
setCredential(ANTHROPIC_API_KEY, component.getApiKey())
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.ANTHROPIC
|
||||
service<AnthropicSettings>().loadState(component.getCurrentState())
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package ee.carlrobert.codegpt.settings.service
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_OPENAI_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettingsForm
|
||||
import javax.swing.JComponent
|
||||
|
||||
class AzureServiceConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: AzureSettingsForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: Azure Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = AzureSettingsForm(service<AzureSettings>().state)
|
||||
return component.getForm()
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.getCurrentState() != service<AzureSettings>().state
|
||||
|| component.getActiveDirectoryToken() != getCredential(AZURE_ACTIVE_DIRECTORY_TOKEN)
|
||||
|| component.getApiKey() != getCredential(AZURE_OPENAI_API_KEY)
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.AZURE
|
||||
service<AzureSettings>().loadState(component.currentState)
|
||||
setCredential(AZURE_OPENAI_API_KEY, component.getApiKey())
|
||||
setCredential(AZURE_ACTIVE_DIRECTORY_TOKEN, component.getActiveDirectoryToken())
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,26 @@
|
|||
package ee.carlrobert.codegpt.settings.service
|
||||
|
||||
import com.intellij.icons.AllIcons.General
|
||||
import com.intellij.ide.HelpTooltip
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.openapi.ui.panel.ComponentPanelBuilder
|
||||
import com.intellij.ui.EnumComboBoxModel
|
||||
import com.intellij.ui.components.JBCheckBox
|
||||
import com.intellij.ui.components.JBLabel
|
||||
import com.intellij.ui.components.fields.IntegerField
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
import java.awt.FlowLayout
|
||||
import javax.swing.Box
|
||||
import javax.swing.JPanel
|
||||
|
||||
class CodeCompletionConfigurationForm(codeCompletionsEnabled: Boolean, maxTokens: Int) {
|
||||
class CodeCompletionConfigurationForm(
|
||||
codeCompletionsEnabled: Boolean,
|
||||
maxTokens: Int,
|
||||
fimTemplate: InfillPromptTemplate?
|
||||
) {
|
||||
|
||||
private val codeCompletionsEnabledCheckBox = JBCheckBox(
|
||||
CodeGPTBundle.get("codeCompletionsForm.enableFeatureText"),
|
||||
|
|
@ -18,15 +31,33 @@ class CodeCompletionConfigurationForm(codeCompletionsEnabled: Boolean, maxTokens
|
|||
columns = 12
|
||||
value = maxTokens
|
||||
}
|
||||
private val promptTemplateComboBox =
|
||||
ComboBox(EnumComboBoxModel(InfillPromptTemplate::class.java)).apply {
|
||||
item = fimTemplate
|
||||
addItemListener {
|
||||
updatePromptTemplateHelpTooltip(it.item as InfillPromptTemplate)
|
||||
}
|
||||
}
|
||||
private val promptTemplateHelpText = JBLabel(General.ContextHelp)
|
||||
|
||||
fun getForm(): JPanel {
|
||||
return FormBuilder.createFormBuilder()
|
||||
val formBuilder = FormBuilder.createFormBuilder()
|
||||
.addComponent(codeCompletionsEnabledCheckBox)
|
||||
.addVerticalGap(4)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("codeCompletionsForm.maxTokensLabel"),
|
||||
codeCompletionMaxTokensField
|
||||
)
|
||||
.addVerticalGap(4);
|
||||
if (fimTemplate != null) {
|
||||
formBuilder.addVerticalGap(4)
|
||||
.addLabeledComponent(
|
||||
"FIM template:",
|
||||
JPanel(FlowLayout(FlowLayout.LEADING, 0, 0)).apply {
|
||||
add(promptTemplateComboBox)
|
||||
add(Box.createHorizontalStrut(4))
|
||||
add(promptTemplateHelpText)
|
||||
})
|
||||
}
|
||||
return formBuilder.addLabeledComponent(
|
||||
CodeGPTBundle.get("codeCompletionsForm.maxTokensLabel"),
|
||||
codeCompletionMaxTokensField
|
||||
)
|
||||
.addComponentToRightColumn(
|
||||
ComponentPanelBuilder.createCommentComponent(
|
||||
CodeGPTBundle.get("codeCompletionsForm.maxTokensComment"), true, 48, true
|
||||
|
|
@ -46,4 +77,20 @@ class CodeCompletionConfigurationForm(codeCompletionsEnabled: Boolean, maxTokens
|
|||
set(maxTokens) {
|
||||
codeCompletionMaxTokensField.value = maxTokens
|
||||
}
|
||||
|
||||
var fimTemplate: InfillPromptTemplate?
|
||||
get() = promptTemplateComboBox.item
|
||||
set(template) {
|
||||
promptTemplateComboBox.item = template
|
||||
}
|
||||
|
||||
private fun updatePromptTemplateHelpTooltip(template: InfillPromptTemplate) {
|
||||
promptTemplateHelpText.setToolTipText(null)
|
||||
|
||||
val description = StringEscapeUtils.escapeHtml4(template.buildPrompt("PREFIX", "SUFFIX"))
|
||||
HelpTooltip()
|
||||
.setTitle(template.toString())
|
||||
.setDescription("<html><p>$description</p></html>")
|
||||
.installOn(promptTemplateHelpText)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package ee.carlrobert.codegpt.settings.service
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.LLAMA_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.llama.form.LlamaSettingsForm
|
||||
import javax.swing.JComponent
|
||||
|
||||
class LlamaServiceConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: LlamaSettingsForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: Custom Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = LlamaSettingsForm(service<LlamaSettings>().state)
|
||||
return component
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.getCurrentState() != service<LlamaSettings>().state
|
||||
|| component.llamaServerPreferencesForm.getApiKey() != getCredential(LLAMA_API_KEY)
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.LLAMA_CPP
|
||||
setCredential(LLAMA_API_KEY, component.llamaServerPreferencesForm.getApiKey())
|
||||
service<LlamaSettings>().loadState(component.currentState)
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package ee.carlrobert.codegpt.settings.service
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettingsForm
|
||||
import javax.swing.JComponent
|
||||
|
||||
class OpenAIServiceConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: OpenAISettingsForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: OpenAI Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = OpenAISettingsForm(service<OpenAISettings>().state)
|
||||
return component.getForm()
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.getCurrentState() != service<OpenAISettings>().state
|
||||
|| component.getApiKey() != getCredential(OPENAI_API_KEY)
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.OPENAI
|
||||
setCredential(OPENAI_API_KEY, component.getApiKey())
|
||||
service<OpenAISettings>().loadState(component.getCurrentState())
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package ee.carlrobert.codegpt.settings.service
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.conversations.ConversationsState
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.telemetry.TelemetryAction
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.ChatToolWindowContentManager
|
||||
import ee.carlrobert.codegpt.util.ApplicationUtil.findCurrentProject
|
||||
import javax.swing.JComponent
|
||||
|
||||
class ServiceConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: ServiceConfigurableComponent
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: Services"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = ServiceConfigurableComponent()
|
||||
return component.getPanel()
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.getSelectedService() != service<GeneralSettings>().state.selectedService
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
val state = service<GeneralSettings>().state
|
||||
state.selectedService = component.getSelectedService()
|
||||
|
||||
val serviceChanged = component.getSelectedService() != state.selectedService
|
||||
if (serviceChanged) {
|
||||
resetActiveTab()
|
||||
TelemetryAction.SETTINGS_CHANGED.createActionMessage()
|
||||
.property("service", component.getSelectedService().code.lowercase())
|
||||
.send()
|
||||
}
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.setSelectedService(service<GeneralSettings>().state.selectedService)
|
||||
}
|
||||
|
||||
private fun resetActiveTab() {
|
||||
service<ConversationsState>().currentConversation = null
|
||||
val project = findCurrentProject()
|
||||
?: throw RuntimeException("Could not find current project.")
|
||||
project.getService(ChatToolWindowContentManager::class.java).resetAll()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package ee.carlrobert.codegpt.settings.service
|
||||
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.ex.Settings
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.ui.EnumComboBoxModel
|
||||
import com.intellij.ui.components.ActionLink
|
||||
import com.intellij.ui.components.JBLabel
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceConfigurable
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceForm
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceConfigurable
|
||||
import ee.carlrobert.codegpt.settings.service.google.GoogleSettingsConfigurable
|
||||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettingsConfigurable
|
||||
import javax.swing.JPanel
|
||||
|
||||
class ServiceConfigurableComponent {
|
||||
|
||||
var form: CodeGPTServiceForm = CodeGPTServiceForm()
|
||||
|
||||
private var serviceComboBox: ComboBox<ServiceType> =
|
||||
ComboBox(EnumComboBoxModel(ServiceType::class.java)).apply {
|
||||
selectedItem = service<GeneralSettings>().state.selectedService
|
||||
}
|
||||
|
||||
fun getSelectedService(): ServiceType {
|
||||
return serviceComboBox.item
|
||||
}
|
||||
|
||||
fun setSelectedService(serviceType: ServiceType?) {
|
||||
serviceComboBox.selectedItem = serviceType
|
||||
}
|
||||
|
||||
fun getPanel(): JPanel = FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.label"),
|
||||
serviceComboBox
|
||||
)
|
||||
.addVerticalGap(8)
|
||||
.addComponent(JBLabel("All available providers that can be used with CodeGPT:"))
|
||||
.addVerticalGap(8)
|
||||
.addComponent(FormBuilder.createFormBuilder()
|
||||
.setFormLeftIndent(16).apply {
|
||||
addLinks(this)
|
||||
}
|
||||
.panel)
|
||||
.addComponentFillVertically(JPanel(), 0)
|
||||
.panel
|
||||
|
||||
private fun addLinks(formBuilder: FormBuilder) {
|
||||
mapOf(
|
||||
"CodeGPT" to CodeGPTServiceConfigurable::class.java,
|
||||
"OpenAI" to OpenAIServiceConfigurable::class.java,
|
||||
"Custom OpenAI" to CustomServiceConfigurable::class.java,
|
||||
"Azure" to AzureServiceConfigurable::class.java,
|
||||
"Anthropic" to AnthropicServiceConfigurable::class.java,
|
||||
"Google" to GoogleSettingsConfigurable::class.java,
|
||||
"You.com" to YouServiceConfigurable::class.java,
|
||||
"LLaMA C/C++ (Local)" to LlamaServiceConfigurable::class.java,
|
||||
"Ollama (Local)" to OllamaSettingsConfigurable::class.java,
|
||||
).entries.forEach { (name, configurableClass) ->
|
||||
formBuilder.addComponent(ActionLink(name) {
|
||||
val context = service<DataManager>().getDataContext(it.source as ActionLink)
|
||||
val settings = Settings.KEY.getData(context)
|
||||
settings?.select(settings.find(configurableClass))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package ee.carlrobert.codegpt.settings.service
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettings
|
||||
import ee.carlrobert.codegpt.settings.service.you.YouSettingsForm
|
||||
import javax.swing.JComponent
|
||||
|
||||
class YouServiceConfigurable : Configurable {
|
||||
|
||||
private var parentDisposable = Disposer.newDisposable()
|
||||
private lateinit var component: YouSettingsForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: You.com Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
parentDisposable = Disposer.newDisposable();
|
||||
component = YouSettingsForm(service<YouSettings>().state, parentDisposable)
|
||||
return component
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.getCurrentState() != service<YouSettings>().state
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.YOU
|
||||
service<YouSettings>().loadState(component.currentState)
|
||||
}
|
||||
|
||||
override fun disposeUIResources() {
|
||||
Disposer.dispose(parentDisposable)
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package ee.carlrobert.codegpt.settings.service.codegpt
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CODEGPT_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType
|
||||
import javax.swing.JComponent
|
||||
|
||||
class CodeGPTServiceConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: CodeGPTServiceForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: CodeGPT Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = CodeGPTServiceForm()
|
||||
return component.getForm()
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.isModified() || component.getApiKey() != getCredential(CODEGPT_API_KEY)
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
setCredential(CODEGPT_API_KEY, component.getApiKey())
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.CODEGPT
|
||||
component.applyChanges()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
package ee.carlrobert.codegpt.settings.service.codegpt
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.openapi.ui.panel.ComponentPanelBuilder
|
||||
import com.intellij.ui.TitledSeparator
|
||||
import com.intellij.ui.components.JBCheckBox
|
||||
import com.intellij.ui.components.JBPasswordField
|
||||
import com.intellij.ui.components.fields.IntegerField
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CODEGPT_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.ui.UIUtil
|
||||
import ee.carlrobert.llm.client.codegpt.CodeGPTAvailableModels
|
||||
import ee.carlrobert.llm.client.codegpt.CodeGPTAvailableModels.AVAILABLE_CHAT_MODELS
|
||||
import ee.carlrobert.llm.client.codegpt.CodeGPTAvailableModels.AVAILABLE_CODE_MODELS
|
||||
import ee.carlrobert.llm.client.codegpt.CodeGPTModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jdesktop.swingx.combobox.ListComboBoxModel
|
||||
import java.awt.Component
|
||||
import javax.swing.DefaultListCellRenderer
|
||||
import javax.swing.JList
|
||||
import javax.swing.JPanel
|
||||
|
||||
class CodeGPTServiceForm {
|
||||
|
||||
private val apiKeyField = JBPasswordField().apply {
|
||||
columns = 30
|
||||
}
|
||||
|
||||
private val chatCompletionModelComboBox =
|
||||
ComboBox(ListComboBoxModel(AVAILABLE_CHAT_MODELS)).apply {
|
||||
selectedItem =
|
||||
CodeGPTAvailableModels.findByCode(service<CodeGPTServiceSettings>().state.chatCompletionSettings.model)
|
||||
renderer = CustomComboBoxRenderer()
|
||||
}
|
||||
|
||||
private val codeCompletionsEnabledCheckBox = JBCheckBox(
|
||||
CodeGPTBundle.get("codeCompletionsForm.enableFeatureText"),
|
||||
service<CodeGPTServiceSettings>().state.codeCompletionSettings.codeCompletionsEnabled
|
||||
)
|
||||
|
||||
private val codeCompletionModelComboBox =
|
||||
ComboBox(ListComboBoxModel(AVAILABLE_CODE_MODELS)).apply {
|
||||
selectedItem =
|
||||
CodeGPTAvailableModels.findByCode(service<CodeGPTServiceSettings>().state.codeCompletionSettings.model)
|
||||
renderer = CustomComboBoxRenderer()
|
||||
}
|
||||
|
||||
private val codeCompletionMaxTokensField =
|
||||
IntegerField("completion_max_tokens", 8, 4096).apply {
|
||||
columns = 12
|
||||
value = service<CodeGPTServiceSettings>().state.codeCompletionSettings.maxTokens
|
||||
}
|
||||
|
||||
init {
|
||||
apiKeyField.text = runBlocking(Dispatchers.IO) {
|
||||
getCredential(CODEGPT_API_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
fun getForm(): JPanel = FormBuilder.createFormBuilder()
|
||||
.addComponent(TitledSeparator(CodeGPTBundle.get("shared.configuration")))
|
||||
.addComponent(
|
||||
FormBuilder.createFormBuilder()
|
||||
.setFormLeftIndent(16)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"),
|
||||
apiKeyField
|
||||
)
|
||||
.addComponentToRightColumn(
|
||||
UIUtil.createComment("settingsConfigurable.service.codegpt.apiKey.comment")
|
||||
)
|
||||
.addLabeledComponent("Model:", chatCompletionModelComboBox)
|
||||
.addVerticalGap(4)
|
||||
.panel
|
||||
)
|
||||
.addComponent(TitledSeparator("Code Completions"))
|
||||
.addComponent(
|
||||
FormBuilder.createFormBuilder()
|
||||
.setFormLeftIndent(16)
|
||||
.addComponent(codeCompletionsEnabledCheckBox)
|
||||
.addLabeledComponent("Model:", codeCompletionModelComboBox)
|
||||
.addLabeledComponent("Max tokens:", codeCompletionMaxTokensField)
|
||||
.addComponentToRightColumn(
|
||||
ComponentPanelBuilder.createCommentComponent(
|
||||
CodeGPTBundle.get("codeCompletionsForm.maxTokensComment"), true, 48, true
|
||||
)
|
||||
)
|
||||
.panel
|
||||
)
|
||||
.addComponentFillVertically(JPanel(), 0)
|
||||
.panel
|
||||
|
||||
fun getApiKey() = String(apiKeyField.password).ifEmpty { null }
|
||||
|
||||
fun isModified() = service<CodeGPTServiceSettings>().state.run {
|
||||
(chatCompletionModelComboBox.selectedItem as CodeGPTModel).code != chatCompletionSettings.model
|
||||
|| (codeCompletionModelComboBox.selectedItem as CodeGPTModel).code != codeCompletionSettings.model
|
||||
|| codeCompletionMaxTokensField.value != codeCompletionSettings.maxTokens
|
||||
|| codeCompletionsEnabledCheckBox.isSelected != codeCompletionSettings.codeCompletionsEnabled
|
||||
|| getApiKey() != getCredential(CODEGPT_API_KEY)
|
||||
}
|
||||
|
||||
fun applyChanges() {
|
||||
service<CodeGPTServiceSettings>().state.run {
|
||||
chatCompletionSettings.model =
|
||||
(chatCompletionModelComboBox.selectedItem as CodeGPTModel).code
|
||||
codeCompletionSettings.codeCompletionsEnabled =
|
||||
codeCompletionsEnabledCheckBox.isSelected
|
||||
codeCompletionSettings.maxTokens = codeCompletionMaxTokensField.value
|
||||
codeCompletionSettings.model =
|
||||
(codeCompletionModelComboBox.selectedItem as CodeGPTModel).code
|
||||
}
|
||||
setCredential(CODEGPT_API_KEY, getApiKey())
|
||||
}
|
||||
|
||||
fun resetForm() {
|
||||
service<CodeGPTServiceSettings>().state.run {
|
||||
chatCompletionModelComboBox.selectedItem = chatCompletionSettings.model
|
||||
codeCompletionModelComboBox.selectedItem = codeCompletionSettings.model
|
||||
codeCompletionMaxTokensField.value = codeCompletionSettings.maxTokens
|
||||
codeCompletionsEnabledCheckBox.isSelected =
|
||||
codeCompletionSettings.codeCompletionsEnabled
|
||||
}
|
||||
apiKeyField.text = getCredential(CODEGPT_API_KEY)
|
||||
}
|
||||
|
||||
private class CustomComboBoxRenderer : DefaultListCellRenderer() {
|
||||
override fun getListCellRendererComponent(
|
||||
list: JList<*>,
|
||||
value: Any?,
|
||||
index: Int,
|
||||
isSelected: Boolean,
|
||||
cellHasFocus: Boolean
|
||||
): Component {
|
||||
val component =
|
||||
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus)
|
||||
if (value is CodeGPTModel) {
|
||||
text = value.name
|
||||
}
|
||||
return component
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package ee.carlrobert.codegpt.settings.service.codegpt
|
||||
|
||||
import com.intellij.openapi.components.*
|
||||
|
||||
@Service
|
||||
@State(
|
||||
name = "CodeGPT_CodeGPTServiceSettings",
|
||||
storages = [Storage("CodeGPT_CodeGPTServiceSettings.xml")]
|
||||
)
|
||||
class CodeGPTServiceSettings :
|
||||
SimplePersistentStateComponent<CodeGPTServiceSettingsState>(CodeGPTServiceSettingsState())
|
||||
|
||||
class CodeGPTServiceSettingsState : BaseState() {
|
||||
var chatCompletionSettings by property(CodeGPTServiceChatCompletionSettingsState())
|
||||
var codeCompletionSettings by property(CodeGPTServiceCodeCompletionSettingsState())
|
||||
}
|
||||
|
||||
class CodeGPTServiceChatCompletionSettingsState : BaseState() {
|
||||
var model by string("meta-llama/Llama-3-70b-chat-hf")
|
||||
}
|
||||
|
||||
class CodeGPTServiceCodeCompletionSettingsState : BaseState() {
|
||||
var codeCompletionsEnabled by property(true)
|
||||
var model by string("codellama/CodeLlama-70b-hf")
|
||||
var maxTokens by property(128)
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package ee.carlrobert.codegpt.settings.service.custom
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CUSTOM_SERVICE_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType
|
||||
import ee.carlrobert.codegpt.settings.service.custom.form.CustomServiceForm
|
||||
import javax.swing.JComponent
|
||||
|
||||
class CustomServiceConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: CustomServiceForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: Custom Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = CustomServiceForm()
|
||||
return component.getForm()
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.isModified()
|
||||
|| component.getApiKey() != getCredential(CUSTOM_SERVICE_API_KEY)
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
setCredential(CUSTOM_SERVICE_API_KEY, component.getApiKey())
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.CUSTOM_OPENAI
|
||||
component.applyChanges()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@ package ee.carlrobert.codegpt.settings.service.custom
|
|||
import com.intellij.openapi.components.*
|
||||
import com.intellij.util.xmlb.annotations.OptionTag
|
||||
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate
|
||||
import ee.carlrobert.codegpt.settings.service.custom.template.CustomServiceChatCompletionTemplate
|
||||
import ee.carlrobert.codegpt.settings.service.custom.template.CustomServiceCodeCompletionTemplate
|
||||
import ee.carlrobert.codegpt.settings.service.custom.template.CustomServiceTemplate
|
||||
import ee.carlrobert.codegpt.util.MapConverter
|
||||
|
||||
@Service
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.codegpt.settings.service.custom
|
||||
package ee.carlrobert.codegpt.settings.service.custom.form
|
||||
|
||||
import com.intellij.openapi.ui.MessageType
|
||||
import com.intellij.ui.components.JBTextField
|
||||
|
|
@ -6,6 +6,8 @@ import com.intellij.util.ui.FormBuilder
|
|||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import ee.carlrobert.codegpt.completions.CompletionRequestProvider
|
||||
import ee.carlrobert.codegpt.completions.CompletionRequestService
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceChatCompletionSettingsState
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceFormTabbedPane
|
||||
import ee.carlrobert.codegpt.ui.OverlayUtil
|
||||
import ee.carlrobert.llm.client.openai.completion.ErrorDetails
|
||||
import ee.carlrobert.llm.completion.CompletionEventListener
|
||||
|
|
@ -15,7 +17,10 @@ import javax.swing.JButton
|
|||
import javax.swing.JPanel
|
||||
import javax.swing.SwingUtilities
|
||||
|
||||
class CustomServiceChatCompletionForm(state: CustomServiceChatCompletionSettingsState) {
|
||||
class CustomServiceChatCompletionForm(
|
||||
state: CustomServiceChatCompletionSettingsState,
|
||||
val getApiKey: () -> String?
|
||||
) {
|
||||
|
||||
private val urlField = JBTextField(state.url, 30)
|
||||
private val tabbedPane = CustomServiceFormTabbedPane(state.headers, state.body)
|
||||
|
|
@ -67,7 +72,13 @@ class CustomServiceChatCompletionForm(state: CustomServiceChatCompletionSettings
|
|||
|
||||
private fun testConnection() {
|
||||
CompletionRequestService.getInstance().getCustomOpenAIChatCompletionAsync(
|
||||
CompletionRequestProvider.buildCustomOpenAICompletionRequest("Hello!"),
|
||||
CompletionRequestProvider.buildCustomOpenAICompletionRequest(
|
||||
"Test",
|
||||
urlField.text,
|
||||
tabbedPane.headers,
|
||||
tabbedPane.body,
|
||||
getApiKey.invoke()
|
||||
),
|
||||
TestConnectionEventListener()
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.codegpt.settings.service.custom
|
||||
package ee.carlrobert.codegpt.settings.service.custom.form
|
||||
|
||||
import com.intellij.icons.AllIcons.General
|
||||
import com.intellij.ide.HelpTooltip
|
||||
|
|
@ -16,6 +16,8 @@ import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate
|
|||
import ee.carlrobert.codegpt.codecompletions.InfillRequestDetails
|
||||
import ee.carlrobert.codegpt.completions.CompletionRequestService
|
||||
import ee.carlrobert.codegpt.settings.configuration.Placeholder
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceCodeCompletionSettingsState
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceFormTabbedPane
|
||||
import ee.carlrobert.codegpt.ui.OverlayUtil
|
||||
import ee.carlrobert.llm.client.openai.completion.ErrorDetails
|
||||
import ee.carlrobert.llm.completion.CompletionEventListener
|
||||
|
|
@ -28,7 +30,10 @@ import javax.swing.JButton
|
|||
import javax.swing.JPanel
|
||||
import javax.swing.SwingUtilities
|
||||
|
||||
class CustomServiceCodeCompletionForm(state: CustomServiceCodeCompletionSettingsState) {
|
||||
class CustomServiceCodeCompletionForm(
|
||||
state: CustomServiceCodeCompletionSettingsState,
|
||||
val getApiKey: () -> String?
|
||||
) {
|
||||
|
||||
private val featureEnabledCheckBox = JBCheckBox(
|
||||
CodeGPTBundle.get("codeCompletionsForm.enableFeatureText"),
|
||||
|
|
@ -37,7 +42,7 @@ class CustomServiceCodeCompletionForm(state: CustomServiceCodeCompletionSettings
|
|||
private val promptTemplateComboBox =
|
||||
ComboBox(EnumComboBoxModel(InfillPromptTemplate::class.java)).apply {
|
||||
selectedItem = state.infillTemplate
|
||||
setSelectedItem(InfillPromptTemplate.LLAMA)
|
||||
setSelectedItem(InfillPromptTemplate.CODE_LLAMA)
|
||||
addItemListener {
|
||||
updatePromptTemplateHelpTooltip(it.item as InfillPromptTemplate)
|
||||
}
|
||||
|
|
@ -138,7 +143,14 @@ class CustomServiceCodeCompletionForm(state: CustomServiceCodeCompletionSettings
|
|||
|
||||
private fun testConnection() {
|
||||
CompletionRequestService.getInstance().getCustomOpenAICompletionAsync(
|
||||
CodeCompletionRequestFactory.buildCustomRequest(InfillRequestDetails("Hello", "!")),
|
||||
CodeCompletionRequestFactory.buildCustomRequest(
|
||||
InfillRequestDetails("Hello", "!"),
|
||||
urlField.text,
|
||||
tabbedPane.headers,
|
||||
tabbedPane.body,
|
||||
promptTemplateComboBox.selectedItem as InfillPromptTemplate,
|
||||
getApiKey.invoke()
|
||||
),
|
||||
TestConnectionEventListener()
|
||||
)
|
||||
}
|
||||
|
|
@ -1,18 +1,23 @@
|
|||
package ee.carlrobert.codegpt.settings.service.custom
|
||||
package ee.carlrobert.codegpt.settings.service.custom.form
|
||||
|
||||
import com.intellij.icons.AllIcons.General
|
||||
import com.intellij.ide.HelpTooltip
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.ui.EnumComboBoxModel
|
||||
import com.intellij.ui.TitledSeparator
|
||||
import com.intellij.ui.components.JBLabel
|
||||
import com.intellij.ui.components.JBPasswordField
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceChatCompletionSettingsState
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceCodeCompletionSettingsState
|
||||
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.custom.template.CustomServiceTemplate
|
||||
import ee.carlrobert.codegpt.ui.UIUtil
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.awt.FlowLayout
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
|
|
@ -24,7 +29,6 @@ class CustomServiceForm {
|
|||
|
||||
private val apiKeyField = JBPasswordField().apply {
|
||||
columns = 30
|
||||
text = getCredential(CredentialKey.CUSTOM_SERVICE_API_KEY)
|
||||
}
|
||||
private val templateHelpText = JBLabel(General.ContextHelp)
|
||||
private val templateComboBox = ComboBox(EnumComboBoxModel(CustomServiceTemplate::class.java))
|
||||
|
|
@ -34,8 +38,13 @@ class CustomServiceForm {
|
|||
|
||||
init {
|
||||
val state = service<CustomServiceSettings>().state
|
||||
chatCompletionsForm = CustomServiceChatCompletionForm(state.chatCompletionSettings)
|
||||
codeCompletionsForm = CustomServiceCodeCompletionForm(state.codeCompletionSettings)
|
||||
apiKeyField.text = runBlocking(Dispatchers.IO) {
|
||||
getCredential(CredentialKey.CUSTOM_SERVICE_API_KEY)
|
||||
}
|
||||
chatCompletionsForm =
|
||||
CustomServiceChatCompletionForm(state.chatCompletionSettings, this::getApiKey)
|
||||
codeCompletionsForm =
|
||||
CustomServiceCodeCompletionForm(state.codeCompletionSettings, this::getApiKey)
|
||||
tabbedPane = JTabbedPane().apply {
|
||||
add(CodeGPTBundle.get("shared.chatCompletions"), chatCompletionsForm.form)
|
||||
add(CodeGPTBundle.get("shared.codeCompletions"), codeCompletionsForm.form)
|
||||
|
|
@ -65,29 +74,24 @@ class CustomServiceForm {
|
|||
}
|
||||
|
||||
fun getForm(): JPanel = FormBuilder.createFormBuilder()
|
||||
.addComponent(TitledSeparator(CodeGPTBundle.get("shared.configuration")))
|
||||
.addComponent(
|
||||
FormBuilder.createFormBuilder()
|
||||
.setFormLeftIndent(16)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.custom.openai.presetTemplate.label"),
|
||||
JPanel(FlowLayout(FlowLayout.LEADING, 0, 0)).apply {
|
||||
add(templateComboBox)
|
||||
add(Box.createHorizontalStrut(8))
|
||||
add(templateHelpText)
|
||||
}
|
||||
)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"),
|
||||
apiKeyField
|
||||
)
|
||||
.addComponentToRightColumn(
|
||||
UIUtil.createComment("settingsConfigurable.service.custom.openai.apiKey.comment")
|
||||
)
|
||||
.addVerticalGap(4)
|
||||
.addComponent(tabbedPane)
|
||||
.panel
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.service.custom.openai.presetTemplate.label"),
|
||||
JPanel(FlowLayout(FlowLayout.LEADING, 0, 0)).apply {
|
||||
add(templateComboBox)
|
||||
add(Box.createHorizontalStrut(8))
|
||||
add(templateHelpText)
|
||||
}
|
||||
)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"),
|
||||
apiKeyField
|
||||
)
|
||||
.addComponentToRightColumn(
|
||||
UIUtil.createComment("settingsConfigurable.service.custom.openai.apiKey.comment")
|
||||
)
|
||||
.addVerticalGap(4)
|
||||
.addComponent(tabbedPane)
|
||||
.addComponentFillVertically(JPanel(), 0)
|
||||
.panel
|
||||
|
||||
fun getApiKey() = String(apiKeyField.password).ifEmpty { null }
|
||||
|
|
@ -102,7 +106,6 @@ class CustomServiceForm {
|
|||
|| codeCompletionsForm.url != codeCompletionSettings.url
|
||||
|| codeCompletionsForm.headers != codeCompletionSettings.headers
|
||||
|| codeCompletionsForm.body != codeCompletionSettings.body
|
||||
|| getApiKey() != getCredential(CredentialKey.CUSTOM_SERVICE_API_KEY)
|
||||
}
|
||||
|
||||
fun applyChanges() {
|
||||
|
|
@ -126,6 +129,7 @@ class CustomServiceForm {
|
|||
fun resetForm() {
|
||||
service<CustomServiceSettings>().state.run {
|
||||
templateComboBox.item = template
|
||||
apiKeyField.text = getCredential(CredentialKey.CUSTOM_SERVICE_API_KEY)
|
||||
chatCompletionsForm.resetForm(chatCompletionSettings)
|
||||
codeCompletionsForm.resetForm(codeCompletionSettings)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.codegpt.settings.service.custom
|
||||
package ee.carlrobert.codegpt.settings.service.custom.template
|
||||
|
||||
enum class CustomServiceChatCompletionTemplate(
|
||||
val url: String,
|
||||
|
|
@ -89,6 +89,16 @@ enum class CustomServiceChatCompletionTemplate(
|
|||
"http://localhost:8080/v1/chat/completions",
|
||||
getDefaultHeaders(),
|
||||
getDefaultBodyParams(emptyMap())
|
||||
),
|
||||
MISTRAL_AI(
|
||||
"https://api.mistral.ai/v1/chat/completions",
|
||||
getDefaultHeaders("Authorization", "Bearer \$CUSTOM_SERVICE_API_KEY"),
|
||||
getDefaultBodyParams(
|
||||
mapOf(
|
||||
"model" to "open-mistral-7b",
|
||||
"max_tokens" to 1024
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.codegpt.settings.service.custom
|
||||
package ee.carlrobert.codegpt.settings.service.custom.template
|
||||
|
||||
enum class CustomServiceCodeCompletionTemplate(
|
||||
val url: String,
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.codegpt.settings.service.custom
|
||||
package ee.carlrobert.codegpt.settings.service.custom.template
|
||||
|
||||
enum class CustomServiceTemplate(
|
||||
val providerName: String,
|
||||
|
|
@ -61,6 +61,11 @@ enum class CustomServiceTemplate(
|
|||
"LLaMA C/C++",
|
||||
"https://github.com/ggerganov/llama.cpp/blob/master/examples/server/README.md",
|
||||
CustomServiceChatCompletionTemplate.LLAMA_CPP
|
||||
),
|
||||
MISTRAL_AI(
|
||||
"Mistral AI",
|
||||
"https://docs.mistral.ai/getting-started/quickstart",
|
||||
CustomServiceChatCompletionTemplate.MISTRAL_AI
|
||||
);
|
||||
|
||||
override fun toString(): String {
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package ee.carlrobert.codegpt.settings.service.google
|
||||
|
||||
import com.intellij.openapi.components.*
|
||||
import ee.carlrobert.llm.client.google.models.GoogleModel
|
||||
|
||||
@Service
|
||||
@State(name = "CodeGPT_GoogleSettings_210", storages = [Storage("CodeGPT_GoogleSettings_210.xml")])
|
||||
class GoogleSettings : SimplePersistentStateComponent<GoogleSettingsState>(GoogleSettingsState())
|
||||
|
||||
class GoogleSettingsState : BaseState() {
|
||||
var model by string(GoogleModel.GEMINI_PRO.code)
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package ee.carlrobert.codegpt.settings.service.google;
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.GOOGLE_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType
|
||||
import javax.swing.JComponent
|
||||
|
||||
class GoogleSettingsConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: GoogleSettingsForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: Google Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = GoogleSettingsForm()
|
||||
return component.getForm()
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.isModified() || component.getApiKey() != getCredential(GOOGLE_API_KEY)
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
setCredential(GOOGLE_API_KEY, component.getApiKey())
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.GOOGLE
|
||||
component.applyChanges()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package ee.carlrobert.codegpt.settings.service.google
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.ui.EnumComboBoxModel
|
||||
import com.intellij.ui.TitledSeparator
|
||||
import com.intellij.ui.components.JBPasswordField
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import com.intellij.util.ui.UI
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.GOOGLE_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
|
||||
import ee.carlrobert.codegpt.ui.UIUtil
|
||||
import ee.carlrobert.llm.client.google.models.GoogleModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import javax.swing.JPanel
|
||||
import javax.swing.event.HyperlinkEvent
|
||||
|
||||
class GoogleSettingsForm {
|
||||
|
||||
private val apiKeyField = JBPasswordField()
|
||||
private val completionModelComboBox: ComboBox<GoogleModel>
|
||||
|
||||
init {
|
||||
val state = service<GoogleSettings>().state
|
||||
apiKeyField.columns = 30
|
||||
apiKeyField.text = runBlocking(Dispatchers.IO) {
|
||||
getCredential(GOOGLE_API_KEY)
|
||||
}
|
||||
completionModelComboBox = ComboBox(
|
||||
EnumComboBoxModel(GoogleModel::class.java)
|
||||
)
|
||||
completionModelComboBox.selectedItem = GoogleModel.findByCode(state.model)
|
||||
}
|
||||
|
||||
fun getForm(): JPanel = FormBuilder.createFormBuilder()
|
||||
.addComponent(TitledSeparator(CodeGPTBundle.get("shared.configuration")))
|
||||
.addComponent(
|
||||
UIUtil.withEmptyLeftBorder(
|
||||
UI.PanelFactory.grid()
|
||||
.add(
|
||||
UI.PanelFactory.panel(apiKeyField)
|
||||
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
|
||||
.resizeX(false)
|
||||
.withComment(CodeGPTBundle.get("settingsConfigurable.service.google.apiKey.comment"))
|
||||
.withCommentHyperlinkListener { event: HyperlinkEvent? ->
|
||||
UIUtil.handleHyperlinkClicked(
|
||||
event
|
||||
)
|
||||
})
|
||||
|
||||
.add(
|
||||
UI.PanelFactory.panel(completionModelComboBox)
|
||||
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.model.label"))
|
||||
.resizeX(false)
|
||||
.withComment(CodeGPTBundle.get("settingsConfigurable.service.google.model.comment"))
|
||||
.withCommentHyperlinkListener { event: HyperlinkEvent? ->
|
||||
UIUtil.handleHyperlinkClicked(
|
||||
event
|
||||
)
|
||||
}
|
||||
)
|
||||
.createPanel()
|
||||
)
|
||||
)
|
||||
.addComponentFillVertically(JPanel(), 0)
|
||||
.panel
|
||||
|
||||
|
||||
fun getApiKey(): String? = String(apiKeyField.password).ifEmpty { null }
|
||||
|
||||
fun getModel(): String = (completionModelComboBox.model
|
||||
.selectedItem as GoogleModel)
|
||||
.code
|
||||
|
||||
fun getCurrentState() = GoogleSettingsState().apply { model = getModel() }
|
||||
|
||||
fun resetForm() {
|
||||
val state = service<GoogleSettings>().state
|
||||
apiKeyField.text = getCredential(GOOGLE_API_KEY)
|
||||
completionModelComboBox.selectedItem = GoogleModel.findByCode(state.model)
|
||||
}
|
||||
|
||||
fun isModified(): Boolean = service<GoogleSettings>().state.run {
|
||||
model != getModel() || getApiKey() != getCredential(GOOGLE_API_KEY)
|
||||
}
|
||||
|
||||
fun applyChanges() {
|
||||
service<GoogleSettings>().state.run {
|
||||
model = getModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package ee.carlrobert.codegpt.settings.service.ollama
|
||||
|
||||
import com.intellij.openapi.components.BaseState
|
||||
import com.intellij.openapi.components.SimplePersistentStateComponent
|
||||
import com.intellij.openapi.components.State
|
||||
import com.intellij.openapi.components.Storage
|
||||
import ee.carlrobert.codegpt.codecompletions.InfillPromptTemplate
|
||||
|
||||
@State(name = "CodeGPT_OllamaSettings_210", storages = [Storage("CodeGPT_OllamaSettings_210.xml")])
|
||||
class OllamaSettings :
|
||||
SimplePersistentStateComponent<OllamaSettingsState>(OllamaSettingsState())
|
||||
|
||||
class OllamaSettingsState : BaseState() {
|
||||
var host by string("http://localhost:11434")
|
||||
var model by string()
|
||||
var codeCompletionsEnabled by property(true)
|
||||
var codeCompletionMaxTokens by property(128)
|
||||
var fimTemplate by enum<InfillPromptTemplate>(InfillPromptTemplate.CODE_LLAMA)
|
||||
var availableModels by list<String>()
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package ee.carlrobert.codegpt.settings.service.ollama
|
||||
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType
|
||||
import javax.swing.JComponent
|
||||
|
||||
class OllamaSettingsConfigurable : Configurable {
|
||||
|
||||
private lateinit var component: OllamaSettingsForm
|
||||
|
||||
override fun getDisplayName(): String {
|
||||
return "CodeGPT: Ollama Service"
|
||||
}
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
component = OllamaSettingsForm()
|
||||
return component.getForm()
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return component.isModified()
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
component.applyChanges()
|
||||
service<GeneralSettings>().state.selectedService = ServiceType.OLLAMA
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
component.resetForm()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
package ee.carlrobert.codegpt.settings.service.ollama
|
||||
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.openapi.application.invokeLater
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.observable.util.whenTextChangedFromUi
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.ui.TitledSeparator
|
||||
import com.intellij.ui.components.JBTextField
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import ee.carlrobert.codegpt.settings.service.CodeCompletionConfigurationForm
|
||||
import ee.carlrobert.codegpt.ui.OverlayUtil
|
||||
import ee.carlrobert.codegpt.ui.UIUtil
|
||||
import ee.carlrobert.llm.client.ollama.OllamaClient
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.awt.BorderLayout
|
||||
import java.net.ConnectException
|
||||
import javax.swing.ComboBoxModel
|
||||
import javax.swing.DefaultComboBoxModel
|
||||
import javax.swing.JButton
|
||||
import javax.swing.JPanel
|
||||
|
||||
class OllamaSettingsForm {
|
||||
|
||||
private val refreshModelsButton =
|
||||
JButton(CodeGPTBundle.get("settingsConfigurable.service.ollama.models.refresh"))
|
||||
private val hostField: JBTextField
|
||||
private val modelComboBox: ComboBox<String>
|
||||
private val codeCompletionConfigurationForm: CodeCompletionConfigurationForm
|
||||
|
||||
companion object {
|
||||
private val logger = thisLogger()
|
||||
}
|
||||
|
||||
init {
|
||||
val settings = service<OllamaSettings>().state
|
||||
codeCompletionConfigurationForm = CodeCompletionConfigurationForm(
|
||||
settings.codeCompletionsEnabled,
|
||||
settings.codeCompletionMaxTokens,
|
||||
settings.fimTemplate
|
||||
)
|
||||
val emptyModelsComboBoxModel =
|
||||
DefaultComboBoxModel(arrayOf("Hit refresh to see models for this host"))
|
||||
modelComboBox = ComboBox(emptyModelsComboBoxModel).apply {
|
||||
isEnabled = false
|
||||
}
|
||||
hostField = JBTextField().apply {
|
||||
text = settings.host
|
||||
whenTextChangedFromUi {
|
||||
modelComboBox.model = emptyModelsComboBoxModel
|
||||
modelComboBox.isEnabled = false
|
||||
}
|
||||
}
|
||||
refreshModelsButton.addActionListener { refreshModels() }
|
||||
}
|
||||
|
||||
fun getForm(): JPanel = FormBuilder.createFormBuilder()
|
||||
.addComponent(TitledSeparator(CodeGPTBundle.get("shared.configuration")))
|
||||
.addComponent(
|
||||
FormBuilder.createFormBuilder()
|
||||
.setFormLeftIndent(16)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.shared.baseHost.label"),
|
||||
hostField
|
||||
)
|
||||
.addLabeledComponent(
|
||||
CodeGPTBundle.get("settingsConfigurable.shared.model.label"),
|
||||
JPanel(BorderLayout(8, 0)).apply {
|
||||
add(modelComboBox, BorderLayout.CENTER)
|
||||
add(refreshModelsButton, BorderLayout.EAST)
|
||||
}
|
||||
)
|
||||
.panel
|
||||
)
|
||||
.addComponent(TitledSeparator(CodeGPTBundle.get("shared.codeCompletions")))
|
||||
.addComponent(UIUtil.withEmptyLeftBorder(codeCompletionConfigurationForm.getForm()))
|
||||
.addComponentFillVertically(JPanel(), 0)
|
||||
.panel
|
||||
|
||||
fun getModel(): String {
|
||||
return if (modelComboBox.isEnabled) {
|
||||
modelComboBox.item
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
fun resetForm() {
|
||||
service<OllamaSettings>().state.run {
|
||||
hostField.text = host
|
||||
modelComboBox.item = model
|
||||
codeCompletionConfigurationForm.isCodeCompletionsEnabled = codeCompletionsEnabled
|
||||
codeCompletionConfigurationForm.maxTokens = codeCompletionMaxTokens
|
||||
codeCompletionConfigurationForm.fimTemplate = fimTemplate
|
||||
}
|
||||
}
|
||||
|
||||
fun applyChanges() {
|
||||
service<OllamaSettings>().state.run {
|
||||
host = hostField.text
|
||||
model = modelComboBox.item
|
||||
codeCompletionsEnabled = codeCompletionConfigurationForm.isCodeCompletionsEnabled
|
||||
codeCompletionMaxTokens = codeCompletionConfigurationForm.maxTokens
|
||||
fimTemplate = codeCompletionConfigurationForm.fimTemplate!!
|
||||
}
|
||||
}
|
||||
|
||||
fun isModified() = service<OllamaSettings>().state.run {
|
||||
hostField.text != host
|
||||
|| modelComboBox.item != model
|
||||
|| codeCompletionConfigurationForm.isCodeCompletionsEnabled != codeCompletionsEnabled
|
||||
|| codeCompletionConfigurationForm.maxTokens != codeCompletionMaxTokens
|
||||
|| codeCompletionConfigurationForm.fimTemplate != fimTemplate
|
||||
}
|
||||
|
||||
fun refreshModels() {
|
||||
disableModelComboBoxWithPlaceholder(DefaultComboBoxModel(arrayOf("Loading")))
|
||||
try {
|
||||
val models = runBlocking(Dispatchers.IO) {
|
||||
OllamaClient.Builder()
|
||||
.setHost(hostField.text)
|
||||
.build()
|
||||
.modelTags
|
||||
.models
|
||||
.map { it.name }
|
||||
}
|
||||
service<OllamaSettings>().state.availableModels = models.toMutableList()
|
||||
invokeLater {
|
||||
modelComboBox.apply {
|
||||
if (models.isNotEmpty()) {
|
||||
model = DefaultComboBoxModel(models.toTypedArray())
|
||||
isEnabled = true
|
||||
} else {
|
||||
model = DefaultComboBoxModel(arrayOf("No models"))
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ex: RuntimeException) {
|
||||
logger.error(ex)
|
||||
if (ex.cause is ConnectException) {
|
||||
OverlayUtil.showNotification(
|
||||
"Unable to connect to Ollama server",
|
||||
NotificationType.ERROR
|
||||
)
|
||||
} else {
|
||||
OverlayUtil.showNotification(ex.message, NotificationType.ERROR)
|
||||
}
|
||||
disableModelComboBoxWithPlaceholder(DefaultComboBoxModel(arrayOf("Unable to load models")))
|
||||
}
|
||||
}
|
||||
|
||||
private fun disableModelComboBoxWithPlaceholder(placeholderModel: ComboBoxModel<String>) {
|
||||
invokeLater {
|
||||
modelComboBox.apply {
|
||||
model = placeholderModel
|
||||
isEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
<depends>com.intellij.modules.platform</depends>
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
<depends optional="true" config-file="plugin-java.xml">com.intellij.modules.java</depends>
|
||||
<depends optional="true">Git4Idea</depends>
|
||||
|
||||
<projectListeners>
|
||||
<listener topic="com.intellij.codeInsight.lookup.LookupManagerListener"
|
||||
|
|
@ -18,6 +19,26 @@
|
|||
<postStartupActivity implementation="ee.carlrobert.codegpt.CodeGPTUpdateActivity"/>
|
||||
<applicationConfigurable id="settings.codegpt" parentId="tools" displayName="CodeGPT"
|
||||
instance="ee.carlrobert.codegpt.settings.GeneralSettingsConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services" parentId="settings.codegpt" displayName="Providers"
|
||||
instance="ee.carlrobert.codegpt.settings.service.ServiceConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.codegpt" parentId="settings.codegpt.services" displayName="CodeGPT"
|
||||
instance="ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.openai" parentId="settings.codegpt.services" displayName="OpenAI"
|
||||
instance="ee.carlrobert.codegpt.settings.service.OpenAIServiceConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.custom" parentId="settings.codegpt.services" displayName="Custom OpenAI"
|
||||
instance="ee.carlrobert.codegpt.settings.service.custom.CustomServiceConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.azure" parentId="settings.codegpt.services" displayName="Azure"
|
||||
instance="ee.carlrobert.codegpt.settings.service.AzureServiceConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.anthropic" parentId="settings.codegpt.services" displayName="Anthropic"
|
||||
instance="ee.carlrobert.codegpt.settings.service.AnthropicServiceConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.google" parentId="settings.codegpt.services" displayName="Google"
|
||||
instance="ee.carlrobert.codegpt.settings.service.google.GoogleSettingsConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.you" parentId="settings.codegpt.services" displayName="You.com"
|
||||
instance="ee.carlrobert.codegpt.settings.service.YouServiceConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.llama_cpp" parentId="settings.codegpt.services" displayName="LLaMA C/C++ (Local)"
|
||||
instance="ee.carlrobert.codegpt.settings.service.LlamaServiceConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.services.ollama" parentId="settings.codegpt.services" displayName="Ollama (Local)"
|
||||
instance="ee.carlrobert.codegpt.settings.service.ollama.OllamaSettingsConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.configuration" parentId="settings.codegpt" displayName="Configuration"
|
||||
instance="ee.carlrobert.codegpt.settings.configuration.ConfigurationConfigurable"/>
|
||||
<applicationConfigurable id="settings.codegpt.advanced" parentId="settings.codegpt" displayName="Advanced Settings"
|
||||
|
|
@ -35,6 +56,7 @@
|
|||
<applicationService serviceImplementation="ee.carlrobert.codegpt.settings.service.openai.OpenAISettings"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.codegpt.settings.service.you.YouSettings"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.codegpt.settings.service.llama.LlamaSettings"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.codegpt.settings.IncludedFilesSettings"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.codegpt.settings.advanced.AdvancedSettings"/>
|
||||
|
|
|
|||
2
src/main/resources/icons/codegpt-model.svg
Normal file
2
src/main/resources/icons/codegpt-model.svg
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="13px" height="13px" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--emojione-monotone" preserveAspectRatio="xMidYMid meet"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m-4.592 37.521c1.316 1.621 2.988 2.431 5.018 2.431c2.078 0 3.664-.695 4.756-2.086c.604-.748 1.104-1.87 1.502-3.366h6.023c-.52 3.163-1.848 5.735-3.982 7.717c-2.137 1.981-4.871 2.972-8.209 2.972c-4.129 0-7.375-1.338-9.736-4.016c-2.363-2.689-3.545-6.378-3.545-11.063c0-5.066 1.344-8.971 4.031-11.713c2.338-2.389 5.311-3.583 8.92-3.583c4.83 0 8.361 1.601 10.594 4.804c1.234 1.798 1.896 3.602 1.986 5.413h-6.063c-.387-1.392-.881-2.44-1.484-3.149c-1.08-1.26-2.682-1.891-4.803-1.891c-2.16 0-3.863.89-5.111 2.668c-1.246 1.778-1.869 4.295-1.869 7.549c0 3.254.658 5.691 1.972 7.313" fill="#000000"></path></svg>
|
||||
|
After Width: | Height: | Size: 1 KiB |
2
src/main/resources/icons/codegpt-model_dark.svg
Normal file
2
src/main/resources/icons/codegpt-model_dark.svg
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="13px" height="13px" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--emojione-monotone" preserveAspectRatio="xMidYMid meet"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m-4.592 37.521c1.316 1.621 2.988 2.431 5.018 2.431c2.078 0 3.664-.695 4.756-2.086c.604-.748 1.104-1.87 1.502-3.366h6.023c-.52 3.163-1.848 5.735-3.982 7.717c-2.137 1.981-4.871 2.972-8.209 2.972c-4.129 0-7.375-1.338-9.736-4.016c-2.363-2.689-3.545-6.378-3.545-11.063c0-5.066 1.344-8.971 4.031-11.713c2.338-2.389 5.311-3.583 8.92-3.583c4.83 0 8.361 1.601 10.594 4.804c1.234 1.798 1.896 3.602 1.986 5.413h-6.063c-.387-1.392-.881-2.44-1.484-3.149c-1.08-1.26-2.682-1.891-4.803-1.891c-2.16 0-3.863.89-5.111 2.668c-1.246 1.778-1.869 4.295-1.869 7.549c0 3.254.658 5.691 1.972 7.313" fill="#ffffff"></path></svg>
|
||||
|
After Width: | Height: | Size: 1 KiB |
14
src/main/resources/icons/google.svg
Normal file
14
src/main/resources/icons/google.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M16 8.016A8.522 8.522 0 008.016 16h-.032A8.521 8.521 0 000 8.016v-.032A8.521 8.521 0 007.984 0h.032A8.522 8.522 0 0016 7.984v.032z"
|
||||
fill="url(#prefix__paint0_radial_980_20147)"/>
|
||||
<defs>
|
||||
<radialGradient id="prefix__paint0_radial_980_20147" cx="0" cy="0" r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(16.1326 5.4553 -43.70045 129.2322 1.588 6.503)">
|
||||
<stop offset=".067" stop-color="#9168C0"/>
|
||||
<stop offset=".343" stop-color="#5684D1"/>
|
||||
<stop offset=".672" stop-color="#1BA1E3"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 660 B |
7
src/main/resources/icons/ollama.svg
Normal file
7
src/main/resources/icons/ollama.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.3 KiB |
7
src/main/resources/icons/ollama_dark.svg
Normal file
7
src/main/resources/icons/ollama_dark.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.3 KiB |
|
|
@ -17,12 +17,15 @@ action.statusbar.disableCompletions=Disable Completions
|
|||
settings.displayName=CodeGPT: Settings
|
||||
settings.openaiQuotaExceeded=OpenAI quota exceeded.
|
||||
settingsConfigurable.displayName.label=Display name:
|
||||
settingsConfigurable.service.label=Service:
|
||||
settingsConfigurable.service.label=Selected provider:
|
||||
settingsConfigurable.service.codegpt.apiKey.comment=You can find the API key in your <a href="https://codegpt.carlrobert.ee/account">User settings</a>.
|
||||
settingsConfigurable.service.custom.openai.apiKey.comment=A secret value stored in the system's Keychain or KeePass, depending on your OS. This approach is recommended over storing the secret in the header as plain text.
|
||||
settingsConfigurable.service.openai.apiKey.comment=You can find the API key in your <a href="https://platform.openai.com/account/api-keys">User settings</a>.
|
||||
settingsConfigurable.service.openai.customModel.label=Custom model:
|
||||
settingsConfigurable.service.openai.organization.label=Organization:
|
||||
settingsConfigurable.section.openai.organization.comment=Useful when you are part of multiple organizations <sup><strong>optional</strong></sup>
|
||||
settingsConfigurable.service.google.apiKey.comment=You can find the API key in your <a href="https://aistudio.google.com/app/apikey">User settings</a>.
|
||||
settingsConfigurable.service.google.model.comment=Note: Gemini Vision models <a href="https://ai.google.dev/gemini-api/docs/get-started/web?multi-turn-conversations-chat&hl=en#multi-turn-conversations-chat">do not yet support chats</a>.
|
||||
settingsConfigurable.service.anthropic.apiKey.comment=You can find the API key in your <a href="https://console.anthropic.com/settings/keys">User settings</a>.
|
||||
settingsConfigurable.service.anthropic.apiVersion.comment=We always recommend using the <a href="https://docs.anthropic.com/claude/reference/versions">latest API version</a> whenever possible.
|
||||
settingsConfigurable.service.anthropic.model.comment=For details on model comparison metrics, see <a href="https://docs.anthropic.com/claude/docs/models-overview#model-comparison">model comparison</a>.
|
||||
|
|
@ -116,6 +119,7 @@ settingsConfigurable.service.custom.openai.url.label=URL:
|
|||
settingsConfigurable.service.custom.openai.linkToDocs=Link to API docs
|
||||
settingsConfigurable.service.custom.openai.connectionSuccess=Connection successful.
|
||||
settingsConfigurable.service.custom.openai.connectionFailed=Connection failed.
|
||||
settingsConfigurable.service.ollama.models.refresh=Refresh Models
|
||||
configurationConfigurable.section.commitMessage.title=Commit Message Template
|
||||
configurationConfigurable.section.commitMessage.systemPromptField.label=Prompt template:
|
||||
configurationConfigurable.section.inlineCompletion.title=Inline Completion
|
||||
|
|
@ -167,12 +171,15 @@ toolwindow.chat.youProCheckBox.enable=Turn on for complex queries
|
|||
toolwindow.chat.youProCheckBox.disable=Turn off for faster responses
|
||||
toolwindow.chat.youProCheckBox.notAllowed=Enable by subscribing to YouPro plan
|
||||
toolwindow.chat.textArea.emptyText=Ask me anything...
|
||||
service.openai.title=OpenAI Service
|
||||
service.custom.openai.title=Custom OpenAI Service
|
||||
service.anthropic.title=Anthropic Service
|
||||
service.azure.title=Azure Service
|
||||
service.you.title=You.com Service (Free, Cloud)
|
||||
service.llama.title=LLaMA C/C++ Port (Free, Local)
|
||||
service.codegpt.title=CodeGPT
|
||||
service.openai.title=OpenAI
|
||||
service.custom.openai.title=Custom OpenAI
|
||||
service.anthropic.title=Anthropic
|
||||
service.azure.title=Azure
|
||||
service.google.title=Google
|
||||
service.you.title=You.com
|
||||
service.llama.title=LLaMA C/C++ (Local)
|
||||
service.ollama.title=Ollama (Local)
|
||||
validation.error.fieldRequired=This field is required.
|
||||
validation.error.invalidEmail=The email you entered is invalid.
|
||||
validation.error.mustBeNumber=Value must be number.
|
||||
|
|
@ -204,4 +211,4 @@ shared.chatCompletions=Chat Completions
|
|||
shared.codeCompletions=Code Completions
|
||||
codeCompletionsForm.enableFeatureText=Enable code completions
|
||||
codeCompletionsForm.maxTokensLabel=Max tokens:
|
||||
codeCompletionsForm.maxTokensComment=The maximum number of tokens that can be generated in the code completion.
|
||||
codeCompletionsForm.maxTokensComment=The maximum number of tokens that will be generated in the code completion.
|
||||
|
|
@ -39,7 +39,7 @@ class CodeCompletionServiceTest : IntegrationTest() {
|
|||
assertThat(request.method).isEqualTo("POST")
|
||||
assertThat(request.body)
|
||||
.extracting("prompt")
|
||||
.isEqualTo(InfillPromptTemplate.LLAMA.buildPrompt(prefix, suffix))
|
||||
.isEqualTo(InfillPromptTemplate.CODE_LLAMA.buildPrompt(prefix, suffix))
|
||||
listOf(
|
||||
jsonMapResponse(
|
||||
e("content", expectedCompletion),
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ package ee.carlrobert.codegpt.completions
|
|||
import ee.carlrobert.codegpt.completions.CompletionRequestProvider.COMPLETION_SYSTEM_PROMPT
|
||||
import ee.carlrobert.codegpt.conversations.ConversationService
|
||||
import ee.carlrobert.codegpt.conversations.message.Message
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings
|
||||
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
|
|
@ -14,7 +12,7 @@ import testsupport.IntegrationTest
|
|||
class CompletionRequestProviderTest : IntegrationTest() {
|
||||
|
||||
fun testChatCompletionRequestWithSystemPromptOverride() {
|
||||
setCredential(CredentialKey.OPENAI_API_KEY, "TEST_API_KEY")
|
||||
useOpenAIService()
|
||||
ConfigurationSettings.getCurrentState().systemPrompt = "TEST_SYSTEM_PROMPT"
|
||||
val conversation = ConversationService.getInstance().startConversation()
|
||||
val firstMessage = createDummyMessage(500)
|
||||
|
|
@ -43,6 +41,7 @@ class CompletionRequestProviderTest : IntegrationTest() {
|
|||
}
|
||||
|
||||
fun testChatCompletionRequestWithoutSystemPromptOverride() {
|
||||
useOpenAIService()
|
||||
ConfigurationSettings.getCurrentState().systemPrompt = COMPLETION_SYSTEM_PROMPT
|
||||
val conversation = ConversationService.getInstance().startConversation()
|
||||
val firstMessage = createDummyMessage(500)
|
||||
|
|
@ -71,6 +70,7 @@ class CompletionRequestProviderTest : IntegrationTest() {
|
|||
}
|
||||
|
||||
fun testChatCompletionRequestRetry() {
|
||||
useOpenAIService()
|
||||
ConfigurationSettings.getCurrentState().systemPrompt = "TEST_SYSTEM_PROMPT"
|
||||
val conversation = ConversationService.getInstance().startConversation()
|
||||
val firstMessage = createDummyMessage("FIRST_TEST_PROMPT", 500)
|
||||
|
|
@ -97,6 +97,7 @@ class CompletionRequestProviderTest : IntegrationTest() {
|
|||
}
|
||||
|
||||
fun testReducedChatCompletionRequest() {
|
||||
useOpenAIService()
|
||||
ConfigurationSettings.getCurrentState().systemPrompt = COMPLETION_SYSTEM_PROMPT
|
||||
val conversation = ConversationService.getInstance().startConversation()
|
||||
conversation.addMessage(createDummyMessage(50))
|
||||
|
|
@ -126,6 +127,7 @@ class CompletionRequestProviderTest : IntegrationTest() {
|
|||
}
|
||||
|
||||
fun testTotalUsageExceededException() {
|
||||
useOpenAIService()
|
||||
val conversation = ConversationService.getInstance().startConversation()
|
||||
conversation.addMessage(createDummyMessage(1500))
|
||||
conversation.addMessage(createDummyMessage(1500))
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@ import ee.carlrobert.codegpt.conversations.message.Message
|
|||
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings
|
||||
import ee.carlrobert.llm.client.http.RequestEntity
|
||||
import ee.carlrobert.llm.client.http.exchange.StreamHttpExchange
|
||||
import ee.carlrobert.llm.client.util.JSONUtil.e
|
||||
import ee.carlrobert.llm.client.util.JSONUtil.jsonArray
|
||||
import ee.carlrobert.llm.client.util.JSONUtil.jsonMap
|
||||
import ee.carlrobert.llm.client.util.JSONUtil.jsonMapResponse
|
||||
import ee.carlrobert.llm.client.util.JSONUtil.*
|
||||
import org.apache.http.HttpHeaders
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import testsupport.IntegrationTest
|
||||
|
|
@ -171,6 +168,74 @@ class DefaultCompletionRequestHandlerTest : IntegrationTest() {
|
|||
waitExpecting { "Hello!" == message.response }
|
||||
}
|
||||
|
||||
|
||||
fun testGoogleChatCompletionCall() {
|
||||
useGoogleService()
|
||||
ConfigurationSettings.getCurrentState().systemPrompt = "TEST_SYSTEM_PROMPT"
|
||||
val message = Message("TEST_PROMPT")
|
||||
val conversation = ConversationService.getInstance().startConversation()
|
||||
val requestHandler = CompletionRequestHandler(getRequestEventListener(message))
|
||||
expectGoogle(StreamHttpExchange { request: RequestEntity ->
|
||||
assertThat(request.uri.path).isEqualTo("/v1/models/gemini-pro:streamGenerateContent")
|
||||
assertThat(request.method).isEqualTo("POST")
|
||||
assertThat(request.uri.query).isEqualTo("key=TEST_API_KEY&alt=sse")
|
||||
assertThat(request.body)
|
||||
.extracting("contents")
|
||||
.isEqualTo(
|
||||
listOf(
|
||||
mapOf("parts" to listOf(mapOf("text" to "TEST_SYSTEM_PROMPT")), "role" to "user"),
|
||||
mapOf("parts" to listOf(mapOf("text" to "Understood.")), "role" to "model"),
|
||||
mapOf("parts" to listOf(mapOf("text" to "TEST_PROMPT")), "role" to "user"),
|
||||
)
|
||||
)
|
||||
listOf(
|
||||
jsonMapResponse(
|
||||
"candidates",
|
||||
jsonArray(jsonMap("content", jsonMap("parts", jsonArray(jsonMap("text", "Hello")))))
|
||||
),
|
||||
jsonMapResponse(
|
||||
"candidates",
|
||||
jsonArray(jsonMap("content", jsonMap("parts", jsonArray(jsonMap("text", "!")))))
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
requestHandler.call(CallParameters(conversation, ConversationType.DEFAULT, message, false))
|
||||
|
||||
waitExpecting { "Hello!" == message.response }
|
||||
}
|
||||
|
||||
fun testCodeGPTServiceChatCompletionCall() {
|
||||
useCodeGPTService()
|
||||
ConfigurationSettings.getCurrentState().systemPrompt = "TEST_SYSTEM_PROMPT"
|
||||
val message = Message("TEST_PROMPT")
|
||||
val conversation = ConversationService.getInstance().startConversation()
|
||||
val requestHandler = CompletionRequestHandler(getRequestEventListener(message))
|
||||
expectCodeGPT(StreamHttpExchange { request: RequestEntity ->
|
||||
assertThat(request.uri.path).isEqualTo("/v1/chat/completions")
|
||||
assertThat(request.method).isEqualTo("POST")
|
||||
assertThat(request.headers[HttpHeaders.AUTHORIZATION]!![0]).isEqualTo("Bearer TEST_API_KEY")
|
||||
assertThat(request.body)
|
||||
.extracting(
|
||||
"model",
|
||||
"messages")
|
||||
.containsExactly(
|
||||
"TEST_MODEL",
|
||||
listOf(
|
||||
mapOf("role" to "system", "content" to "TEST_SYSTEM_PROMPT"),
|
||||
mapOf("role" to "user", "content" to "TEST_PROMPT")))
|
||||
listOf(
|
||||
jsonMapResponse("choices", jsonArray(jsonMap("delta", jsonMap("role", "assistant")))),
|
||||
jsonMapResponse("choices", jsonArray(jsonMap("delta", jsonMap("content", "Hel")))),
|
||||
jsonMapResponse("choices", jsonArray(jsonMap("delta", jsonMap("content", "lo")))),
|
||||
jsonMapResponse("choices", jsonArray(jsonMap("delta", jsonMap("content", "!")))))
|
||||
})
|
||||
|
||||
requestHandler.call(CallParameters(conversation, ConversationType.DEFAULT, message, false))
|
||||
|
||||
waitExpecting { "Hello!" == message.response }
|
||||
}
|
||||
|
||||
private fun getRequestEventListener(message: Message): CompletionResponseEventListener {
|
||||
return object : CompletionResponseEventListener {
|
||||
override fun handleCompleted(fullMessage: String, callParameters: CallParameters) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@ package ee.carlrobert.codegpt.completions
|
|||
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate.ALPACA
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate.CHAT_ML
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate.CODE_GEMMA
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate.CODE_QWEN
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate.LLAMA
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate.LLAMA_3
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate.PHI_3
|
||||
import ee.carlrobert.codegpt.completions.llama.PromptTemplate.TORA
|
||||
import ee.carlrobert.codegpt.conversations.message.Message
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
|
|
@ -104,6 +107,208 @@ class PromptTemplateTest {
|
|||
TEST_USER_PROMPT<|eot_id|><|start_header_id|>assistant<|end_header_id|>""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldBuildPhi3PromptWithoutHistory() {
|
||||
val prompt = PHI_3.buildPrompt(SYSTEM_PROMPT, USER_PROMPT, listOf())
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<|user|>
|
||||
TEST_USER_PROMPT<|end|>
|
||||
<|assistant|>""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullAndEmptySource
|
||||
@ValueSource(strings = [" ", "\t", "\n"])
|
||||
fun shouldBuildPhi3PromptWithoutHistorySkippingBlankSystemPrompt(systemPrompt: String?) {
|
||||
val prompt = PHI_3.buildPrompt(systemPrompt, USER_PROMPT, listOf())
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<|user|>
|
||||
TEST_USER_PROMPT<|end|>
|
||||
<|assistant|>""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldBuildPhi3PromptWithHistory() {
|
||||
val prompt = PHI_3.buildPrompt(SYSTEM_PROMPT, USER_PROMPT, HISTORY)
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<|user|>
|
||||
TEST_PREV_PROMPT_1<|end|>
|
||||
<|assistant|>
|
||||
TEST_PREV_RESPONSE_1<|end|>
|
||||
<|user|>
|
||||
TEST_PREV_PROMPT_2<|end|>
|
||||
<|assistant|>
|
||||
TEST_PREV_RESPONSE_2<|end|>
|
||||
<|user|>
|
||||
TEST_USER_PROMPT<|end|>
|
||||
<|assistant|>""".trimIndent())
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullAndEmptySource
|
||||
@ValueSource(strings = [" ", "\t", "\n"])
|
||||
fun shouldBuildPhi3PromptWithHistorySkippingBlankSystemPrompt(systemPrompt: String?) {
|
||||
val prompt = PHI_3.buildPrompt(systemPrompt, USER_PROMPT, HISTORY)
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<|user|>
|
||||
TEST_PREV_PROMPT_1<|end|>
|
||||
<|assistant|>
|
||||
TEST_PREV_RESPONSE_1<|end|>
|
||||
<|user|>
|
||||
TEST_PREV_PROMPT_2<|end|>
|
||||
<|assistant|>
|
||||
TEST_PREV_RESPONSE_2<|end|>
|
||||
<|user|>
|
||||
TEST_USER_PROMPT<|end|>
|
||||
<|assistant|>""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldBuildCodeGemmaPromptWithoutHistory() {
|
||||
val prompt = CODE_GEMMA.buildPrompt(SYSTEM_PROMPT, USER_PROMPT, listOf())
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<start_of_turn>user
|
||||
TEST_USER_PROMPT<end_of_turn>
|
||||
<start_of_turn>model
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullAndEmptySource
|
||||
@ValueSource(strings = [" ", "\t", "\n"])
|
||||
fun shouldBuildCodeGemmaPromptWithoutHistorySkippingBlankSystemPrompt(systemPrompt: String?) {
|
||||
val prompt = CODE_GEMMA.buildPrompt(systemPrompt, USER_PROMPT, listOf())
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<start_of_turn>user
|
||||
TEST_USER_PROMPT<end_of_turn>
|
||||
<start_of_turn>model
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldBuildCodeGemmaPromptWithHistory() {
|
||||
val prompt = CODE_GEMMA.buildPrompt(SYSTEM_PROMPT, USER_PROMPT, HISTORY)
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<start_of_turn>user
|
||||
TEST_PREV_PROMPT_1<end_of_turn>
|
||||
<start_of_turn>model
|
||||
TEST_PREV_RESPONSE_1<end_of_turn>
|
||||
<start_of_turn>user
|
||||
TEST_PREV_PROMPT_2<end_of_turn>
|
||||
<start_of_turn>model
|
||||
TEST_PREV_RESPONSE_2<end_of_turn>
|
||||
<start_of_turn>user
|
||||
TEST_USER_PROMPT<end_of_turn>
|
||||
<start_of_turn>model
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullAndEmptySource
|
||||
@ValueSource(strings = [" ", "\t", "\n"])
|
||||
fun shouldBuildCodeGemmaPromptWithHistorySkippingBlankSystemPrompt(systemPrompt: String?) {
|
||||
val prompt = CODE_GEMMA.buildPrompt(systemPrompt, USER_PROMPT, HISTORY)
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<start_of_turn>user
|
||||
TEST_PREV_PROMPT_1<end_of_turn>
|
||||
<start_of_turn>model
|
||||
TEST_PREV_RESPONSE_1<end_of_turn>
|
||||
<start_of_turn>user
|
||||
TEST_PREV_PROMPT_2<end_of_turn>
|
||||
<start_of_turn>model
|
||||
TEST_PREV_RESPONSE_2<end_of_turn>
|
||||
<start_of_turn>user
|
||||
TEST_USER_PROMPT<end_of_turn>
|
||||
<start_of_turn>model
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldBuildCodeQwenPromptWithoutHistory() {
|
||||
val prompt = CODE_QWEN.buildPrompt(SYSTEM_PROMPT, USER_PROMPT, listOf())
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<|im_start|>system
|
||||
TEST_SYSTEM_PROMPT<|im_end|>
|
||||
<|im_start|>user
|
||||
TEST_USER_PROMPT<|im_end|>
|
||||
<|im_start|>assistant
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullAndEmptySource
|
||||
@ValueSource(strings = [" ", "\t", "\n"])
|
||||
fun shouldBuildCodeQwenPromptWithoutHistorySkippingBlankSystemPrompt(systemPrompt: String?) {
|
||||
val prompt = CODE_QWEN.buildPrompt(systemPrompt, USER_PROMPT, listOf())
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<|im_start|>user
|
||||
TEST_USER_PROMPT<|im_end|>
|
||||
<|im_start|>assistant
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldBuildCodeQwenPromptWithHistory() {
|
||||
val prompt = CODE_QWEN.buildPrompt(SYSTEM_PROMPT, USER_PROMPT, HISTORY)
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<|im_start|>system
|
||||
TEST_SYSTEM_PROMPT<|im_end|>
|
||||
<|im_start|>user
|
||||
TEST_PREV_PROMPT_1<|im_end|>
|
||||
<|im_start|>assistant
|
||||
TEST_PREV_RESPONSE_1<|im_end|>
|
||||
<|im_start|>user
|
||||
TEST_PREV_PROMPT_2<|im_end|>
|
||||
<|im_start|>assistant
|
||||
TEST_PREV_RESPONSE_2<|im_end|>
|
||||
<|im_start|>user
|
||||
TEST_USER_PROMPT<|im_end|>
|
||||
<|im_start|>assistant
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullAndEmptySource
|
||||
@ValueSource(strings = [" ", "\t", "\n"])
|
||||
fun shouldBuildCodeQwenPromptWithHistorySkippingBlankSystemPrompt(systemPrompt: String?) {
|
||||
val prompt = CODE_QWEN.buildPrompt(systemPrompt, USER_PROMPT, HISTORY)
|
||||
|
||||
assertThat(prompt).isEqualTo("""
|
||||
<|im_start|>user
|
||||
TEST_PREV_PROMPT_1<|im_end|>
|
||||
<|im_start|>assistant
|
||||
TEST_PREV_RESPONSE_1<|im_end|>
|
||||
<|im_start|>user
|
||||
TEST_PREV_PROMPT_2<|im_end|>
|
||||
<|im_start|>assistant
|
||||
TEST_PREV_RESPONSE_2<|im_end|>
|
||||
<|im_start|>user
|
||||
TEST_USER_PROMPT<|im_end|>
|
||||
<|im_start|>assistant
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldBuildAlpacaPromptWithHistory() {
|
||||
val prompt = ALPACA.buildPrompt(SYSTEM_PROMPT, USER_PROMPT, HISTORY)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,27 @@
|
|||
package testsupport.mixin
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_OPENAI_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.*
|
||||
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings
|
||||
import ee.carlrobert.codegpt.settings.service.ServiceType
|
||||
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings
|
||||
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings
|
||||
import ee.carlrobert.codegpt.settings.service.google.GoogleSettings
|
||||
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings
|
||||
import ee.carlrobert.llm.client.google.models.GoogleModel
|
||||
import java.util.function.BooleanSupplier
|
||||
|
||||
interface ShortcutsTestMixin {
|
||||
|
||||
fun useCodeGPTService() {
|
||||
GeneralSettings.getCurrentState().selectedService = ServiceType.CODEGPT
|
||||
setCredential(CODEGPT_API_KEY, "TEST_API_KEY")
|
||||
service<CodeGPTServiceSettings>().state.chatCompletionSettings.model = "TEST_MODEL"
|
||||
}
|
||||
|
||||
fun useOpenAIService() {
|
||||
useOpenAIService("gpt-4")
|
||||
}
|
||||
|
|
@ -41,6 +50,12 @@ interface ShortcutsTestMixin {
|
|||
LlamaSettings.getCurrentState().serverPort = null
|
||||
}
|
||||
|
||||
fun useGoogleService() {
|
||||
GeneralSettings.getCurrentState().selectedService = ServiceType.GOOGLE
|
||||
setCredential(GOOGLE_API_KEY, "TEST_API_KEY")
|
||||
service<GoogleSettings>().state.model = GoogleModel.GEMINI_PRO.code
|
||||
}
|
||||
|
||||
fun waitExpecting(condition: BooleanSupplier?) {
|
||||
PlatformTestUtil.waitWithEventsDispatching(
|
||||
"Waiting for message response timed out or did not meet expected conditions",
|
||||
|
|
@ -48,5 +63,4 @@ interface ShortcutsTestMixin {
|
|||
5
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue