From 34f1bc2e4cd1434d7789cd1770bafc898938321d Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sun, 20 Oct 2024 00:08:02 +1100 Subject: [PATCH 01/23] response cutoff bug fixed --- .../gui/ai/components/aichat/AiChatComponent.java | 1 - .../java/org/jabref/logic/ai/AiDefaultPreferences.java | 2 ++ .../java/org/jabref/logic/ai/chatting/AiChatLogic.java | 9 ++++++++- .../ai/chatting/model/JabRefChatLanguageModel.java | 10 ++++++++++ .../ai/chatting/model/JvmOpenAiChatLanguageModel.java | 3 +-- src/main/java/org/jabref/model/ai/AiProvider.java | 3 ++- 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java b/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java index 25e52d294e4..235a92b0b32 100644 --- a/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java +++ b/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java @@ -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); - // 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")) { diff --git a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java index e83c1a084b5..86c2d5ba55c 100644 --- a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java @@ -10,6 +10,8 @@ public class AiDefaultPreferences { public enum PredefinedChatModel { GPT_4O_MINI(AiProvider.OPEN_AI, "gpt-4o-mini", 128000), + GPT_LOCAL(AiProvider.OPEN_AI, "Phi-3.1-mini-128k-instruct-Q4_0-precise-output-tensor.gguf", 128000), +// GPT_4O_MINI(AiProvider.OPEN_AI, "gpt-4o-mini", 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), diff --git a/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java b/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java index f079b093604..be682168e8b 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java +++ b/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java @@ -162,9 +162,16 @@ public AiMessage execute(UserMessage message) { aiPreferences.getAiProvider().getApiUrl(), name.get(), message.singleText()); - + System.out.println("The API URL being used is: " + aiPreferences.getAiProvider().getApiUrl()); + System.out.println("API Base URL: " + aiPreferences.getSelectedApiBaseUrl()); + System.out.println("Using model ID: " + aiPreferences.getSelectedChatModel()); chatHistory.add(message); + + LOGGER.info("Sending request to URL: " + aiPreferences.getSelectedApiBaseUrl()); + LOGGER.info("Using model ID: " + aiPreferences.getSelectedChatModel()); + LOGGER.info("Request message: " + message.singleText()); AiMessage result = new AiMessage(chain.execute(message.singleText())); + LOGGER.info("Received response: " + result.text()); chatHistory.add(result); LOGGER.debug("Message was answered by the AI provider for {}: {}", name.get(), result.text()); diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 92fc11df484..be06565cb87 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -10,6 +10,7 @@ import org.jabref.logic.ai.AiPreferences; import org.jabref.logic.ai.chatting.AiChatLogic; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.ai.chatting.model.Chat4AllModel; import com.google.common.util.concurrent.ThreadFactoryBuilder; import dev.langchain4j.data.message.AiMessage; @@ -62,6 +63,15 @@ private void rebuild() { switch (aiPreferences.getAiProvider()) { case OPEN_AI -> { langchainChatModel = Optional.of(new JvmOpenAiChatLanguageModel(aiPreferences, httpClient)); +// langchainChatModel = Optional.of(Chat4AllModel +// .builder() +// .modelName(aiPreferences.getSelectedChatModel()) +// .baseUrl(aiPreferences.getSelectedApiBaseUrl()) +// .httpClient(httpClient) +// .temperature(aiPreferences.getTemperature()) +// .build() +// ); + } case MISTRAL_AI -> { diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java index 023a503d2aa..d9e4ee02399 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java @@ -31,13 +31,11 @@ public class JvmOpenAiChatLanguageModel implements ChatLanguageModel { public JvmOpenAiChatLanguageModel(AiPreferences aiPreferences, HttpClient httpClient) { this.aiPreferences = aiPreferences; - OpenAI openAI = OpenAI .newBuilder(aiPreferences.getApiKeyForAiProvider(aiPreferences.getAiProvider())) .httpClient(httpClient) .baseUrl(aiPreferences.getSelectedApiBaseUrl()) .build(); - this.chatClient = openAI.chatClient(); } @@ -59,6 +57,7 @@ public Response generate(List list) { .model(aiPreferences.getSelectedChatModel()) .temperature(aiPreferences.getTemperature()) .n(1) + .maxTokens(2048) .messages(messages) .build(); diff --git a/src/main/java/org/jabref/model/ai/AiProvider.java b/src/main/java/org/jabref/model/ai/AiProvider.java index 00382e98d36..9593523c246 100644 --- a/src/main/java/org/jabref/model/ai/AiProvider.java +++ b/src/main/java/org/jabref/model/ai/AiProvider.java @@ -3,7 +3,8 @@ import java.io.Serializable; public enum AiProvider implements Serializable { - OPEN_AI("OpenAI", "https://openai.com/policies/privacy-policy/", "https://openai.com/policies/privacy-policy/"), + OPEN_AI("OpenAI", "https://api.openai.com/v1", "https://openai.com/policies/privacy-policy/"), +// OPEN_AI("OpenAI", "http://localhost:4891/v1/models", "https://openai.com/policies/privacy-policy/"), MISTRAL_AI("Mistral AI", "https://mistral.ai/terms/#privacy-policy", "https://mistral.ai/terms/#privacy-policy"), GEMINI("Gemini", "https://huggingface.co/privacy", "https://ai.google.dev/gemini-api/terms"), HUGGING_FACE("Hugging Face", "https://huggingface.co/api", "https://huggingface.co/privacy"); From 7cd1b2c41a15efeab5c05780a467c65a40e57d62 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Thu, 24 Oct 2024 02:34:26 +1100 Subject: [PATCH 02/23] add Chat4All option when choose the aiProvider(Preference). complete Chat4AllModel class to send request to the local model and parse the response successfully! --- .../privacynotice/PrivacyNoticeComponent.java | 2 ++ .../gui/preferences/ai/AiTabViewModel.java | 22 ++++++++++++ .../jabref/logic/ai/AiDefaultPreferences.java | 6 ++-- .../org/jabref/logic/ai/AiPreferences.java | 34 +++++++++++++++++++ .../jabref/logic/ai/chatting/AiChatLogic.java | 1 - .../model/JabRefChatLanguageModel.java | 14 +++----- .../preferences/JabRefCliPreferences.java | 8 +++++ .../java/org/jabref/model/ai/AiProvider.java | 4 +-- 8 files changed, 76 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java index 12dad69d580..1b6257e3a02 100644 --- a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java +++ b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java @@ -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; @FXML private Text embeddingModelText; private final AiPreferences aiPreferences; @@ -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); diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java b/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java index c1c4ef5f6a5..ef624bf1baa 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java @@ -54,6 +54,7 @@ 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(); private final StringProperty currentApiKey = new SimpleStringProperty(); @@ -61,6 +62,7 @@ public class AiTabViewModel implements PreferenceTabViewModel { 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(); @@ -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(); @@ -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()); + } } } @@ -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()); + } } }); @@ -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)); @@ -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); } }); @@ -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); } }); @@ -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()); @@ -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(); @@ -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. diff --git a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java index 86c2d5ba55c..75325d21b5e 100644 --- a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java @@ -10,8 +10,7 @@ public class AiDefaultPreferences { public enum PredefinedChatModel { GPT_4O_MINI(AiProvider.OPEN_AI, "gpt-4o-mini", 128000), - GPT_LOCAL(AiProvider.OPEN_AI, "Phi-3.1-mini-128k-instruct-Q4_0-precise-output-tensor.gguf", 128000), -// 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), @@ -64,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; diff --git a/src/main/java/org/jabref/logic/ai/AiPreferences.java b/src/main/java/org/jabref/logic/ai/AiPreferences.java index 3a07a02e70c..0c4fd86af3d 100644 --- a/src/main/java/org/jabref/logic/ai/AiPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiPreferences.java @@ -40,6 +40,7 @@ public class AiPreferences { private final StringProperty mistralAiChatModel; private final StringProperty geminiChatModel; private final StringProperty huggingFaceChatModel; + private final StringProperty chat4AllChatModel; private final BooleanProperty customizeExpertSettings; @@ -47,6 +48,7 @@ public class AiPreferences { private final StringProperty mistralAiApiBaseUrl; private final StringProperty geminiApiBaseUrl; private final StringProperty huggingFaceApiBaseUrl; + private final StringProperty chat4AllApiBaseUrl; private final ObjectProperty embeddingModel; private final StringProperty instruction; @@ -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, @@ -91,6 +95,7 @@ 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); @@ -98,6 +103,7 @@ public AiPreferences(boolean enableAi, 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); @@ -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; } @@ -308,6 +326,17 @@ public String getHuggingFaceApiBaseUrl() { 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; @@ -354,6 +383,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()); }; } } @@ -481,6 +511,8 @@ public String getSelectedChatModel() { huggingFaceChatModel.get(); case GEMINI -> geminiChatModel.get(); + case CHAT4ALL -> + chat4AllChatModel.get(); }; } @@ -495,6 +527,8 @@ public String getSelectedApiBaseUrl() { huggingFaceApiBaseUrl.get(); case GEMINI -> geminiApiBaseUrl.get(); + case CHAT4ALL -> + chat4AllApiBaseUrl.get(); }; } else { return aiProvider.get().getApiUrl(); diff --git a/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java b/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java index be682168e8b..4ea1db2019b 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java +++ b/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java @@ -157,7 +157,6 @@ 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(), diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index be06565cb87..546b6783f7b 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -63,15 +63,11 @@ private void rebuild() { switch (aiPreferences.getAiProvider()) { case OPEN_AI -> { langchainChatModel = Optional.of(new JvmOpenAiChatLanguageModel(aiPreferences, httpClient)); -// langchainChatModel = Optional.of(Chat4AllModel -// .builder() -// .modelName(aiPreferences.getSelectedChatModel()) -// .baseUrl(aiPreferences.getSelectedApiBaseUrl()) -// .httpClient(httpClient) -// .temperature(aiPreferences.getTemperature()) -// .build() -// ); - + } + case CHAT4ALL-> { +// langchainChatModel = Optional.of(new JvmOpenAiChatLanguageModel(aiPreferences, httpClient)); +// System.out.println("a"); + langchainChatModel = Optional.of(new Chat4AllModel(aiPreferences, httpClient)); } case MISTRAL_AI -> { diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index a15d1014c87..ae0092671bf 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -349,12 +349,14 @@ public class JabRefCliPreferences implements CliPreferences { private static final String AI_MISTRAL_AI_CHAT_MODEL = "aiMistralAiChatModel"; private static final String AI_GEMINI_CHAT_MODEL = "aiGeminiChatModel"; private static final String AI_HUGGING_FACE_CHAT_MODEL = "aiHuggingFaceChatModel"; + private static final String AI_CHAT_4_ALL_MODEL = "aiChat4AllChatModel"; private static final String AI_CUSTOMIZE_SETTINGS = "aiCustomizeSettings"; private static final String AI_EMBEDDING_MODEL = "aiEmbeddingModel"; private static final String AI_OPEN_AI_API_BASE_URL = "aiOpenAiApiBaseUrl"; private static final String AI_MISTRAL_AI_API_BASE_URL = "aiMistralAiApiBaseUrl"; private static final String AI_GEMINI_API_BASE_URL = "aiGeminiApiBaseUrl"; private static final String AI_HUGGING_FACE_API_BASE_URL = "aiHuggingFaceApiBaseUrl"; + private static final String AI_CHAT_4_ALL_API_BASE_URL = "aiChat4AllApiBaseUrl"; private static final String AI_SYSTEM_MESSAGE = "aiSystemMessage"; private static final String AI_TEMPERATURE = "aiTemperature"; private static final String AI_CONTEXT_WINDOW_SIZE = "aiMessageWindowSize"; @@ -632,12 +634,14 @@ protected JabRefCliPreferences() { defaults.put(AI_MISTRAL_AI_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.MISTRAL_AI).getName()); defaults.put(AI_GEMINI_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.GEMINI).getName()); defaults.put(AI_HUGGING_FACE_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.HUGGING_FACE).getName()); + defaults.put(AI_CHAT_4_ALL_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.CHAT4ALL).getName()); defaults.put(AI_CUSTOMIZE_SETTINGS, AiDefaultPreferences.CUSTOMIZE_SETTINGS); defaults.put(AI_EMBEDDING_MODEL, AiDefaultPreferences.EMBEDDING_MODEL.name()); defaults.put(AI_OPEN_AI_API_BASE_URL, AiProvider.OPEN_AI.getApiUrl()); defaults.put(AI_MISTRAL_AI_API_BASE_URL, AiProvider.MISTRAL_AI.getApiUrl()); defaults.put(AI_GEMINI_API_BASE_URL, AiProvider.GEMINI.getApiUrl()); defaults.put(AI_HUGGING_FACE_API_BASE_URL, AiProvider.HUGGING_FACE.getApiUrl()); + defaults.put(AI_CHAT_4_ALL_API_BASE_URL, AiProvider.CHAT4ALL.getApiUrl()); defaults.put(AI_SYSTEM_MESSAGE, AiDefaultPreferences.SYSTEM_MESSAGE); defaults.put(AI_TEMPERATURE, AiDefaultPreferences.TEMPERATURE); defaults.put(AI_CONTEXT_WINDOW_SIZE, AiDefaultPreferences.getContextWindowSize(AiDefaultPreferences.PROVIDER, AiDefaultPreferences.CHAT_MODELS.get(AiDefaultPreferences.PROVIDER).getName())); @@ -1825,11 +1829,13 @@ public AiPreferences getAiPreferences() { get(AI_MISTRAL_AI_CHAT_MODEL), get(AI_GEMINI_CHAT_MODEL), get(AI_HUGGING_FACE_CHAT_MODEL), + get(AI_CHAT_4_ALL_MODEL), getBoolean(AI_CUSTOMIZE_SETTINGS), get(AI_OPEN_AI_API_BASE_URL), get(AI_MISTRAL_AI_API_BASE_URL), get(AI_GEMINI_API_BASE_URL), get(AI_HUGGING_FACE_API_BASE_URL), + get(AI_CHAT_4_ALL_API_BASE_URL), EmbeddingModel.valueOf(get(AI_EMBEDDING_MODEL)), get(AI_SYSTEM_MESSAGE), getDouble(AI_TEMPERATURE), @@ -1849,6 +1855,7 @@ public AiPreferences getAiPreferences() { EasyBind.listen(aiPreferences.mistralAiChatModelProperty(), (obs, oldValue, newValue) -> put(AI_MISTRAL_AI_CHAT_MODEL, newValue)); EasyBind.listen(aiPreferences.geminiChatModelProperty(), (obs, oldValue, newValue) -> put(AI_GEMINI_CHAT_MODEL, newValue)); EasyBind.listen(aiPreferences.huggingFaceChatModelProperty(), (obs, oldValue, newValue) -> put(AI_HUGGING_FACE_CHAT_MODEL, newValue)); + EasyBind.listen(aiPreferences.chat4AllChatModelProperty(), (obs, oldValue, newValue) -> put(AI_CHAT_4_ALL_MODEL, newValue)); EasyBind.listen(aiPreferences.customizeExpertSettingsProperty(), (obs, oldValue, newValue) -> putBoolean(AI_CUSTOMIZE_SETTINGS, newValue)); @@ -1856,6 +1863,7 @@ public AiPreferences getAiPreferences() { EasyBind.listen(aiPreferences.mistralAiApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_MISTRAL_AI_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.geminiApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_GEMINI_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.huggingFaceApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_HUGGING_FACE_API_BASE_URL, newValue)); + EasyBind.listen(aiPreferences.chat4AllApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_CHAT_4_ALL_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.embeddingModelProperty(), (obs, oldValue, newValue) -> put(AI_EMBEDDING_MODEL, newValue.name())); EasyBind.listen(aiPreferences.instructionProperty(), (obs, oldValue, newValue) -> put(AI_SYSTEM_MESSAGE, newValue)); diff --git a/src/main/java/org/jabref/model/ai/AiProvider.java b/src/main/java/org/jabref/model/ai/AiProvider.java index 9593523c246..e95ee4866a2 100644 --- a/src/main/java/org/jabref/model/ai/AiProvider.java +++ b/src/main/java/org/jabref/model/ai/AiProvider.java @@ -4,10 +4,10 @@ public enum AiProvider implements Serializable { OPEN_AI("OpenAI", "https://api.openai.com/v1", "https://openai.com/policies/privacy-policy/"), -// OPEN_AI("OpenAI", "http://localhost:4891/v1/models", "https://openai.com/policies/privacy-policy/"), MISTRAL_AI("Mistral AI", "https://mistral.ai/terms/#privacy-policy", "https://mistral.ai/terms/#privacy-policy"), GEMINI("Gemini", "https://huggingface.co/privacy", "https://ai.google.dev/gemini-api/terms"), - HUGGING_FACE("Hugging Face", "https://huggingface.co/api", "https://huggingface.co/privacy"); + HUGGING_FACE("Hugging Face", "https://huggingface.co/api", "https://huggingface.co/privacy"), + CHAT4ALL("Chat4All", "http://localhost:4891/v1", "https://openai.com/policies/privacy-policy/"); private final String label; private final String apiUrl; From 5c29ce0f08b4be76d5d7e3b580602fb35fd9330b Mon Sep 17 00:00:00 2001 From: Jiahao Date: Thu, 24 Oct 2024 02:40:20 +1100 Subject: [PATCH 03/23] Push the Chat4AllModel class --- .../ai/chatting/model/Chat4AllModel.java | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java new file mode 100644 index 00000000000..04feb98d653 --- /dev/null +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java @@ -0,0 +1,202 @@ +package org.jabref.logic.ai.chatting.model; + +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.URI; +import java.time.Duration; +import java.util.List; +import java.util.stream.Collectors; + +import org.jabref.logic.ai.AiPreferences; +import dev.langchain4j.data.message.AiMessage; +import dev.langchain4j.data.message.ChatMessage; +import dev.langchain4j.data.message.SystemMessage; +import dev.langchain4j.data.message.ToolExecutionResultMessage; +import dev.langchain4j.data.message.UserMessage; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.output.FinishReason; +import dev.langchain4j.model.output.Response; +import dev.langchain4j.model.output.TokenUsage; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Chat4AllModel implements ChatLanguageModel { + + private static final Logger LOGGER = LoggerFactory.getLogger(Chat4AllModel.class); + + private final AiPreferences aiPreferences; + private final HttpClient httpClient; + private final Gson gson = new Gson(); + + public Chat4AllModel(AiPreferences aiPreferences, HttpClient httpClient) { + this.aiPreferences = aiPreferences; + this.httpClient = httpClient; + } + + @Override + public Response generate(List list) { + LOGGER.debug("Generating response from Chat4All model with {} messages: {}", list.size(), list); + + List messages = list.stream() + .map(chatMessage -> switch (chatMessage) { + case AiMessage aiMessage -> new Message("assistant", aiMessage.text()); + case SystemMessage systemMessage -> new Message("system", systemMessage.text()); + case ToolExecutionResultMessage toolExecutionResultMessage -> new Message("tool", toolExecutionResultMessage.text()); + case UserMessage userMessage -> new Message("user", userMessage.singleText()); + default -> throw new IllegalStateException("Unknown ChatMessage type: " + chatMessage); + }).collect(Collectors.toList()); + + TextGenerationRequest request = TextGenerationRequest + .builder() + .model(aiPreferences.getSelectedChatModel()) + .messages(messages) + .temperature(aiPreferences.getTemperature()) + .max_tokens(2048) + .build(); + + try { + String requestBody = gson.toJson(request); + String baseUrl = aiPreferences.getSelectedApiBaseUrl(); + String fullUrl = baseUrl.endsWith("/") ? baseUrl + "chat/completions" : baseUrl + "/chat/completions"; + HttpRequest httpRequest = HttpRequest.newBuilder() + .uri(URI.create(fullUrl)) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(requestBody)) + .timeout(Duration.ofSeconds(30)) + .build(); + + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + LOGGER.info("Chat4All response: {}", response.body()); + + TextGenerationResponse textGenerationResponse = gson.fromJson(response.body(), TextGenerationResponse.class); + if (textGenerationResponse.getChoices() == null || textGenerationResponse.getChoices().isEmpty()) { + throw new IllegalArgumentException("No choices returned in the response"); + } + + String generatedText = textGenerationResponse.getChoices().get(0).getMessage().getContent(); + if (generatedText == null || generatedText.isEmpty()) { + throw new IllegalArgumentException("Generated text is null or empty"); + } + + return new Response<>(new AiMessage(generatedText), new TokenUsage(0, 0), FinishReason.OTHER); + + } catch (Exception e) { + LOGGER.error("Error generating message from Chat4All", e); + throw new RuntimeException("Failed to generate AI message", e); + } + } + + private static class TextGenerationRequest { + private final String model; + private final List messages; + private final Double temperature; + private final Integer max_tokens; + + private TextGenerationRequest(Builder builder) { + this.model = builder.model; + this.messages = builder.messages; + this.temperature = builder.temperature; + this.max_tokens = builder.max_tokens; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String model; + private List messages; + private Double temperature; + private Integer max_tokens; + + public Builder model(String model) { + this.model = model; + return this; + } + + public Builder messages(List messages) { + this.messages = messages; + return this; + } + + public Builder temperature(Double temperature) { + this.temperature = temperature; + return this; + } + + public Builder max_tokens(Integer max_tokens) { + this.max_tokens = max_tokens; + return this; + } + + public TextGenerationRequest build() { + return new TextGenerationRequest(this); + } + } + } + + private static class TextGenerationResponse { + private List choices; + + public List getChoices() { + return choices; + } + + public void setChoices(List choices) { + this.choices = choices; + } + + public static class Choice { + private Message message; + + public Message getMessage() { + return message; + } + + public void setMessage(Message message) { + this.message = message; + } + } + + public static class Message { + private String role; + private String content; + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + } + } + + private static class Message { + private final String role; + private final String content; + + public Message(String role, String content) { + this.role = role; + this.content = content; + } + + public String getRole() { + return role; + } + + public String getContent() { + return content; + } + } +} From e8d4f5951dd734b6320c0737c76ee17d18e977be Mon Sep 17 00:00:00 2001 From: qwsxmkoi Date: Fri, 25 Oct 2024 00:00:31 +1100 Subject: [PATCH 04/23] apikey disable if GPT4ALL is selected --- src/main/java/org/jabref/gui/preferences/ai/AiTab.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index efa406a1d27..1da3d16549e 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -90,6 +90,14 @@ public void initialize() { }); apiKeyTextField.textProperty().bindBidirectional(viewModel.apiKeyProperty()); + + apiKeyTextField.disableProperty().bind( + Bindings.or( + viewModel.disableBasicSettingsProperty(), + aiProviderComboBox.valueProperty().isEqualTo(AiProvider.CHAT4ALL) // Disable if GPT4ALL is selected + ) + ); + apiKeyTextField.disableProperty().bind(viewModel.disableBasicSettingsProperty()); customizeExpertSettingsCheckbox.selectedProperty().bindBidirectional(viewModel.customizeExpertSettingsProperty()); From c73f3c5f0e403150293921235af115b8d34c7aa8 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Fri, 25 Oct 2024 00:46:13 +1100 Subject: [PATCH 05/23] fix time out problem --- src/main/java/org/jabref/gui/preferences/ai/AiTab.java | 4 +--- .../org/jabref/logic/ai/chatting/model/Chat4AllModel.java | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index 1da3d16549e..1b0a321946d 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -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; @@ -90,15 +91,12 @@ public void initialize() { }); apiKeyTextField.textProperty().bindBidirectional(viewModel.apiKeyProperty()); - apiKeyTextField.disableProperty().bind( Bindings.or( viewModel.disableBasicSettingsProperty(), aiProviderComboBox.valueProperty().isEqualTo(AiProvider.CHAT4ALL) // Disable if GPT4ALL is selected ) ); - - apiKeyTextField.disableProperty().bind(viewModel.disableBasicSettingsProperty()); customizeExpertSettingsCheckbox.selectedProperty().bindBidirectional(viewModel.customizeExpertSettingsProperty()); customizeExpertSettingsCheckbox.disableProperty().bind(viewModel.disableBasicSettingsProperty()); diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java index 04feb98d653..ce336a3e171 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java @@ -64,7 +64,7 @@ public Response generate(List list) { .uri(URI.create(fullUrl)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(requestBody)) - .timeout(Duration.ofSeconds(30)) + .timeout(Duration.ofSeconds(60)) .build(); HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); From 5da37ae4103942a53ddbd216de0902d09eb90126 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Fri, 25 Oct 2024 00:55:36 +1100 Subject: [PATCH 06/23] fix some warning in code --- .../ai/chatting/model/Chat4AllModel.java | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java index ce336a3e171..70053d33a20 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java @@ -75,7 +75,7 @@ public Response generate(List list) { throw new IllegalArgumentException("No choices returned in the response"); } - String generatedText = textGenerationResponse.getChoices().get(0).getMessage().getContent(); + String generatedText = textGenerationResponse.getChoices().getFirst().getMessage().getContent(); if (generatedText == null || generatedText.isEmpty()) { throw new IllegalArgumentException("Generated text is null or empty"); } @@ -89,10 +89,10 @@ public Response generate(List list) { } private static class TextGenerationRequest { - private final String model; - private final List messages; - private final Double temperature; - private final Integer max_tokens; + protected final String model; + protected final List messages; + protected final Double temperature; + protected final Integer max_tokens; private TextGenerationRequest(Builder builder) { this.model = builder.model; @@ -138,16 +138,12 @@ public TextGenerationRequest build() { } private static class TextGenerationResponse { - private List choices; + protected List choices; public List getChoices() { return choices; } - public void setChoices(List choices) { - this.choices = choices; - } - public static class Choice { private Message message; @@ -183,20 +179,12 @@ public void setContent(String content) { } private static class Message { - private final String role; - private final String content; + protected String role; + protected String content; public Message(String role, String content) { this.role = role; this.content = content; } - - public String getRole() { - return role; - } - - public String getContent() { - return content; - } } } From 969cde7552df9f3a2e96c9fb25a8d7f65cce72f9 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Fri, 25 Oct 2024 01:25:57 +1100 Subject: [PATCH 07/23] write the CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f23a80be7c8..e7dfa68336c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,7 +88,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We fixed an issue where the Undo/Redo buttons were active even when all libraries are closed. [#11837](https://github.com/JabRef/jabref/issues/11837) - We fixed an issue where recently opened files were not displayed in the main menu properly. [#9042](https://github.com/JabRef/jabref/issues/9042) - We fixed an issue where the DOI lookup would show an error when a DOI was found for an entry. [#11850](https://github.com/JabRef/jabref/issues/11850) - +- We fixed an issue where the response from the local ai model is cuttoff.[#11870](https://github.com/JabRef/jabref/issues/11870) ### Removed - We removed support for case-sensitive and exact search. [#11542](https://github.com/JabRef/jabref/pull/11542) From 5f110973cde0a68d890971ddd7f2d583e615f41f Mon Sep 17 00:00:00 2001 From: Jiahao Date: Fri, 25 Oct 2024 02:26:30 +1100 Subject: [PATCH 08/23] fix some check styles --- .../org/jabref/logic/ai/AiPreferences.java | 1 + .../jabref/logic/ai/chatting/AiChatLogic.java | 13 ------------ .../ai/chatting/model/Chat4AllModel.java | 21 ++++++++----------- .../model/JabRefChatLanguageModel.java | 21 ++++++++----------- 4 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/jabref/logic/ai/AiPreferences.java b/src/main/java/org/jabref/logic/ai/AiPreferences.java index 0c4fd86af3d..e17181b2434 100644 --- a/src/main/java/org/jabref/logic/ai/AiPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiPreferences.java @@ -326,6 +326,7 @@ public String getHuggingFaceApiBaseUrl() { public void setHuggingFaceApiBaseUrl(String huggingFaceApiBaseUrl) { this.huggingFaceApiBaseUrl.set(huggingFaceApiBaseUrl); } + public StringProperty chat4AllApiBaseUrlProperty() { return chat4AllApiBaseUrl; } diff --git a/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java b/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java index 4ea1db2019b..57ffc5cffe8 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java +++ b/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java @@ -76,9 +76,7 @@ public AiChatLogic(AiPreferences aiPreferences, this.entries = entries; this.name = name; this.bibDatabaseContext = bibDatabaseContext; - this.entries.addListener((ListChangeListener) change -> rebuildChain()); - setupListeningToPreferencesChanges(); rebuildFull(chatHistory); } @@ -161,20 +159,9 @@ public AiMessage execute(UserMessage message) { aiPreferences.getAiProvider().getApiUrl(), name.get(), message.singleText()); - System.out.println("The API URL being used is: " + aiPreferences.getAiProvider().getApiUrl()); - System.out.println("API Base URL: " + aiPreferences.getSelectedApiBaseUrl()); - System.out.println("Using model ID: " + aiPreferences.getSelectedChatModel()); chatHistory.add(message); - - LOGGER.info("Sending request to URL: " + aiPreferences.getSelectedApiBaseUrl()); - LOGGER.info("Using model ID: " + aiPreferences.getSelectedChatModel()); - LOGGER.info("Request message: " + message.singleText()); AiMessage result = new AiMessage(chain.execute(message.singleText())); - LOGGER.info("Received response: " + result.text()); chatHistory.add(result); - - LOGGER.debug("Message was answered by the AI provider for {}: {}", name.get(), result.text()); - return result; } diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java index 70053d33a20..d6c3f4cb482 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java @@ -1,14 +1,6 @@ package org.jabref.logic.ai.chatting.model; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.net.URI; -import java.time.Duration; -import java.util.List; -import java.util.stream.Collectors; - -import org.jabref.logic.ai.AiPreferences; +import com.google.gson.Gson; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.message.ChatMessage; import dev.langchain4j.data.message.SystemMessage; @@ -18,7 +10,14 @@ import dev.langchain4j.model.output.FinishReason; import dev.langchain4j.model.output.Response; import dev.langchain4j.model.output.TokenUsage; -import com.google.gson.Gson; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.List; +import java.util.stream.Collectors; +import org.jabref.logic.ai.AiPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -79,9 +78,7 @@ public Response generate(List list) { if (generatedText == null || generatedText.isEmpty()) { throw new IllegalArgumentException("Generated text is null or empty"); } - return new Response<>(new AiMessage(generatedText), new TokenUsage(0, 0), FinishReason.OTHER); - } catch (Exception e) { LOGGER.error("Error generating message from Chat4All", e); throw new RuntimeException("Failed to generate AI message", e); diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 546b6783f7b..dd1ff1e7194 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -1,17 +1,5 @@ package org.jabref.logic.ai.chatting.model; -import java.net.http.HttpClient; -import java.time.Duration; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.jabref.logic.ai.AiPreferences; -import org.jabref.logic.ai.chatting.AiChatLogic; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.ai.chatting.model.Chat4AllModel; - import com.google.common.util.concurrent.ThreadFactoryBuilder; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.message.ChatMessage; @@ -21,6 +9,15 @@ import dev.langchain4j.model.huggingface.HuggingFaceChatModel; import dev.langchain4j.model.mistralai.MistralAiChatModel; import dev.langchain4j.model.output.Response; +import java.net.http.HttpClient; +import java.time.Duration; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.jabref.logic.ai.AiPreferences; +import org.jabref.logic.ai.chatting.AiChatLogic; +import org.jabref.logic.l10n.Localization; /** * Wrapper around langchain4j chat language model. From cdd938f5d33a9afb1522b1f7ac27e1ab5e1d5bfd Mon Sep 17 00:00:00 2001 From: Jiahao Date: Fri, 25 Oct 2024 02:55:08 +1100 Subject: [PATCH 09/23] convert some class to record --- .../ai/chatting/model/Chat4AllModel.java | 112 +++++++++--------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java index d6c3f4cb482..d8e66b76e64 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java @@ -70,11 +70,11 @@ public Response generate(List list) { LOGGER.info("Chat4All response: {}", response.body()); TextGenerationResponse textGenerationResponse = gson.fromJson(response.body(), TextGenerationResponse.class); - if (textGenerationResponse.getChoices() == null || textGenerationResponse.getChoices().isEmpty()) { + if (textGenerationResponse.choices() == null || textGenerationResponse.choices().isEmpty()) { throw new IllegalArgumentException("No choices returned in the response"); } - String generatedText = textGenerationResponse.getChoices().getFirst().getMessage().getContent(); + String generatedText = textGenerationResponse.choices().getFirst().message().content(); if (generatedText == null || generatedText.isEmpty()) { throw new IllegalArgumentException("Generated text is null or empty"); } @@ -133,55 +133,61 @@ public TextGenerationRequest build() { } } } - - private static class TextGenerationResponse { - protected List choices; - - public List getChoices() { - return choices; - } - - public static class Choice { - private Message message; - - public Message getMessage() { - return message; - } - - public void setMessage(Message message) { - this.message = message; - } - } - - public static class Message { - private String role; - private String content; - - public String getRole() { - return role; - } - - public void setRole(String role) { - this.role = role; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - } - } - - private static class Message { - protected String role; - protected String content; - - public Message(String role, String content) { - this.role = role; - this.content = content; - } - } + private record TextGenerationResponse(List choices) {} + + private record Choice(Message message) {} + + private record Message(String role, String content) {} + + +// private static class TextGenerationResponse { +// protected List choices; +// +// public List getChoices() { +// return choices; +// } +// +// public static class Choice { +// private Message message; +// +// public Message getMessage() { +// return message; +// } +// +// public void setMessage(Message message) { +// this.message = message; +// } +// } +// +// public static class Message { +// private String role; +// private String content; +// +// public String getRole() { +// return role; +// } +// +// public void setRole(String role) { +// this.role = role; +// } +// +// public String getContent() { +// return content; +// } +// +// public void setContent(String content) { +// this.content = content; +// } +// } +// } +// +// private static class Message { +// protected String role; +// protected String content; +// +// public Message(String role, String content) { +// this.role = role; +// this.content = content; +// } +// } } From ea08296812b79a7dbb09805fb943058d12ae516b Mon Sep 17 00:00:00 2001 From: Jiahao Date: Fri, 25 Oct 2024 03:12:06 +1100 Subject: [PATCH 10/23] continue to fix the checkstyle --- .../logic/ai/chatting/model/Chat4AllModel.java | 17 ++++++++++------- .../chatting/model/JabRefChatLanguageModel.java | 15 +++++++++------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java index d8e66b76e64..e733f5b098d 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java @@ -1,5 +1,13 @@ package org.jabref.logic.ai.chatting.model; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.List; +import java.util.stream.Collectors; + import com.google.gson.Gson; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.message.ChatMessage; @@ -10,14 +18,9 @@ import dev.langchain4j.model.output.FinishReason; import dev.langchain4j.model.output.Response; import dev.langchain4j.model.output.TokenUsage; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.time.Duration; -import java.util.List; -import java.util.stream.Collectors; + import org.jabref.logic.ai.AiPreferences; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index dd1ff1e7194..990f4023f3b 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -1,6 +1,14 @@ package org.jabref.logic.ai.chatting.model; +import java.net.http.HttpClient; +import java.time.Duration; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.message.ChatMessage; import dev.langchain4j.memory.ChatMemory; @@ -9,12 +17,7 @@ import dev.langchain4j.model.huggingface.HuggingFaceChatModel; import dev.langchain4j.model.mistralai.MistralAiChatModel; import dev.langchain4j.model.output.Response; -import java.net.http.HttpClient; -import java.time.Duration; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; + import org.jabref.logic.ai.AiPreferences; import org.jabref.logic.ai.chatting.AiChatLogic; import org.jabref.logic.l10n.Localization; From e776a5e027aad6f0f208ef7774984c4c247d3c9a Mon Sep 17 00:00:00 2001 From: Jiahao Date: Fri, 25 Oct 2024 12:36:59 +1100 Subject: [PATCH 11/23] using checkstyle.xml to detect the inappropriate code and fix it. --- .../ai/chatting/model/Chat4AllModel.java | 68 +++---------------- .../model/JabRefChatLanguageModel.java | 9 ++- 2 files changed, 12 insertions(+), 65 deletions(-) diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java index e733f5b098d..2c07db23789 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java @@ -8,6 +8,8 @@ import java.util.List; import java.util.stream.Collectors; +import org.jabref.logic.ai.AiPreferences; + import com.google.gson.Gson; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.message.ChatMessage; @@ -18,9 +20,6 @@ import dev.langchain4j.model.output.FinishReason; import dev.langchain4j.model.output.Response; import dev.langchain4j.model.output.TokenUsage; - -import org.jabref.logic.ai.AiPreferences; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -136,61 +135,10 @@ public TextGenerationRequest build() { } } } - private record TextGenerationResponse(List choices) {} - - private record Choice(Message message) {} - - private record Message(String role, String content) {} - - -// private static class TextGenerationResponse { -// protected List choices; -// -// public List getChoices() { -// return choices; -// } -// -// public static class Choice { -// private Message message; -// -// public Message getMessage() { -// return message; -// } -// -// public void setMessage(Message message) { -// this.message = message; -// } -// } -// -// public static class Message { -// private String role; -// private String content; -// -// public String getRole() { -// return role; -// } -// -// public void setRole(String role) { -// this.role = role; -// } -// -// public String getContent() { -// return content; -// } -// -// public void setContent(String content) { -// this.content = content; -// } -// } -// } -// -// private static class Message { -// protected String role; -// protected String content; -// -// public Message(String role, String content) { -// this.role = role; -// this.content = content; -// } -// } + + private record TextGenerationResponse(List choices) { } + + private record Choice(Message message) { } + + private record Message(String role, String content) { } } diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 990f4023f3b..9908cf63b15 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -7,8 +7,11 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import com.google.common.util.concurrent.ThreadFactoryBuilder; +import org.jabref.logic.ai.AiPreferences; +import org.jabref.logic.ai.chatting.AiChatLogic; +import org.jabref.logic.l10n.Localization; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.message.ChatMessage; import dev.langchain4j.memory.ChatMemory; @@ -18,10 +21,6 @@ import dev.langchain4j.model.mistralai.MistralAiChatModel; import dev.langchain4j.model.output.Response; -import org.jabref.logic.ai.AiPreferences; -import org.jabref.logic.ai.chatting.AiChatLogic; -import org.jabref.logic.l10n.Localization; - /** * Wrapper around langchain4j chat language model. *

