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 10 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
1 change: 1 addition & 0 deletions CHANGELOG.md
ThiloteE marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- We fixed an issue where it was not possible to select selecting content of other user's comments.[#11106](https://github.com/JabRef/jabref/issues/11106)
- We fixed an issue where web search preferences "Custom API key" table modifications not discarded. [#11925](https://github.com/JabRef/jabref/issues/11925)
- We fixed an issue where trying to open a library from a failed mounted directory on Mac would cause an error. [#10548](https://github.com/JabRef/jabref/issues/10548)
- We fixed an issue where the response from the local ai model is cuttoff.[#11870](https://github.com/JabRef/jabref/issues/11870)
ThiloteE marked this conversation as resolved.
Show resolved Hide resolved

### Removed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ private void onSendMessage(String userPrompt) {
.onFailure(e -> {
LOGGER.error("Got an error while sending a message to AI", e);
setLoading(false);

ThiloteE marked this conversation as resolved.
Show resolved Hide resolved
// Typically, if user has entered an invalid API base URL, we get either "401 - null" or "404 - null" strings.
// Since there might be other strings returned from other API endpoints, we use startsWith() here.
if (e.getMessage().startsWith("404") || e.getMessage().startsWith("401")) {
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 chat4AllTextFlow;
ThiloteE marked this conversation as resolved.
Show resolved Hide resolved
@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(chat4AllTextFlow, AiProvider.CHAT4ALL);

String newEmbeddingModelText = embeddingModelText.getText().replaceAll("%0", aiPreferences.getEmbeddingModel().sizeInfo());
embeddingModelText.setText(newEmbeddingModelText);
Expand Down
8 changes: 7 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 @@ -90,7 +91,12 @@ public void initialize() {
});

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

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 chat4AllChatModel = new SimpleStringProperty();
InAnYan marked this conversation as resolved.
Show resolved Hide resolved

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 chat4AllApiKey = 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 chat4AllApiBaseUrl = 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 CHAT4ALL-> {
chat4AllChatModel.set(oldChatModel);
chat4AllApiKey.set(currentApiKey.get());
chat4AllApiBaseUrl.set(currentApiBaseUrl.get());
}
}
}

Expand All @@ -174,6 +182,11 @@ public AiTabViewModel(CliPreferences preferences) {
currentApiKey.set(huggingFaceApiKey.get());
currentApiBaseUrl.set(huggingFaceApiBaseUrl.get());
}
case CHAT4ALL -> {
currentChatModel.set(chat4AllChatModel.get());
currentApiKey.set(chat4AllApiKey.get());
currentApiBaseUrl.set(chat4AllApiBaseUrl.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 CHAT4ALL -> chat4AllChatModel.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 CHAT4ALL -> chat4AllApiKey.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 CHAT4ALL -> chat4AllApiBaseUrl.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));
chat4AllApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.CHAT4ALL));

openAiApiBaseUrl.setValue(aiPreferences.getOpenAiApiBaseUrl());
mistralAiApiBaseUrl.setValue(aiPreferences.getMistralAiApiBaseUrl());
geminiApiBaseUrl.setValue(aiPreferences.getGeminiApiBaseUrl());
huggingFaceApiBaseUrl.setValue(aiPreferences.getHuggingFaceApiBaseUrl());
chat4AllApiBaseUrl.setValue(aiPreferences.getChat4AllApiBaseUrl());

openAiChatModel.setValue(aiPreferences.getOpenAiChatModel());
mistralAiChatModel.setValue(aiPreferences.getMistralAiChatModel());
geminiChatModel.setValue(aiPreferences.getGeminiChatModel());
huggingFaceChatModel.setValue(aiPreferences.getHuggingFaceChatModel());
chat4AllChatModel.setValue(aiPreferences.getChat4AllChatModel());

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.setChat4AllChatModel(chat4AllChatModel.get() == null ? "" : chat4AllChatModel.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.CHAT4ALL, chat4AllApiKey.get() == null ? "" : chat4AllApiKey.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.setChat4AllApiBaseUrl(chat4AllApiBaseUrl.get() == null ? "" : chat4AllApiBaseUrl.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
4 changes: 3 additions & 1 deletion src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
public class AiDefaultPreferences {
public enum PredefinedChatModel {
GPT_4O_MINI(AiProvider.OPEN_AI, "gpt-4o-mini", 128000),
GPT_LOCAL(AiProvider.CHAT4ALL, "Phi-3.1-mini-128k-instruct-Q4_0-precise-output-tensor.gguf", 128000),
GPT_4O(AiProvider.OPEN_AI, "gpt-4o", 128000),
GPT_4(AiProvider.OPEN_AI, "gpt-4", 8192),
GPT_4_TURBO(AiProvider.OPEN_AI, "gpt-4-turbo", 128000),
Expand Down Expand Up @@ -62,7 +63,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.HUGGING_FACE,
AiProvider.CHAT4ALL, PredefinedChatModel.GPT_LOCAL
);

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 chat4AllChatModel;

private final BooleanProperty customizeExpertSettings;

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

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 chat4AllModel,
boolean customizeExpertSettings,
String openAiApiBaseUrl,
String mistralAiApiBaseUrl,
String geminiApiBaseUrl,
String huggingFaceApiBaseUrl,
String chat4AllApiBaseUrl,
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.chat4AllChatModel = new SimpleStringProperty(chat4AllModel);

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.chat4AllApiBaseUrl = new SimpleStringProperty(chat4AllApiBaseUrl);

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 chat4AllChatModelProperty() {
return chat4AllChatModel;
}

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

public void setChat4AllChatModel(String chat4AllChatModel) {
this.chat4AllChatModel.set(chat4AllChatModel);
}

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

public StringProperty chat4AllApiBaseUrlProperty() {
return chat4AllApiBaseUrl;
}

public String getChat4AllApiBaseUrl() {
return chat4AllApiBaseUrl.get();
}

public void setChat4AllApiBaseUrl(String chat4AllApiBaseUrl) {
this.chat4AllApiBaseUrl.set(chat4AllApiBaseUrl);
}

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 CHAT4ALL -> AiDefaultPreferences.getContextWindowSize(AiProvider.CHAT4ALL, chat4AllChatModel.get());
};
}
}
Expand Down Expand Up @@ -481,6 +512,8 @@ public String getSelectedChatModel() {
huggingFaceChatModel.get();
case GEMINI ->
geminiChatModel.get();
case CHAT4ALL ->
chat4AllChatModel.get();
};
}

