Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support GPT4All server api #11870 #12078

Merged
merged 27 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
34f1bc2
response cutoff bug fixed
NoahXu718 Oct 19, 2024
7cd1b2c
add Chat4All option when choose the aiProvider(Preference). complete …
NoahXu718 Oct 23, 2024
5c29ce0
Push the Chat4AllModel class
NoahXu718 Oct 23, 2024
e8d4f59
apikey disable if GPT4ALL is selected
qwsxmkoi Oct 24, 2024
c73f3c5
fix time out problem
NoahXu718 Oct 24, 2024
5da37ae
fix some warning in code
NoahXu718 Oct 24, 2024
969cde7
write the CHANGELOG.md
NoahXu718 Oct 24, 2024
3f55ce4
Merge branch 'main' into Support-GPT4All-Server-API-#11870
NoahXu718 Oct 24, 2024
5f11097
fix some check styles
NoahXu718 Oct 24, 2024
ebee427
Merge remote-tracking branch 'origin/Support-GPT4All-Server-API-#1187…
NoahXu718 Oct 24, 2024
cdd938f
convert some class to record
NoahXu718 Oct 24, 2024
ea08296
continue to fix the checkstyle
NoahXu718 Oct 24, 2024
e776a5e
using checkstyle.xml to detect the inappropriate code and fix it.
NoahXu718 Oct 25, 2024
6d9cc3e
remove some code that not useful, and fix some code style.
NoahXu718 Oct 25, 2024
063a763
Change all the Chat4All to Gpt4All and privacy policy for GPT4All.
NoahXu718 Oct 25, 2024
e149b4b
add the prompt text for Gpt4All, rewrite the CHANGELOG.md and restore…
NoahXu718 Oct 25, 2024
33d20b1
Change GPT_CHAT_MODEL_PROMPT to GPT_4_ALL_CHAT_MODEL_PROMPT.
NoahXu718 Oct 25, 2024
e2c91e8
fix the name problem and add some comments in Gpt4AllModel.java, usin…
NoahXu718 Oct 26, 2024
725e9fe
change Gpt4All to GPT4ALL
NoahXu718 Oct 26, 2024
09f1230
fix some bug when Api key is empty
NoahXu718 Oct 26, 2024
c576553
fix the checkstyle
NoahXu718 Oct 26, 2024
d23d9a0
use GPT4All as it's the official name in CHANGELOG.md
NoahXu718 Oct 26, 2024
6c9c7e0
Update src/main/java/org/jabref/gui/preferences/ai/AiTab.java
InAnYan Oct 26, 2024
616f1d2
use GPT4All in prompt text and separate BLANK into BLANK_HUGGING_FACE…
NoahXu718 Oct 26, 2024
e4eed8a
Merge remote-tracking branch 'origin/Support-GPT4All-Server-API-#1187…
NoahXu718 Oct 26, 2024
c46baca
Merge branch 'main' into Support-GPT4All-Server-API-#11870
koppor Oct 27, 2024
f5c93c7
Update CHANGELOG.md
ThiloteE Oct 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
ThiloteE marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- When a search hits a file, the file icon of that entry is changed accordingly. [#11542](https://github.com/JabRef/jabref/pull/11542)
- We added an AI-based chat for entries with linked PDF files. [#11430](https://github.com/JabRef/jabref/pull/11430)
- We added an AI-based summarization possibility for entries with linked PDF files. [#11430](https://github.com/JabRef/jabref/pull/11430)
- We added an AI section in JabRef's [preferences](https://docs.jabref.org/ai/preferences). [#11430](https://github.com/JabRef/jabref/pull/11430)
- We added AI providers: OpenAI, Mistral AI, Hugging Face and Google. [#11430](https://github.com/JabRef/jabref/pull/11430), [#11736](https://github.com/JabRef/jabref/pull/11736)
- We added AI providers: [Ollama](https://docs.jabref.org/ai/local-llm#step-by-step-guide-for-ollama) and GPT4All, which add the possibility to use local LLMs privately on your own device. [#11430](https://github.com/JabRef/jabref/pull/11430), [#11870](https://github.com/JabRef/jabref/issues/11870)
- We added support for selecting and using CSL Styles in JabRef's OpenOffice/LibreOffice integration for inserting bibliographic and in-text citations into a document. [#2146](https://github.com/JabRef/jabref/issues/2146), [#8893](https://github.com/JabRef/jabref/issues/8893)
- We added Tools > New library based on references in PDF file... to create a new library based on the references section in a PDF file. [#11522](https://github.com/JabRef/jabref/pull/11522)
- We added "Tools > New library based on references in PDF file" ... to create a new library based on the references section in a PDF file. [#11522](https://github.com/JabRef/jabref/pull/11522)
- When converting the references section of a paper (PDF file), more than the last page is treated. [#11522](https://github.com/JabRef/jabref/pull/11522)
- Added the functionality to invoke offline reference parsing explicitly. [#11565](https://github.com/JabRef/jabref/pull/11565)
- The dialog for [adding an entry using reference text](https://docs.jabref.org/collect/newentryfromplaintext) is now filled with the clipboard contents as default. [#11565](https://github.com/JabRef/jabref/pull/11565)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@
</Text>
</children>
</TextFlow>
<TextFlow fx:id="gpt4AllTextFlow">
<children>
<Text text="%If you have chosen %0 as an AI provider, the privacy policy of %0 applies. You find it at %1.">
<font>
<Font size="14.0" />
</font>
</Text>
</children>
</TextFlow>
<TextFlow>
<Text fx:id="embeddingModelText" text="%Additionally, we use Deep Java Library (DJL) embedding models for both chatting and summarization. The embedding model will be downloaded in background (size %0) from Deep Java Library servers anonymously.">
<font>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class PrivacyNoticeComponent extends ScrollPane {
@FXML private TextFlow mistralAiPrivacyTextFlow;
@FXML private TextFlow geminiPrivacyTextFlow;
@FXML private TextFlow huggingFacePrivacyTextFlow;
@FXML private TextFlow gpt4AllTextFlow;
@FXML private Text embeddingModelText;

private final AiPreferences aiPreferences;
Expand All @@ -49,6 +50,7 @@ private void initialize() {
initPrivacyHyperlink(mistralAiPrivacyTextFlow, AiProvider.MISTRAL_AI);
initPrivacyHyperlink(geminiPrivacyTextFlow, AiProvider.GEMINI);
initPrivacyHyperlink(huggingFacePrivacyTextFlow, AiProvider.HUGGING_FACE);
initPrivacyHyperlink(gpt4AllTextFlow, AiProvider.GPT4ALL);

String newEmbeddingModelText = embeddingModelText.getText().replaceAll("%0", aiPreferences.getEmbeddingModel().sizeInfo());
embeddingModelText.setText(newEmbeddingModelText);
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/org/jabref/gui/preferences/ai/AiTab.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jabref.gui.preferences.ai;

import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
Expand Down Expand Up @@ -28,6 +29,7 @@

public class AiTab extends AbstractPreferenceTabView<AiTabViewModel> implements PreferencesTab {
private static final String HUGGING_FACE_CHAT_MODEL_PROMPT = "TinyLlama/TinyLlama_v1.1 (or any other model name)";
private static final String GPT_4_ALL_CHAT_MODEL_PROMPT = "Phi-3.1-mini (or any other local model name from GPT4All)";

@FXML private CheckBox enableAi;
@FXML private CheckBox autoGenerateEmbeddings;
Expand Down Expand Up @@ -87,10 +89,19 @@ public void initialize() {
if (newValue == AiProvider.HUGGING_FACE) {
chatModelComboBox.setPromptText(HUGGING_FACE_CHAT_MODEL_PROMPT);
}
if (newValue == AiProvider.GPT4ALL) {
chatModelComboBox.setPromptText(GPT_4_ALL_CHAT_MODEL_PROMPT);
}
});

apiKeyTextField.textProperty().bindBidirectional(viewModel.apiKeyProperty());
apiKeyTextField.disableProperty().bind(viewModel.disableBasicSettingsProperty());
// Disable if GPT4ALL is selected
apiKeyTextField.disableProperty().bind(
Bindings.or(
InAnYan marked this conversation as resolved.
Show resolved Hide resolved
viewModel.disableBasicSettingsProperty(),
aiProviderComboBox.valueProperty().isEqualTo(AiProvider.GPT4ALL)
)
);

customizeExpertSettingsCheckbox.selectedProperty().bindBidirectional(viewModel.customizeExpertSettingsProperty());
customizeExpertSettingsCheckbox.disableProperty().bind(viewModel.disableBasicSettingsProperty());
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,15 @@ public class AiTabViewModel implements PreferenceTabViewModel {
private final StringProperty mistralAiChatModel = new SimpleStringProperty();
private final StringProperty geminiChatModel = new SimpleStringProperty();
private final StringProperty huggingFaceChatModel = new SimpleStringProperty();
private final StringProperty gpt4AllChatModel = new SimpleStringProperty();

private final StringProperty currentApiKey = new SimpleStringProperty();

private final StringProperty openAiApiKey = new SimpleStringProperty();
private final StringProperty mistralAiApiKey = new SimpleStringProperty();
private final StringProperty geminiAiApiKey = new SimpleStringProperty();
private final StringProperty huggingFaceApiKey = new SimpleStringProperty();
private final StringProperty gpt4AllApiKey = new SimpleStringProperty();

private final BooleanProperty customizeExpertSettings = new SimpleBooleanProperty();

Expand All @@ -75,6 +77,7 @@ public class AiTabViewModel implements PreferenceTabViewModel {
private final StringProperty mistralAiApiBaseUrl = new SimpleStringProperty();
private final StringProperty geminiApiBaseUrl = new SimpleStringProperty();
private final StringProperty huggingFaceApiBaseUrl = new SimpleStringProperty();
private final StringProperty gpt4AllApiBaseUrl = new SimpleStringProperty();

private final StringProperty instruction = new SimpleStringProperty();
private final StringProperty temperature = new SimpleStringProperty();
Expand Down Expand Up @@ -150,6 +153,11 @@ public AiTabViewModel(CliPreferences preferences) {
huggingFaceApiKey.set(currentApiKey.get());
huggingFaceApiBaseUrl.set(currentApiBaseUrl.get());
}
case GPT4ALL-> {
gpt4AllChatModel.set(oldChatModel);
gpt4AllApiKey.set(currentApiKey.get());
gpt4AllApiBaseUrl.set(currentApiBaseUrl.get());
}
}
}

Expand All @@ -174,6 +182,11 @@ public AiTabViewModel(CliPreferences preferences) {
currentApiKey.set(huggingFaceApiKey.get());
currentApiBaseUrl.set(huggingFaceApiBaseUrl.get());
}
case GPT4ALL -> {
currentChatModel.set(gpt4AllChatModel.get());
currentApiKey.set(gpt4AllApiKey.get());
currentApiBaseUrl.set(gpt4AllApiBaseUrl.get());
}
}
});

Expand All @@ -183,6 +196,7 @@ public AiTabViewModel(CliPreferences preferences) {
case MISTRAL_AI -> mistralAiChatModel.set(newValue);
case GEMINI -> geminiChatModel.set(newValue);
case HUGGING_FACE -> huggingFaceChatModel.set(newValue);
case GPT4ALL -> gpt4AllChatModel.set(newValue);
}

contextWindowSize.set(AiDefaultPreferences.getContextWindowSize(selectedAiProvider.get(), newValue));
Expand All @@ -194,6 +208,7 @@ public AiTabViewModel(CliPreferences preferences) {
case MISTRAL_AI -> mistralAiApiKey.set(newValue);
case GEMINI -> geminiAiApiKey.set(newValue);
case HUGGING_FACE -> huggingFaceApiKey.set(newValue);
case GPT4ALL -> gpt4AllApiKey.set(newValue);
}
});

Expand All @@ -203,6 +218,7 @@ public AiTabViewModel(CliPreferences preferences) {
case MISTRAL_AI -> mistralAiApiBaseUrl.set(newValue);
case GEMINI -> geminiApiBaseUrl.set(newValue);
case HUGGING_FACE -> huggingFaceApiBaseUrl.set(newValue);
case GPT4ALL -> gpt4AllApiBaseUrl.set(newValue);
}
});

Expand Down Expand Up @@ -279,16 +295,19 @@ public void setValues() {
mistralAiApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.MISTRAL_AI));
geminiAiApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.GEMINI));
huggingFaceApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.HUGGING_FACE));
gpt4AllApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.GPT4ALL));