From 6d9cc3eb3b9b814b695af5c74da63e4765ae1032 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sat, 26 Oct 2024 00:13:49 +1100 Subject: [PATCH 12/23] remove some code that not useful, and fix some code style. --- CHANGELOG.md | 2 +- .../jabref/gui/ai/components/aichat/AiChatComponent.java | 1 + src/main/java/org/jabref/gui/preferences/ai/AiTab.java | 3 ++- .../java/org/jabref/logic/ai/chatting/AiChatLogic.java | 7 +++++++ .../logic/ai/chatting/model/JabRefChatLanguageModel.java | 3 +-- .../ai/chatting/model/JvmOpenAiChatLanguageModel.java | 1 - 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34ff63dda43..a24ac70c4fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076) - We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686) - By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955) +- We fixed an issue where the response from the local ai model is cuttoff. [#11870](https://github.com/JabRef/jabref/issues/11870) ### Changed @@ -102,7 +103,6 @@ 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) ### Removed diff --git a/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java b/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java index 235a92b0b32..25e52d294e4 100644 --- a/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java +++ b/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java @@ -210,6 +210,7 @@ private void onSendMessage(String userPrompt) { .onFailure(e -> { LOGGER.error("Got an error while sending a message to AI", e); setLoading(false); + // 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")) { diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index 1b0a321946d..51a1f2462a7 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -91,10 +91,11 @@ public void initialize() { }); apiKeyTextField.textProperty().bindBidirectional(viewModel.apiKeyProperty()); + // Disable if GPT4ALL is selected apiKeyTextField.disableProperty().bind( Bindings.or( viewModel.disableBasicSettingsProperty(), - aiProviderComboBox.valueProperty().isEqualTo(AiProvider.CHAT4ALL) // Disable if GPT4ALL is selected + aiProviderComboBox.valueProperty().isEqualTo(AiProvider.CHAT4ALL) ) ); diff --git a/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java b/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java index 57ffc5cffe8..f079b093604 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java +++ b/src/main/java/org/jabref/logic/ai/chatting/AiChatLogic.java @@ -76,7 +76,9 @@ public AiChatLogic(AiPreferences aiPreferences, this.entries = entries; this.name = name; this.bibDatabaseContext = bibDatabaseContext; + this.entries.addListener((ListChangeListener) change -> rebuildChain()); + setupListeningToPreferencesChanges(); rebuildFull(chatHistory); } @@ -155,13 +157,18 @@ 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; } diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 9908cf63b15..46b6475ffa6 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -63,9 +63,8 @@ private void rebuild() { case OPEN_AI -> { langchainChatModel = Optional.of(new JvmOpenAiChatLanguageModel(aiPreferences, httpClient)); } + case CHAT4ALL-> { -// langchainChatModel = Optional.of(new JvmOpenAiChatLanguageModel(aiPreferences, httpClient)); -// System.out.println("a"); langchainChatModel = Optional.of(new Chat4AllModel(aiPreferences, httpClient)); } diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java index d9e4ee02399..95c52cf651c 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java @@ -57,7 +57,6 @@ public Response generate(List list) { .model(aiPreferences.getSelectedChatModel()) .temperature(aiPreferences.getTemperature()) .n(1) - .maxTokens(2048) .messages(messages) .build(); From 063a763179261cd9ff17415d2cb2dea5a4bef605 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sat, 26 Oct 2024 03:35:45 +1100 Subject: [PATCH 13/23] Change all the Chat4All to Gpt4All and privacy policy for GPT4All. --- .../privacynotice/PrivacyNoticeComponent.fxml | 9 ++++ .../privacynotice/PrivacyNoticeComponent.java | 4 +- .../org/jabref/gui/preferences/ai/AiTab.java | 2 +- .../gui/preferences/ai/AiTabViewModel.java | 40 ++++++++--------- .../jabref/logic/ai/AiDefaultPreferences.java | 4 +- .../org/jabref/logic/ai/AiPreferences.java | 44 +++++++++---------- .../{Chat4AllModel.java => Gpt4AllModel.java} | 12 ++--- .../model/JabRefChatLanguageModel.java | 4 +- .../preferences/JabRefCliPreferences.java | 16 +++---- .../java/org/jabref/model/ai/AiProvider.java | 2 +- 10 files changed, 73 insertions(+), 64 deletions(-) rename src/main/java/org/jabref/logic/ai/chatting/model/{Chat4AllModel.java => Gpt4AllModel.java} (93%) diff --git a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.fxml b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.fxml index 2f439beac31..a4f4da47cc2 100644 --- a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.fxml +++ b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.fxml @@ -66,6 +66,15 @@ + + + + + + + + + diff --git a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java index 1b6257e3a02..4ef78da8c36 100644 --- a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java +++ b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java @@ -25,7 +25,7 @@ public class PrivacyNoticeComponent extends ScrollPane { @FXML private TextFlow mistralAiPrivacyTextFlow; @FXML private TextFlow geminiPrivacyTextFlow; @FXML private TextFlow huggingFacePrivacyTextFlow; - @FXML private TextFlow chat4AllTextFlow; + @FXML private TextFlow gpt4AllTextFlow; @FXML private Text embeddingModelText; private final AiPreferences aiPreferences; @@ -50,7 +50,7 @@ private void initialize() { initPrivacyHyperlink(mistralAiPrivacyTextFlow, AiProvider.MISTRAL_AI); initPrivacyHyperlink(geminiPrivacyTextFlow, AiProvider.GEMINI); initPrivacyHyperlink(huggingFacePrivacyTextFlow, AiProvider.HUGGING_FACE); - initPrivacyHyperlink(chat4AllTextFlow, AiProvider.CHAT4ALL); + initPrivacyHyperlink(gpt4AllTextFlow, AiProvider.GPT4ALL); String newEmbeddingModelText = embeddingModelText.getText().replaceAll("%0", aiPreferences.getEmbeddingModel().sizeInfo()); embeddingModelText.setText(newEmbeddingModelText); diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index 51a1f2462a7..70732645494 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -95,7 +95,7 @@ public void initialize() { apiKeyTextField.disableProperty().bind( Bindings.or( viewModel.disableBasicSettingsProperty(), - aiProviderComboBox.valueProperty().isEqualTo(AiProvider.CHAT4ALL) + aiProviderComboBox.valueProperty().isEqualTo(AiProvider.GPT4ALL) ) ); diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java b/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java index ef624bf1baa..b8871f235e4 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java @@ -54,7 +54,7 @@ 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(); + private final StringProperty gpt4AllChatModel = new SimpleStringProperty(); private final StringProperty currentApiKey = new SimpleStringProperty(); @@ -62,7 +62,7 @@ public class AiTabViewModel implements PreferenceTabViewModel { 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 StringProperty gpt4AllApiKey = new SimpleStringProperty(); private final BooleanProperty customizeExpertSettings = new SimpleBooleanProperty(); @@ -77,7 +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 gpt4AllApiBaseUrl = new SimpleStringProperty(); private final StringProperty instruction = new SimpleStringProperty(); private final StringProperty temperature = new SimpleStringProperty(); @@ -153,10 +153,10 @@ 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()); + case GPT4ALL-> { + gpt4AllChatModel.set(oldChatModel); + gpt4AllApiKey.set(currentApiKey.get()); + gpt4AllApiBaseUrl.set(currentApiBaseUrl.get()); } } } @@ -182,10 +182,10 @@ 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()); + case GPT4ALL -> { + currentChatModel.set(gpt4AllChatModel.get()); + currentApiKey.set(gpt4AllApiKey.get()); + currentApiBaseUrl.set(gpt4AllApiBaseUrl.get()); } } }); @@ -196,7 +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); + case GPT4ALL -> gpt4AllChatModel.set(newValue); } contextWindowSize.set(AiDefaultPreferences.getContextWindowSize(selectedAiProvider.get(), newValue)); @@ -208,7 +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); + case GPT4ALL -> gpt4AllApiKey.set(newValue); } }); @@ -218,7 +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); + case GPT4ALL -> gpt4AllApiBaseUrl.set(newValue); } }); @@ -295,19 +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)); + gpt4AllApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.GPT4ALL)); openAiApiBaseUrl.setValue(aiPreferences.getOpenAiApiBaseUrl()); mistralAiApiBaseUrl.setValue(aiPreferences.getMistralAiApiBaseUrl()); geminiApiBaseUrl.setValue(aiPreferences.getGeminiApiBaseUrl()); huggingFaceApiBaseUrl.setValue(aiPreferences.getHuggingFaceApiBaseUrl()); - chat4AllApiBaseUrl.setValue(aiPreferences.getChat4AllApiBaseUrl()); + gpt4AllApiBaseUrl.setValue(aiPreferences.getGpt4AllApiBaseUrl()); openAiChatModel.setValue(aiPreferences.getOpenAiChatModel()); mistralAiChatModel.setValue(aiPreferences.getMistralAiChatModel()); geminiChatModel.setValue(aiPreferences.getGeminiChatModel()); huggingFaceChatModel.setValue(aiPreferences.getHuggingFaceChatModel()); - chat4AllChatModel.setValue(aiPreferences.getChat4AllChatModel()); + gpt4AllChatModel.setValue(aiPreferences.getGpt4AllChatModel()); enableAi.setValue(aiPreferences.getEnableAi()); autoGenerateSummaries.setValue(aiPreferences.getAutoGenerateSummaries()); @@ -339,13 +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.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.CHAT4ALL, chat4AllApiKey.get() == null ? "" : chat4AllApiKey.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(); @@ -357,7 +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.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. diff --git a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java index 75325d21b5e..3ea26c4c576 100644 --- a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java @@ -10,7 +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_LOCAL(AiProvider.GPT4ALL, "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), @@ -64,7 +64,7 @@ public String toString() { AiProvider.MISTRAL_AI, PredefinedChatModel.OPEN_MIXTRAL_8X22B, AiProvider.GEMINI, PredefinedChatModel.GEMINI_1_5_FLASH, AiProvider.HUGGING_FACE, PredefinedChatModel.HUGGING_FACE, - AiProvider.CHAT4ALL, PredefinedChatModel.GPT_LOCAL + AiProvider.GPT4ALL, PredefinedChatModel.GPT_LOCAL ); public static final boolean CUSTOMIZE_SETTINGS = false; diff --git a/src/main/java/org/jabref/logic/ai/AiPreferences.java b/src/main/java/org/jabref/logic/ai/AiPreferences.java index e17181b2434..48b10812338 100644 --- a/src/main/java/org/jabref/logic/ai/AiPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiPreferences.java @@ -40,7 +40,7 @@ public class AiPreferences { private final StringProperty mistralAiChatModel; private final StringProperty geminiChatModel; private final StringProperty huggingFaceChatModel; - private final StringProperty chat4AllChatModel; + private final StringProperty gpt4AllChatModel; private final BooleanProperty customizeExpertSettings; @@ -48,7 +48,7 @@ public class AiPreferences { private final StringProperty mistralAiApiBaseUrl; private final StringProperty geminiApiBaseUrl; private final StringProperty huggingFaceApiBaseUrl; - private final StringProperty chat4AllApiBaseUrl; + private final StringProperty gpt4AllApiBaseUrl; private final ObjectProperty embeddingModel; private final StringProperty instruction; @@ -69,13 +69,13 @@ public AiPreferences(boolean enableAi, String mistralAiChatModel, String geminiChatModel, String huggingFaceChatModel, - String chat4AllModel, + String gpt4AllModel, boolean customizeExpertSettings, String openAiApiBaseUrl, String mistralAiApiBaseUrl, String geminiApiBaseUrl, String huggingFaceApiBaseUrl, - String chat4AllApiBaseUrl, + String gpt4AllApiBaseUrl, EmbeddingModel embeddingModel, String instruction, double temperature, @@ -95,7 +95,7 @@ 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.gpt4AllChatModel = new SimpleStringProperty(gpt4AllModel); this.customizeExpertSettings = new SimpleBooleanProperty(customizeExpertSettings); @@ -103,7 +103,7 @@ public AiPreferences(boolean enableAi, this.mistralAiApiBaseUrl = new SimpleStringProperty(mistralAiApiBaseUrl); this.geminiApiBaseUrl = new SimpleStringProperty(geminiApiBaseUrl); this.huggingFaceApiBaseUrl = new SimpleStringProperty(huggingFaceApiBaseUrl); - this.chat4AllApiBaseUrl = new SimpleStringProperty(chat4AllApiBaseUrl); + this.gpt4AllApiBaseUrl = new SimpleStringProperty(gpt4AllApiBaseUrl); this.embeddingModel = new SimpleObjectProperty<>(embeddingModel); this.instruction = new SimpleStringProperty(instruction); @@ -239,16 +239,16 @@ public void setHuggingFaceChatModel(String huggingFaceChatModel) { this.huggingFaceChatModel.set(huggingFaceChatModel); } - public StringProperty chat4AllChatModelProperty() { - return chat4AllChatModel; + public StringProperty gpt4AllChatModelProperty() { + return gpt4AllChatModel; } - public String getChat4AllChatModel() { + public String getGpt4AllChatModel() { return huggingFaceChatModel.get(); } - public void setChat4AllChatModel(String chat4AllChatModel) { - this.chat4AllChatModel.set(chat4AllChatModel); + public void setGpt4AllChatModel(String gpt4AllChatModel) { + this.gpt4AllChatModel.set(gpt4AllChatModel); } public BooleanProperty customizeExpertSettingsProperty() { @@ -327,16 +327,16 @@ public void setHuggingFaceApiBaseUrl(String huggingFaceApiBaseUrl) { this.huggingFaceApiBaseUrl.set(huggingFaceApiBaseUrl); } - public StringProperty chat4AllApiBaseUrlProperty() { - return chat4AllApiBaseUrl; + public StringProperty gpt4AllApiBaseUrlProperty() { + return gpt4AllApiBaseUrl; } - public String getChat4AllApiBaseUrl() { - return chat4AllApiBaseUrl.get(); + public String getGpt4AllApiBaseUrl() { + return gpt4AllApiBaseUrl.get(); } - public void setChat4AllApiBaseUrl(String chat4AllApiBaseUrl) { - this.chat4AllApiBaseUrl.set(chat4AllApiBaseUrl); + public void setGpt4AllApiBaseUrl(String gpt4AllApiBaseUrl) { + this.gpt4AllApiBaseUrl.set(gpt4AllApiBaseUrl); } public StringProperty instructionProperty() { @@ -384,7 +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()); + case GPT4ALL -> AiDefaultPreferences.getContextWindowSize(AiProvider.GPT4ALL, gpt4AllChatModel.get()); }; } } @@ -512,8 +512,8 @@ public String getSelectedChatModel() { huggingFaceChatModel.get(); case GEMINI -> geminiChatModel.get(); - case CHAT4ALL -> - chat4AllChatModel.get(); + case GPT4ALL -> + gpt4AllChatModel.get(); }; } @@ -528,8 +528,8 @@ public String getSelectedApiBaseUrl() { huggingFaceApiBaseUrl.get(); case GEMINI -> geminiApiBaseUrl.get(); - case CHAT4ALL -> - chat4AllApiBaseUrl.get(); + case GPT4ALL -> + gpt4AllApiBaseUrl.get(); }; } else { return aiProvider.get().getApiUrl(); diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java similarity index 93% rename from src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java rename to src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java index 2c07db23789..66539927aeb 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Chat4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java @@ -23,22 +23,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Chat4AllModel implements ChatLanguageModel { +public class Gpt4AllModel implements ChatLanguageModel { - private static final Logger LOGGER = LoggerFactory.getLogger(Chat4AllModel.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Gpt4AllModel.class); private final AiPreferences aiPreferences; private final HttpClient httpClient; private final Gson gson = new Gson(); - public Chat4AllModel(AiPreferences aiPreferences, HttpClient httpClient) { + public Gpt4AllModel(AiPreferences aiPreferences, HttpClient httpClient) { this.aiPreferences = aiPreferences; this.httpClient = httpClient; } @Override public Response generate(List list) { - LOGGER.debug("Generating response from Chat4All model with {} messages: {}", list.size(), list); + LOGGER.debug("Generating response from Gpt4All model with {} messages: {}", list.size(), list); List messages = list.stream() .map(chatMessage -> switch (chatMessage) { @@ -69,7 +69,7 @@ public Response generate(List list) { .build(); HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - LOGGER.info("Chat4All response: {}", response.body()); + LOGGER.info("Gpt4All response: {}", response.body()); TextGenerationResponse textGenerationResponse = gson.fromJson(response.body(), TextGenerationResponse.class); if (textGenerationResponse.choices() == null || textGenerationResponse.choices().isEmpty()) { @@ -82,7 +82,7 @@ public Response generate(List list) { } return new Response<>(new AiMessage(generatedText), new TokenUsage(0, 0), FinishReason.OTHER); } catch (Exception e) { - LOGGER.error("Error generating message from Chat4All", e); + LOGGER.error("Error generating message from Gpt4All", e); throw new RuntimeException("Failed to generate AI message", e); } } diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 46b6475ffa6..83b7c5e9b92 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -64,8 +64,8 @@ private void rebuild() { langchainChatModel = Optional.of(new JvmOpenAiChatLanguageModel(aiPreferences, httpClient)); } - case CHAT4ALL-> { - langchainChatModel = Optional.of(new Chat4AllModel(aiPreferences, httpClient)); + case GPT4ALL-> { + langchainChatModel = Optional.of(new Gpt4AllModel(aiPreferences, httpClient)); } case MISTRAL_AI -> { diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index a87a37debd2..27760c02f70 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -356,14 +356,14 @@ public class JabRefCliPreferences implements CliPreferences { private static final String AI_MISTRAL_AI_CHAT_MODEL = "aiMistralAiChatModel"; private static final String AI_GEMINI_CHAT_MODEL = "aiGeminiChatModel"; private static final String AI_HUGGING_FACE_CHAT_MODEL = "aiHuggingFaceChatModel"; - private static final String AI_CHAT_4_ALL_MODEL = "aiChat4AllChatModel"; + private static final String AI_GPT_4_ALL_MODEL = "aiGpt4AllChatModel"; private static final String AI_CUSTOMIZE_SETTINGS = "aiCustomizeSettings"; private static final String AI_EMBEDDING_MODEL = "aiEmbeddingModel"; private static final String AI_OPEN_AI_API_BASE_URL = "aiOpenAiApiBaseUrl"; private static final String AI_MISTRAL_AI_API_BASE_URL = "aiMistralAiApiBaseUrl"; private static final String AI_GEMINI_API_BASE_URL = "aiGeminiApiBaseUrl"; private static final String AI_HUGGING_FACE_API_BASE_URL = "aiHuggingFaceApiBaseUrl"; - private static final String AI_CHAT_4_ALL_API_BASE_URL = "aiChat4AllApiBaseUrl"; + private static final String AI_GPT_4_ALL_API_BASE_URL = "aiGpt4AllApiBaseUrl"; private static final String AI_SYSTEM_MESSAGE = "aiSystemMessage"; private static final String AI_TEMPERATURE = "aiTemperature"; private static final String AI_CONTEXT_WINDOW_SIZE = "aiMessageWindowSize"; @@ -643,14 +643,14 @@ protected JabRefCliPreferences() { defaults.put(AI_MISTRAL_AI_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.MISTRAL_AI).getName()); defaults.put(AI_GEMINI_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.GEMINI).getName()); defaults.put(AI_HUGGING_FACE_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.HUGGING_FACE).getName()); - defaults.put(AI_CHAT_4_ALL_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.CHAT4ALL).getName()); + defaults.put(AI_GPT_4_ALL_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.GPT4ALL).getName()); defaults.put(AI_CUSTOMIZE_SETTINGS, AiDefaultPreferences.CUSTOMIZE_SETTINGS); defaults.put(AI_EMBEDDING_MODEL, AiDefaultPreferences.EMBEDDING_MODEL.name()); defaults.put(AI_OPEN_AI_API_BASE_URL, AiProvider.OPEN_AI.getApiUrl()); defaults.put(AI_MISTRAL_AI_API_BASE_URL, AiProvider.MISTRAL_AI.getApiUrl()); defaults.put(AI_GEMINI_API_BASE_URL, AiProvider.GEMINI.getApiUrl()); defaults.put(AI_HUGGING_FACE_API_BASE_URL, AiProvider.HUGGING_FACE.getApiUrl()); - defaults.put(AI_CHAT_4_ALL_API_BASE_URL, AiProvider.CHAT4ALL.getApiUrl()); + defaults.put(AI_GPT_4_ALL_API_BASE_URL, AiProvider.GPT4ALL.getApiUrl()); defaults.put(AI_SYSTEM_MESSAGE, AiDefaultPreferences.SYSTEM_MESSAGE); defaults.put(AI_TEMPERATURE, AiDefaultPreferences.TEMPERATURE); defaults.put(AI_CONTEXT_WINDOW_SIZE, AiDefaultPreferences.getContextWindowSize(AiDefaultPreferences.PROVIDER, AiDefaultPreferences.CHAT_MODELS.get(AiDefaultPreferences.PROVIDER).getName())); @@ -1839,13 +1839,13 @@ public AiPreferences getAiPreferences() { get(AI_MISTRAL_AI_CHAT_MODEL), get(AI_GEMINI_CHAT_MODEL), get(AI_HUGGING_FACE_CHAT_MODEL), - get(AI_CHAT_4_ALL_MODEL), + get(AI_GPT_4_ALL_MODEL), getBoolean(AI_CUSTOMIZE_SETTINGS), get(AI_OPEN_AI_API_BASE_URL), get(AI_MISTRAL_AI_API_BASE_URL), get(AI_GEMINI_API_BASE_URL), get(AI_HUGGING_FACE_API_BASE_URL), - get(AI_CHAT_4_ALL_API_BASE_URL), + get(AI_GPT_4_ALL_API_BASE_URL), EmbeddingModel.valueOf(get(AI_EMBEDDING_MODEL)), get(AI_SYSTEM_MESSAGE), getDouble(AI_TEMPERATURE), @@ -1865,7 +1865,7 @@ public AiPreferences getAiPreferences() { EasyBind.listen(aiPreferences.mistralAiChatModelProperty(), (obs, oldValue, newValue) -> put(AI_MISTRAL_AI_CHAT_MODEL, newValue)); EasyBind.listen(aiPreferences.geminiChatModelProperty(), (obs, oldValue, newValue) -> put(AI_GEMINI_CHAT_MODEL, newValue)); EasyBind.listen(aiPreferences.huggingFaceChatModelProperty(), (obs, oldValue, newValue) -> put(AI_HUGGING_FACE_CHAT_MODEL, newValue)); - EasyBind.listen(aiPreferences.chat4AllChatModelProperty(), (obs, oldValue, newValue) -> put(AI_CHAT_4_ALL_MODEL, newValue)); + EasyBind.listen(aiPreferences.gpt4AllChatModelProperty(), (obs, oldValue, newValue) -> put(AI_GPT_4_ALL_MODEL, newValue)); EasyBind.listen(aiPreferences.customizeExpertSettingsProperty(), (obs, oldValue, newValue) -> putBoolean(AI_CUSTOMIZE_SETTINGS, newValue)); @@ -1873,7 +1873,7 @@ public AiPreferences getAiPreferences() { EasyBind.listen(aiPreferences.mistralAiApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_MISTRAL_AI_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.geminiApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_GEMINI_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.huggingFaceApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_HUGGING_FACE_API_BASE_URL, newValue)); - EasyBind.listen(aiPreferences.chat4AllApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_CHAT_4_ALL_API_BASE_URL, newValue)); + EasyBind.listen(aiPreferences.gpt4AllApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_GPT_4_ALL_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.embeddingModelProperty(), (obs, oldValue, newValue) -> put(AI_EMBEDDING_MODEL, newValue.name())); EasyBind.listen(aiPreferences.instructionProperty(), (obs, oldValue, newValue) -> put(AI_SYSTEM_MESSAGE, newValue)); diff --git a/src/main/java/org/jabref/model/ai/AiProvider.java b/src/main/java/org/jabref/model/ai/AiProvider.java index e95ee4866a2..053406fdc5f 100644 --- a/src/main/java/org/jabref/model/ai/AiProvider.java +++ b/src/main/java/org/jabref/model/ai/AiProvider.java @@ -7,7 +7,7 @@ public enum AiProvider implements Serializable { MISTRAL_AI("Mistral AI", "https://mistral.ai/terms/#privacy-policy", "https://mistral.ai/terms/#privacy-policy"), GEMINI("Gemini", "https://huggingface.co/privacy", "https://ai.google.dev/gemini-api/terms"), HUGGING_FACE("Hugging Face", "https://huggingface.co/api", "https://huggingface.co/privacy"), - CHAT4ALL("Chat4All", "http://localhost:4891/v1", "https://openai.com/policies/privacy-policy/"); + GPT4ALL("GPT4All", "http://localhost:4891/v1", "https://www.nomic.ai/gpt4all/legal/privacy-policy"); private final String label; private final String apiUrl; From e149b4b556b353710c2f0add17bea33ad7d1f490 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sat, 26 Oct 2024 04:29:54 +1100 Subject: [PATCH 14/23] add the prompt text for Gpt4All, rewrite the CHANGELOG.md and restore the JvmOpenAiChatLanguageModel.java to its original state(main). --- CHANGELOG.md | 2 +- src/main/java/org/jabref/gui/preferences/ai/AiTab.java | 4 ++++ src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java | 2 +- .../logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a24ac70c4fa..e8b4e3aeab4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076) - We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686) - By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955) -- We fixed an issue where the response from the local ai model is cuttoff. [#11870](https://github.com/JabRef/jabref/issues/11870) +- We fixed an issue that when we use the local model from Gpt4All, the response from the model is cuttoff.. [#11870](https://github.com/JabRef/jabref/issues/11870) ### Changed diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index 70732645494..c9c49d42f5e 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -29,6 +29,7 @@ public class AiTab extends AbstractPreferenceTabView 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_CHAT_MODEL_PROMPT = "Phi-3.1-mini(or any other local model name from Gpt4All)"; @FXML private CheckBox enableAi; @FXML private CheckBox autoGenerateEmbeddings; @@ -88,6 +89,9 @@ public void initialize() { if (newValue == AiProvider.HUGGING_FACE) { chatModelComboBox.setPromptText(HUGGING_FACE_CHAT_MODEL_PROMPT); } + if (newValue == AiProvider.GPT4ALL) { + chatModelComboBox.setPromptText(GPT_CHAT_MODEL_PROMPT); + } }); apiKeyTextField.textProperty().bindBidirectional(viewModel.apiKeyProperty()); diff --git a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java index 3ea26c4c576..f42cb129a94 100644 --- a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java @@ -10,7 +10,7 @@ public class AiDefaultPreferences { public enum PredefinedChatModel { GPT_4O_MINI(AiProvider.OPEN_AI, "gpt-4o-mini", 128000), - GPT_LOCAL(AiProvider.GPT4ALL, "Phi-3.1-mini-128k-instruct-Q4_0-precise-output-tensor.gguf", 128000), + GPT_LOCAL(AiProvider.GPT4ALL, "", 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), diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java index 95c52cf651c..023a503d2aa 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java @@ -31,11 +31,13 @@ public class JvmOpenAiChatLanguageModel implements ChatLanguageModel { public JvmOpenAiChatLanguageModel(AiPreferences aiPreferences, HttpClient httpClient) { this.aiPreferences = aiPreferences; + OpenAI openAI = OpenAI .newBuilder(aiPreferences.getApiKeyForAiProvider(aiPreferences.getAiProvider())) .httpClient(httpClient) .baseUrl(aiPreferences.getSelectedApiBaseUrl()) .build(); + this.chatClient = openAI.chatClient(); } From 33d20b18870e54d4818fd851ede693bacfa603cb Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sat, 26 Oct 2024 04:32:59 +1100 Subject: [PATCH 15/23] Change GPT_CHAT_MODEL_PROMPT to GPT_4_ALL_CHAT_MODEL_PROMPT. --- src/main/java/org/jabref/gui/preferences/ai/AiTab.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index c9c49d42f5e..a9859559a0e 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -29,7 +29,7 @@ public class AiTab extends AbstractPreferenceTabView 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_CHAT_MODEL_PROMPT = "Phi-3.1-mini(or any other local model name from Gpt4All)"; + 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; @@ -90,7 +90,7 @@ public void initialize() { chatModelComboBox.setPromptText(HUGGING_FACE_CHAT_MODEL_PROMPT); } if (newValue == AiProvider.GPT4ALL) { - chatModelComboBox.setPromptText(GPT_CHAT_MODEL_PROMPT); + chatModelComboBox.setPromptText(GPT_4_ALL_CHAT_MODEL_PROMPT); } }); From e2c91e8a74b875749ce604197b4375bd91c7c56c Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sat, 26 Oct 2024 19:28:09 +1100 Subject: [PATCH 16/23] fix the name problem and add some comments in Gpt4AllModel.java, using BLANK when the model name is not specified --- CHANGELOG.md | 2 +- src/main/java/org/jabref/gui/preferences/ai/AiTab.java | 2 +- .../java/org/jabref/logic/ai/AiDefaultPreferences.java | 8 ++++---- .../org/jabref/logic/ai/chatting/model/Gpt4AllModel.java | 4 ++++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8b4e3aeab4..4d82c491ab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076) - We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686) - By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955) -- We fixed an issue that when we use the local model from Gpt4All, the response from the model is cuttoff.. [#11870](https://github.com/JabRef/jabref/issues/11870) +- We fixed an issue that when we use the local model from Gpt4All, the response from the model is cuttoff. [#11870](https://github.com/JabRef/jabref/issues/11870) ### Changed diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index a9859559a0e..e06bc1727c5 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -29,7 +29,7 @@ public class AiTab extends AbstractPreferenceTabView 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)"; + 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; diff --git a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java index f42cb129a94..6f0a8dbff3e 100644 --- a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java @@ -10,7 +10,6 @@ public class AiDefaultPreferences { public enum PredefinedChatModel { GPT_4O_MINI(AiProvider.OPEN_AI, "gpt-4o-mini", 128000), - GPT_LOCAL(AiProvider.GPT4ALL, "", 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), @@ -24,7 +23,8 @@ 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(AiProvider.HUGGING_FACE, "", 0); private final AiProvider aiProvider; private final String name; @@ -63,8 +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.GPT4ALL, PredefinedChatModel.GPT_LOCAL + AiProvider.HUGGING_FACE, PredefinedChatModel.BLANK, + AiProvider.GPT4ALL, PredefinedChatModel.BLANK ); public static final boolean CUSTOMIZE_SETTINGS = false; diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java index 66539927aeb..20c26951f69 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java @@ -80,6 +80,10 @@ public Response generate(List list) { if (generatedText == null || generatedText.isEmpty()) { throw new IllegalArgumentException("Generated text is null or empty"); } + + // Note: We do not check the token usage and finish reason here. + // This class is not a complete implementation of langchain4j's ChatLanguageModel. + // We only implemented the functionality we specifically need. return new Response<>(new AiMessage(generatedText), new TokenUsage(0, 0), FinishReason.OTHER); } catch (Exception e) { LOGGER.error("Error generating message from Gpt4All", e); From 725e9fef1949a66b1cef650ef2f066b20739e6b7 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sat, 26 Oct 2024 21:17:59 +1100 Subject: [PATCH 17/23] change Gpt4All to GPT4ALL --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d82c491ab1..2de019fe9ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076) - We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686) - By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955) -- We fixed an issue that when we use the local model from Gpt4All, the response from the model is cuttoff. [#11870](https://github.com/JabRef/jabref/issues/11870) +- We fixed an issue that when we use the local model from GPT4ALL, the response from the model is cuttoff. [#11870](https://github.com/JabRef/jabref/issues/11870) ### Changed From 09f1230113fa2e1091311487578f35224e21b820 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sat, 26 Oct 2024 23:17:19 +1100 Subject: [PATCH 18/23] fix some bug when Api key is empty --- .../logic/ai/chatting/model/JabRefChatLanguageModel.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 83b7c5e9b92..6736e55de48 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -20,6 +20,7 @@ import dev.langchain4j.model.huggingface.HuggingFaceChatModel; import dev.langchain4j.model.mistralai.MistralAiChatModel; import dev.langchain4j.model.output.Response; +import org.jabref.model.ai.AiProvider; /** * Wrapper around langchain4j chat language model. @@ -54,7 +55,7 @@ public JabRefChatLanguageModel(AiPreferences aiPreferences) { */ private void rebuild() { String apiKey = aiPreferences.getApiKeyForAiProvider(aiPreferences.getAiProvider()); - if (!aiPreferences.getEnableAi() || apiKey.isEmpty()) { + if (!aiPreferences.getEnableAi() || (apiKey.isEmpty() && aiPreferences.getAiProvider() != AiProvider.GPT4ALL)) { langchainChatModel = Optional.empty(); return; } @@ -133,7 +134,7 @@ public Response generate(List list) { if (langchainChatModel.isEmpty()) { if (!aiPreferences.getEnableAi()) { throw new RuntimeException(Localization.lang("In order to use AI chat, you need to enable chatting with attached PDF files in JabRef preferences (AI tab).")); - } else if (aiPreferences.getApiKeyForAiProvider(aiPreferences.getAiProvider()).isEmpty()) { + } else if (aiPreferences.getApiKeyForAiProvider(aiPreferences.getAiProvider()).isEmpty() && aiPreferences.getAiProvider() != AiProvider.GPT4ALL) { throw new RuntimeException(Localization.lang("In order to use AI chat, set an API key inside JabRef preferences (AI tab).")); } else { rebuild(); From c576553f619a6eebe1999957de1e1a98291c8737 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sat, 26 Oct 2024 23:21:44 +1100 Subject: [PATCH 19/23] fix the checkstyle --- .../jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 6736e55de48..8445e15347d 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -10,6 +10,7 @@ import org.jabref.logic.ai.AiPreferences; import org.jabref.logic.ai.chatting.AiChatLogic; import org.jabref.logic.l10n.Localization; +import org.jabref.model.ai.AiProvider; import com.google.common.util.concurrent.ThreadFactoryBuilder; import dev.langchain4j.data.message.AiMessage; @@ -20,7 +21,6 @@ import dev.langchain4j.model.huggingface.HuggingFaceChatModel; import dev.langchain4j.model.mistralai.MistralAiChatModel; import dev.langchain4j.model.output.Response; -import org.jabref.model.ai.AiProvider; /** * Wrapper around langchain4j chat language model. From d23d9a016b8d9f9a6a6a855bea2a52819163aa07 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sun, 27 Oct 2024 01:42:56 +1100 Subject: [PATCH 20/23] use GPT4All as it's the official name in CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2de019fe9ca..08274c83239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076) - We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686) - By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955) -- We fixed an issue that when we use the local model from GPT4ALL, the response from the model is cuttoff. [#11870](https://github.com/JabRef/jabref/issues/11870) +- We fixed an issue that when we use the local model from GPT4All, the response from the model is cuttoff. [#11870](https://github.com/JabRef/jabref/issues/11870) ### Changed From 6c9c7e02bf2d375a2e2dc6df83117513dbc67046 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Sat, 26 Oct 2024 18:49:57 +0300 Subject: [PATCH 21/23] Update src/main/java/org/jabref/gui/preferences/ai/AiTab.java --- src/main/java/org/jabref/gui/preferences/ai/AiTab.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index e06bc1727c5..3360e3a5b4a 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -29,7 +29,7 @@ public class AiTab extends AbstractPreferenceTabView 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)"; + 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; From 616f1d2c15e1aef81fa78c41e221c00408b0cba6 Mon Sep 17 00:00:00 2001 From: Jiahao Date: Sun, 27 Oct 2024 02:58:22 +1100 Subject: [PATCH 22/23] use GPT4All in prompt text and separate BLANK into BLANK_HUGGING_FACE and BLANK_GPT4ALL --- src/main/java/org/jabref/gui/preferences/ai/AiTab.java | 2 +- .../java/org/jabref/logic/ai/AiDefaultPreferences.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index e06bc1727c5..3360e3a5b4a 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -29,7 +29,7 @@ public class AiTab extends AbstractPreferenceTabView 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)"; + 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; diff --git a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java index 6f0a8dbff3e..3cdbd9bfda8 100644 --- a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java @@ -24,7 +24,8 @@ public enum PredefinedChatModel { GEMINI_1_0_PRO(AiProvider.GEMINI, "gemini-1.0-pro", 32000), // Dummy variant for Hugging Face models. // Blank entry used for cases where the model name is not specified. - BLANK(AiProvider.HUGGING_FACE, "", 0); + BLANK_HUGGING_FACE(AiProvider.HUGGING_FACE, "", 0), + BLANK_GPT4ALL(AiProvider.GPT4ALL, "", 0); private final AiProvider aiProvider; private final String name; @@ -63,8 +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.BLANK, - AiProvider.GPT4ALL, PredefinedChatModel.BLANK + AiProvider.HUGGING_FACE, PredefinedChatModel.BLANK_HUGGING_FACE, + AiProvider.GPT4ALL, PredefinedChatModel.BLANK_GPT4ALL ); public static final boolean CUSTOMIZE_SETTINGS = false; From f5c93c7c881ad78f2e496291f8533d051695afa3 Mon Sep 17 00:00:00 2001 From: ThiloteE <73715071+ThiloteE@users.noreply.github.com> Date: Sun, 27 Oct 2024 13:45:50 +0100 Subject: [PATCH 23/23] Update CHANGELOG.md - Add AI preferences section to changelog - Add AI providers to changelog --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a74cc53929..806deb5b445 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) @@ -40,7 +43,6 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076) - We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686) - By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955) -- We fixed an issue that when we use the local model from GPT4All, the response from the model is cuttoff. [#11870](https://github.com/JabRef/jabref/issues/11870) - We use the menu icon for background tasks as a progress indicator to visualise an import's progress when dragging and dropping several PDF files into the main table. [#12072](https://github.com/JabRef/jabref/pull/12072) ### Changed