#178 - Add support for running local LLMs via LLaMA C/C++ port (#249)

* Initial implementation of integrating llama.cpp to run LLaMA models locally

* Move submodule

* Copy llama submodule to bundle

* Support for downloading models from IDE

* Code cleanup

* Store port field

* Replace service selection radio group with dropdown

* Add quantization support + other fixes

* Add option to override host

* Fix override host handler

* Disable port field when override host enabled

* Design updates

* Fix llama settings configuration, design changes, clean up code

* Improve You.com coupon design

* Add new Phind model and help tooltip

* Fetch you.com subscription

* Add CodeBooga model, fix downloadable model selection

* Chat history support

* Code refactoring, minor bug fixes

* UI updates, several bug fixes, removed code llama python model

* Code cleanup, enable llama port only on macOS

* Change downloaded gguf models path

* Move some of the labels to codegpt bundle

* Minor fixes

* Remove ToRA model, add help texts

* Fix test

* Modify description
This commit is contained in:
Carl-Robert 2023-11-03 12:00:24 +02:00 committed by GitHub
parent ca2eb9b6fa
commit 45908e69df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
71 changed files with 2748 additions and 533 deletions

View file

@ -1,12 +1,22 @@
package ee.carlrobert.codegpt.settings;
import static java.util.stream.Collectors.toList;
import com.intellij.openapi.Disposable;
import com.intellij.ui.TitledSeparator;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.ComponentValidator;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.SystemInfoRt;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.settings.service.ServiceSelectionForm;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.settings.state.OpenAISettingsState;
import ee.carlrobert.codegpt.settings.state.SettingsState;
import java.awt.CardLayout;
import java.util.Arrays;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComponent;
import javax.swing.JPanel;
@ -14,25 +24,53 @@ public class SettingsComponent {
private final JPanel mainPanel;
private final JBTextField displayNameField;
private final ComboBox<ServiceType> serviceComboBox;
private final ServiceSelectionForm serviceSelectionForm;
private final YouServiceSelectionPanel youServiceSelectionPanel;
public SettingsComponent(Disposable parentDisposable, SettingsState settings) {
serviceSelectionForm = new ServiceSelectionForm(parentDisposable, settings);
displayNameField = new JBTextField(settings.getDisplayName(), 20);
youServiceSelectionPanel = new YouServiceSelectionPanel(parentDisposable);
serviceSelectionForm = new ServiceSelectionForm(parentDisposable);
var cardLayout = new CardLayout();
var cards = new JPanel(cardLayout);
cards.add(serviceSelectionForm.getOpenAIServiceSectionPanel(), ServiceType.OPENAI.getCode());
cards.add(serviceSelectionForm.getAzureServiceSectionPanel(), ServiceType.AZURE.getCode());
cards.add(serviceSelectionForm.getYouServiceSectionPanel(), ServiceType.YOU.getCode());
cards.add(serviceSelectionForm.getLlamaServiceSectionPanel(), ServiceType.LLAMA_CPP.getCode());
var serviceComboBoxModel = new DefaultComboBoxModel<ServiceType>();
serviceComboBoxModel.addAll(Arrays.stream(ServiceType.values())
.filter(it -> !"LLAMA_CPP".equals(it.getCode()) || SystemInfoRt.isUnix)
.collect(toList()));
serviceComboBox = new ComboBox<>(serviceComboBoxModel);
serviceComboBox.setSelectedItem(ServiceType.OPENAI);
serviceComboBox.setPreferredSize(displayNameField.getPreferredSize());
var serviceInputValidator = createInputValidator(parentDisposable, serviceComboBox);
serviceInputValidator.revalidate();
serviceComboBox.addItemListener(e -> {
serviceInputValidator.revalidate();
cardLayout.show(cards, ((ServiceType) e.getItem()).getCode());
});
mainPanel = FormBuilder.createFormBuilder()
.addComponent(UI.PanelFactory.panel(displayNameField)
.withLabel(CodeGPTBundle.get("settingsConfigurable.section.integration.displayNameFieldLabel"))
.resizeX(false)
.createPanel())
.addComponent(new TitledSeparator(CodeGPTBundle.get("settingsConfigurable.section.service.title")))
.addComponent(serviceSelectionForm.getForm())
.addVerticalGap(8)
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.displayName.label"),
displayNameField)
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.label"),
serviceComboBox)
.addComponent(cards)
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}
public ServiceType getSelectedService() {
return serviceComboBox.getItem();
}
public void setSelectedService(ServiceType serviceType) {
serviceComboBox.setSelectedItem(serviceType);
}
public JPanel getPanel() {
return mainPanel;
}
@ -41,18 +79,6 @@ public class SettingsComponent {
return displayNameField;
}
public String getEmail() {
return youServiceSelectionPanel.getEmail();
}
public void setEmail(String email) {
youServiceSelectionPanel.setEmail(email);
}
public String getPassword() {
return youServiceSelectionPanel.getPassword();
}
public ServiceSelectionForm getServiceSelectionForm() {
return serviceSelectionForm;
}
@ -64,4 +90,27 @@ public class SettingsComponent {
public void setDisplayName(String displayName) {
displayNameField.setText(displayName);
}
private ComponentValidator createInputValidator(
Disposable parentDisposable,
JComponent component) {
var validator = new ComponentValidator(parentDisposable)
.withValidator(() -> {
if (component instanceof ComboBox) {
var selectedItem = ((ComboBox<?>) component).getSelectedItem();
if (selectedItem == ServiceType.OPENAI &&
OpenAISettingsState.getInstance().isOpenAIQuotaExceeded()) {
return new ValidationInfo(
CodeGPTBundle.get("settings.openaiQuotaExceeded"),
component);
}
}
return null;
})
.andStartOnFocusLost()
.installOn(component);
validator.enableValidation();
return validator;
}
}