Expand All @@ -495,6 +528,8 @@ public String getSelectedApiBaseUrl() {
huggingFaceApiBaseUrl.get();
case GEMINI ->
geminiApiBaseUrl.get();
case CHAT4ALL ->
chat4AllApiBaseUrl.get();
};
} else {
return aiProvider.get().getApiUrl();
Expand Down
7 changes: 0 additions & 7 deletions src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ public AiChatLogic(AiPreferences aiPreferences,
this.entries = entries;
this.name = name;
this.bibDatabaseContext = bibDatabaseContext;

ThiloteE marked this conversation as resolved.
Show resolved Hide resolved
this.entries.addListener((ListChangeListener<BibEntry>) change -> rebuildChain());

setupListeningToPreferencesChanges();
rebuildFull(chatHistory);
}
Expand Down Expand Up @@ -157,18 +155,13 @@ private String augmentSystemMessage(String systemMessage) {

public AiMessage execute(UserMessage message) {
// Message will be automatically added to ChatMemory through ConversationalRetrievalChain.

LOGGER.info("Sending message to AI provider ({}) for answering in {}: {}",
aiPreferences.getAiProvider().getApiUrl(),
name.get(),
message.singleText());

chatHistory.add(message);
AiMessage result = new AiMessage(chain.execute(message.singleText()));
chatHistory.add(result);

LOGGER.debug("Message was answered by the AI provider for {}: {}", name.get(), result.text());

return result;
}

Expand Down
Loading
Loading