openAiApiBaseUrl.setValue(aiPreferences.getOpenAiApiBaseUrl());
mistralAiApiBaseUrl.setValue(aiPreferences.getMistralAiApiBaseUrl());
geminiApiBaseUrl.setValue(aiPreferences.getGeminiApiBaseUrl());
huggingFaceApiBaseUrl.setValue(aiPreferences.getHuggingFaceApiBaseUrl());
gpt4AllApiBaseUrl.setValue(aiPreferences.getGpt4AllApiBaseUrl());

openAiChatModel.setValue(aiPreferences.getOpenAiChatModel());
mistralAiChatModel.setValue(aiPreferences.getMistralAiChatModel());
geminiChatModel.setValue(aiPreferences.getGeminiChatModel());
huggingFaceChatModel.setValue(aiPreferences.getHuggingFaceChatModel());
gpt4AllChatModel.setValue(aiPreferences.getGpt4AllChatModel());

enableAi.setValue(aiPreferences.getEnableAi());
autoGenerateSummaries.setValue(aiPreferences.getAutoGenerateSummaries());
Expand Down Expand Up @@ -320,11 +339,13 @@ public void storeSettings() {
aiPreferences.setMistralAiChatModel(mistralAiChatModel.get() == null ? "" : mistralAiChatModel.get());
aiPreferences.setGeminiChatModel(geminiChatModel.get() == null ? "" : geminiChatModel.get());
aiPreferences.setHuggingFaceChatModel(huggingFaceChatModel.get() == null ? "" : huggingFaceChatModel.get());
aiPreferences.setGpt4AllChatModel(gpt4AllChatModel.get() == null ? "" : gpt4AllChatModel.get());

aiPreferences.storeAiApiKeyInKeyring(AiProvider.OPEN_AI, openAiApiKey.get() == null ? "" : openAiApiKey.get());
aiPreferences.storeAiApiKeyInKeyring(AiProvider.MISTRAL_AI, mistralAiApiKey.get() == null ? "" : mistralAiApiKey.get());
aiPreferences.storeAiApiKeyInKeyring(AiProvider.GEMINI, geminiAiApiKey.get() == null ? "" : geminiAiApiKey.get());
aiPreferences.storeAiApiKeyInKeyring(AiProvider.HUGGING_FACE, huggingFaceApiKey.get() == null ? "" : huggingFaceApiKey.get());
aiPreferences.storeAiApiKeyInKeyring(AiProvider.GPT4ALL, gpt4AllApiKey.get() == null ? "" : gpt4AllApiKey.get());
// We notify in all cases without a real check if something was changed
aiPreferences.apiKeyUpdated();

Expand All @@ -336,6 +357,7 @@ public void storeSettings() {
aiPreferences.setMistralAiApiBaseUrl(mistralAiApiBaseUrl.get() == null ? "" : mistralAiApiBaseUrl.get());
aiPreferences.setGeminiApiBaseUrl(geminiApiBaseUrl.get() == null ? "" : geminiApiBaseUrl.get());
aiPreferences.setHuggingFaceApiBaseUrl(huggingFaceApiBaseUrl.get() == null ? "" : huggingFaceApiBaseUrl.get());
aiPreferences.setGpt4AllApiBaseUrl(gpt4AllApiBaseUrl.get() == null ? "" : gpt4AllApiBaseUrl.get());

aiPreferences.setInstruction(instruction.get());
// We already check the correctness of temperature and RAG minimum score in validators, so we don't need to check it here.
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ public enum PredefinedChatModel {
GEMINI_1_5_PRO(AiProvider.GEMINI, "gemini-1.5-pro", 2097152),
GEMINI_1_0_PRO(AiProvider.GEMINI, "gemini-1.0-pro", 32000),
// Dummy variant for Hugging Face models.
HUGGING_FACE(AiProvider.HUGGING_FACE, "", 0);
// Blank entry used for cases where the model name is not specified.
BLANK_HUGGING_FACE(AiProvider.HUGGING_FACE, "", 0),
BLANK_GPT4ALL(AiProvider.GPT4ALL, "", 0);

private final AiProvider aiProvider;
private final String name;
Expand Down Expand Up @@ -62,7 +64,8 @@ public String toString() {
AiProvider.OPEN_AI, PredefinedChatModel.GPT_4O_MINI,
AiProvider.MISTRAL_AI, PredefinedChatModel.OPEN_MIXTRAL_8X22B,
AiProvider.GEMINI, PredefinedChatModel.GEMINI_1_5_FLASH,
AiProvider.HUGGING_FACE, PredefinedChatModel.HUGGING_FACE
AiProvider.HUGGING_FACE, PredefinedChatModel.BLANK_HUGGING_FACE,
AiProvider.GPT4ALL, PredefinedChatModel.BLANK_GPT4ALL
);

public static final boolean CUSTOMIZE_SETTINGS = false;
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/org/jabref/logic/ai/AiPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ public class AiPreferences {
private final StringProperty mistralAiChatModel;
private final StringProperty geminiChatModel;
private final StringProperty huggingFaceChatModel;
private final StringProperty gpt4AllChatModel;

private final BooleanProperty customizeExpertSettings;

private final StringProperty openAiApiBaseUrl;
private final StringProperty mistralAiApiBaseUrl;
private final StringProperty geminiApiBaseUrl;
private final StringProperty huggingFaceApiBaseUrl;
private final StringProperty gpt4AllApiBaseUrl;

private final ObjectProperty<EmbeddingModel> embeddingModel;
private final StringProperty instruction;
Expand All @@ -67,11 +69,13 @@ public AiPreferences(boolean enableAi,
String mistralAiChatModel,
String geminiChatModel,
String huggingFaceChatModel,
String gpt4AllModel,
boolean customizeExpertSettings,
String openAiApiBaseUrl,
String mistralAiApiBaseUrl,
String geminiApiBaseUrl,
String huggingFaceApiBaseUrl,
String gpt4AllApiBaseUrl,
EmbeddingModel embeddingModel,
String instruction,
double temperature,
Expand All @@ -91,13 +95,15 @@ public AiPreferences(boolean enableAi,
this.mistralAiChatModel = new SimpleStringProperty(mistralAiChatModel);
this.geminiChatModel = new SimpleStringProperty(geminiChatModel);
this.huggingFaceChatModel = new SimpleStringProperty(huggingFaceChatModel);
this.gpt4AllChatModel = new SimpleStringProperty(gpt4AllModel);

this.customizeExpertSettings = new SimpleBooleanProperty(customizeExpertSettings);

this.openAiApiBaseUrl = new SimpleStringProperty(openAiApiBaseUrl);
this.mistralAiApiBaseUrl = new SimpleStringProperty(mistralAiApiBaseUrl);
this.geminiApiBaseUrl = new SimpleStringProperty(geminiApiBaseUrl);
this.huggingFaceApiBaseUrl = new SimpleStringProperty(huggingFaceApiBaseUrl);
this.gpt4AllApiBaseUrl = new SimpleStringProperty(gpt4AllApiBaseUrl);

this.embeddingModel = new SimpleObjectProperty<>(embeddingModel);
this.instruction = new SimpleStringProperty(instruction);
Expand Down Expand Up @@ -233,6 +239,18 @@ public void setHuggingFaceChatModel(String huggingFaceChatModel) {
this.huggingFaceChatModel.set(huggingFaceChatModel);
}

public StringProperty gpt4AllChatModelProperty() {
return gpt4AllChatModel;
}

public String getGpt4AllChatModel() {
return huggingFaceChatModel.get();
}

public void setGpt4AllChatModel(String gpt4AllChatModel) {
this.gpt4AllChatModel.set(gpt4AllChatModel);
}

public BooleanProperty customizeExpertSettingsProperty() {
return customizeExpertSettings;
}
Expand Down Expand Up @@ -309,6 +327,18 @@ public void setHuggingFaceApiBaseUrl(String huggingFaceApiBaseUrl) {
this.huggingFaceApiBaseUrl.set(huggingFaceApiBaseUrl);
}

public StringProperty gpt4AllApiBaseUrlProperty() {
return gpt4AllApiBaseUrl;
}

public String getGpt4AllApiBaseUrl() {
return gpt4AllApiBaseUrl.get();
}

public void setGpt4AllApiBaseUrl(String gpt4AllApiBaseUrl) {
this.gpt4AllApiBaseUrl.set(gpt4AllApiBaseUrl);
}

public StringProperty instructionProperty() {
return instruction;
}
Expand Down Expand Up @@ -354,6 +384,7 @@ public int getContextWindowSize() {
case MISTRAL_AI -> AiDefaultPreferences.getContextWindowSize(AiProvider.MISTRAL_AI, mistralAiChatModel.get());
case HUGGING_FACE -> AiDefaultPreferences.getContextWindowSize(AiProvider.HUGGING_FACE, huggingFaceChatModel.get());
case GEMINI -> AiDefaultPreferences.getContextWindowSize(AiProvider.GEMINI, geminiChatModel.get());
case GPT4ALL -> AiDefaultPreferences.getContextWindowSize(AiProvider.GPT4ALL, gpt4AllChatModel.get());
};
}
}
Expand Down Expand Up @@ -481,6 +512,8 @@ public String getSelectedChatModel() {
huggingFaceChatModel.get();
case GEMINI ->
geminiChatModel.get();
case GPT4ALL ->
gpt4AllChatModel.get();
};
}

Expand All @@ -495,6 +528,8 @@ public String getSelectedApiBaseUrl() {
huggingFaceApiBaseUrl.get();
case GEMINI ->
geminiApiBaseUrl.get();
case GPT4ALL ->
gpt4AllApiBaseUrl.get();
};
} else {
return aiProvider.get().getApiUrl();
Expand Down
Loading
Loading