Skip to content

Commit a264d6b

Browse files
authored
Merge pull request #61 from InAnYan/fix-for-51
2 parents bc30d1a + 7df72ed commit a264d6b

File tree

58 files changed

+1114
-528
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1114
-528
lines changed

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ modularity.disableEffectiveArgumentsAdjustment()
9999
modularity.patchModule("langchain4j", "langchain4j-core-0.31.0.jar")
100100
modularity.patchModule("langchain4j", "langchain4j-embeddings-0.31.0.jar")
101101
modularity.patchModule("langchain4j", "langchain4j-embeddings-all-minilm-l6-v2-0.31.0.jar")
102+
modularity.patchModule("langchain4j", "langchain4j-embeddings-all-minilm-l6-v2-q-0.31.0.jar")
102103
modularity.patchModule("langchain4j", "langchain4j-open-ai-0.31.0.jar")
103104

104105
sourceSets {
@@ -312,6 +313,7 @@ dependencies {
312313
// AI
313314
implementation 'dev.langchain4j:langchain4j:0.31.0'
314315
implementation 'dev.langchain4j:langchain4j-embeddings-all-minilm-l6-v2:0.31.0'
316+
implementation 'dev.langchain4j:langchain4j-embeddings-all-minilm-l6-v2-q:0.31.0'
315317
implementation('dev.langchain4j:langchain4j-open-ai:0.31.0') {
316318
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
317319
}

src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,5 @@
156156
requires mslinks;
157157
requires com.dlsc.unitfx;
158158
requires org.checkerframework.checker.qual;
159+
requires jakarta.validation;
159160
}

src/main/java/org/jabref/gui/LibraryTab.java

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.jabref.gui.util.DefaultTaskExecutor;
5959
import org.jabref.gui.util.TaskExecutor;
6060
import org.jabref.logic.ai.AiService;
61+
import org.jabref.logic.ai.embeddings.EmbeddingsGenerationTaskManager;
6162
import org.jabref.logic.citationstyle.CitationStyleCache;
6263
import org.jabref.logic.importer.ParserResult;
6364
import org.jabref.logic.importer.util.FileFieldParser;
@@ -153,6 +154,8 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR }
153154
private BackgroundTask<ParserResult> dataLoadingTask;
154155

155156
private final IndexingTaskManager indexingTaskManager;
157+
private EmbeddingsGenerationTaskManager embeddingsGenerationTaskManager;
158+
156159
private final TaskExecutor taskExecutor;
157160
private final DirectoryMonitorManager directoryMonitorManager;
158161

@@ -176,6 +179,7 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext,
176179
this.fileUpdateMonitor = fileUpdateMonitor;
177180
this.entryTypesManager = entryTypesManager;
178181
this.indexingTaskManager = new IndexingTaskManager(taskExecutor);
182+
this.embeddingsGenerationTaskManager = new EmbeddingsGenerationTaskManager(bibDatabaseContext, preferencesService.getFilePreferences(), aiService, taskExecutor);
179183
this.taskExecutor = taskExecutor;
180184
this.directoryMonitorManager = new DirectoryMonitorManager(Globals.getDirectoryMonitor());
181185

@@ -191,6 +195,7 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext,
191195
setupAutoCompletion();
192196

193197
this.getDatabase().registerListener(new IndexUpdateListener());
198+
this.getDatabase().registerListener(new EmbeddingsUpdateListener());
194199
this.getDatabase().registerListener(new EntriesRemovedListener());
195200

196201
// ensure that at each addition of a new entry, the entry is added to the groups interface
@@ -262,12 +267,16 @@ private void onDatabaseLoadingSucceed(ParserResult result) {
262267

263268
if (preferencesService.getFilePreferences().shouldFulltextIndexLinkedFiles()) {
264269
try {
265-
indexingTaskManager.updateIndex(PdfIndexerManager.getIndexer(bibDatabaseContext, preferencesService.getFilePreferences(), preferencesService.getAiPreferences()), bibDatabaseContext);
270+
indexingTaskManager.updateIndex(PdfIndexerManager.getIndexer(bibDatabaseContext, preferencesService.getFilePreferences()), bibDatabaseContext);
266271
} catch (IOException e) {
267272
LOGGER.error("Cannot access lucene index", e);
268273
}
269274
}
270275

276+
if (preferencesService.getAiPreferences().getEnableChatWithFiles()) {
277+
embeddingsGenerationTaskManager.updateEmbeddings(bibDatabaseContext);
278+
}
279+
271280
LOGGER.trace("loading.set(false);");
272281
loading.set(false);
273282
dataLoadingTask = null;
@@ -308,11 +317,13 @@ private void setDatabaseContext(BibDatabaseContext bibDatabaseContext) {
308317
this.tableModel = new MainTableDataModel(getBibDatabaseContext(), preferencesService, stateManager);
309318
citationStyleCache = new CitationStyleCache(bibDatabaseContext);
310319
annotationCache = new FileAnnotationCache(bibDatabaseContext, preferencesService.getFilePreferences());
320+
this.embeddingsGenerationTaskManager = new EmbeddingsGenerationTaskManager(bibDatabaseContext, preferencesService.getFilePreferences(), aiService, taskExecutor);
311321

312322
setupMainPanel();
313323
setupAutoCompletion();
314324

315325
this.getDatabase().registerListener(new IndexUpdateListener());
326+
this.getDatabase().registerListener(new EmbeddingsUpdateListener());
316327
this.getDatabase().registerListener(new EntriesRemovedListener());
317328

318329
// ensure that at each addition of a new entry, the entry is added to the groups interface
@@ -1064,7 +1075,7 @@ private class IndexUpdateListener {
10641075
public void listen(EntriesAddedEvent addedEntryEvent) {
10651076
if (preferencesService.getFilePreferences().shouldFulltextIndexLinkedFiles()) {
10661077
try {
1067-
PdfIndexer pdfIndexer = PdfIndexerManager.getIndexer(bibDatabaseContext, preferencesService.getFilePreferences(), preferencesService.getAiPreferences());
1078+
PdfIndexer pdfIndexer = PdfIndexerManager.getIndexer(bibDatabaseContext, preferencesService.getFilePreferences());
10681079
indexingTaskManager.addToIndex(pdfIndexer, addedEntryEvent.getBibEntries());
10691080
} catch (IOException e) {
10701081
LOGGER.error("Cannot access lucene index", e);
@@ -1076,7 +1087,7 @@ public void listen(EntriesAddedEvent addedEntryEvent) {
10761087
public void listen(EntriesRemovedEvent removedEntriesEvent) {
10771088
if (preferencesService.getFilePreferences().shouldFulltextIndexLinkedFiles()) {
10781089
try {
1079-
PdfIndexer pdfIndexer = PdfIndexerManager.getIndexer(bibDatabaseContext, preferencesService.getFilePreferences(), preferencesService.getAiPreferences());
1090+
PdfIndexer pdfIndexer = PdfIndexerManager.getIndexer(bibDatabaseContext, preferencesService.getFilePreferences());
10801091
for (BibEntry removedEntry : removedEntriesEvent.getBibEntries()) {
10811092
indexingTaskManager.removeFromIndex(pdfIndexer, removedEntry);
10821093
}
@@ -1099,7 +1110,7 @@ public void listen(FieldChangedEvent fieldChangedEvent) {
10991110
removedFiles.removeAll(newFileList);
11001111

11011112
try {
1102-
PdfIndexer indexer = PdfIndexerManager.getIndexer(bibDatabaseContext, preferencesService.getFilePreferences(), preferencesService.getAiPreferences());
1113+
PdfIndexer indexer = PdfIndexerManager.getIndexer(bibDatabaseContext, preferencesService.getFilePreferences());
11031114
indexingTaskManager.addToIndex(indexer, fieldChangedEvent.getBibEntry(), addedFiles);
11041115
indexingTaskManager.removeFromIndex(indexer, removedFiles);
11051116
} catch (IOException e) {
@@ -1114,6 +1125,44 @@ public IndexingTaskManager getIndexingTaskManager() {
11141125
return indexingTaskManager;
11151126
}
11161127

1128+
private class EmbeddingsUpdateListener {
1129+
@Subscribe
1130+
public void listen(EntriesAddedEvent event) {
1131+
if (preferencesService.getAiPreferences().getEnableChatWithFiles()) {
1132+
embeddingsGenerationTaskManager.addToProcess(event.getBibEntries());
1133+
}
1134+
}
1135+
1136+
@Subscribe
1137+
public void listen(EntriesRemovedEvent event) {
1138+
if (preferencesService.getAiPreferences().getEnableChatWithFiles()) {
1139+
embeddingsGenerationTaskManager.removeFromProcess(event.getBibEntries());
1140+
}
1141+
}
1142+
1143+
@Subscribe
1144+
public void listen(FieldChangedEvent event) {
1145+
if (preferencesService.getAiPreferences().getEnableChatWithFiles()) {
1146+
if (event.getField().equals(StandardField.FILE)) {
1147+
List<LinkedFile> oldFileList = FileFieldParser.parse(event.getOldValue());
1148+
List<LinkedFile> newFileList = FileFieldParser.parse(event.getNewValue());
1149+
1150+
List<LinkedFile> addedFiles = new ArrayList<>(newFileList);
1151+
addedFiles.removeAll(oldFileList);
1152+
List<LinkedFile> removedFiles = new ArrayList<>(oldFileList);
1153+
removedFiles.removeAll(newFileList);
1154+
1155+
embeddingsGenerationTaskManager.addToProcess(addedFiles);
1156+
embeddingsGenerationTaskManager.removeFromProcess(removedFiles);
1157+
}
1158+
}
1159+
}
1160+
}
1161+
1162+
public EmbeddingsGenerationTaskManager getEmbeddingsGenerationTaskManager() {
1163+
return embeddingsGenerationTaskManager;
1164+
}
1165+
11171166
public static class DatabaseNotification extends NotificationPane {
11181167
public DatabaseNotification(Node content) {
11191168
super(content);

src/main/java/org/jabref/gui/actions/StandardActions.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,9 @@ public enum StandardActions implements Action {
197197
GROUP_SUBGROUP_SORT_ENTRIES(Localization.lang("Sort subgroups by # of entries (Descending)")),
198198
GROUP_SUBGROUP_SORT_ENTRIES_REVERSE(Localization.lang("Sort subgroups by # of entries (Ascending)")),
199199
GROUP_ENTRIES_ADD(Localization.lang("Add selected entries to this group")),
200-
GROUP_ENTRIES_REMOVE(Localization.lang("Remove selected entries from this group"));
200+
GROUP_ENTRIES_REMOVE(Localization.lang("Remove selected entries from this group")),
201+
202+
REGENERATE_EMBEDDINGS_CACHE(Localization.lang("Regenerate embeddings cache"));
201203

202204
private String text;
203205
private final String description;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package org.jabref.gui.ai;
2+
3+
import org.jabref.gui.DialogService;
4+
import org.jabref.gui.LibraryTab;
5+
import org.jabref.gui.StateManager;
6+
import org.jabref.gui.actions.SimpleCommand;
7+
import org.jabref.gui.util.BackgroundTask;
8+
import org.jabref.gui.util.TaskExecutor;
9+
import org.jabref.logic.l10n.Localization;
10+
11+
import static org.jabref.gui.actions.ActionHelper.needsDatabase;
12+
13+
public class RegenerateEmbeddingsAction extends SimpleCommand {
14+
private final StateManager stateManager;
15+
private final GetCurrentLibraryTab currentLibraryTab;
16+
private final DialogService dialogService;
17+
private final TaskExecutor taskExecutor;
18+
19+
private boolean shouldContinue = true;
20+
21+
public RegenerateEmbeddingsAction(StateManager stateManager,
22+
GetCurrentLibraryTab currentLibraryTab,
23+
DialogService dialogService,
24+
TaskExecutor taskExecutor) {
25+
this.stateManager = stateManager;
26+
this.currentLibraryTab = currentLibraryTab;
27+
this.dialogService = dialogService;
28+
this.taskExecutor = taskExecutor;
29+
30+
this.executable.bind(needsDatabase(stateManager));
31+
}
32+
33+
@Override
34+
public void execute() {
35+
init();
36+
BackgroundTask.wrap(this::rebuildIndex)
37+
.executeWith(taskExecutor);
38+
}
39+
40+
public void init() {
41+
if (stateManager.getActiveDatabase().isEmpty()) {
42+
return;
43+
}
44+
45+
boolean confirm = dialogService.showConfirmationDialogAndWait(
46+
Localization.lang("Regenerate embeddings cache"),
47+
Localization.lang("Regenerate embeddings cache for current library?"));
48+
49+
if (!confirm) {
50+
shouldContinue = false;
51+
return;
52+
}
53+
54+
dialogService.notify(Localization.lang("Regenerating embeddings cache..."));
55+
}
56+
57+
private void rebuildIndex() {
58+
if (!shouldContinue || stateManager.getActiveDatabase().isEmpty()) {
59+
return;
60+
}
61+
62+
currentLibraryTab.get().getEmbeddingsGenerationTaskManager().invalidate();
63+
}
64+
65+
public interface GetCurrentLibraryTab {
66+
LibraryTab get();
67+
}
68+
}

src/main/java/org/jabref/gui/entryeditor/aichattab/components/aichat/AiChatComponent.fxml renamed to src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.fxml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<?import javafx.scene.layout.*?>
66
<?import javafx.scene.text.*?>
77

8-
<fx:root spacing="10.0" type="javafx.scene.layout.VBox" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.entryeditor.aichattab.components.aichat.AiChatComponent">
8+
<fx:root spacing="10.0" type="javafx.scene.layout.VBox" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.ai.components.aichat.AiChatComponent">
99
<padding>
1010
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
1111
</padding>

src/main/java/org/jabref/gui/entryeditor/aichattab/components/aichat/AiChatComponent.java renamed to src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
1-
package org.jabref.gui.entryeditor.aichattab.components.aichat;
1+
package org.jabref.gui.ai.components.aichat;
22

33
import java.util.function.Consumer;
44

55
import javafx.application.Platform;
66
import javafx.fxml.FXML;
7-
import javafx.geometry.NodeOrientation;
8-
import javafx.geometry.Pos;
97
import javafx.scene.Node;
10-
import javafx.scene.Parent;
118
import javafx.scene.control.Button;
129
import javafx.scene.control.ProgressIndicator;
1310
import javafx.scene.control.TextField;
1411
import javafx.scene.layout.BorderPane;
15-
import javafx.scene.layout.HBox;
1612
import javafx.scene.layout.VBox;
1713

18-
import org.jabref.gui.entryeditor.aichattab.components.chatmessage.ChatMessageComponent;
19-
import org.jabref.logic.ai.ChatMessage;
14+
import org.jabref.gui.ai.components.chatmessage.ChatMessageComponent;
15+
import org.jabref.logic.ai.chathistory.ChatMessage;
2016

2117
import com.airhacks.afterburner.views.ViewLoader;
2218

src/main/java/org/jabref/gui/entryeditor/aichattab/components/chatmessage/ChatMessageComponent.fxml renamed to src/main/java/org/jabref/gui/ai/components/chatmessage/ChatMessageComponent.fxml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<?import javafx.scene.layout.*?>
66
<?import javafx.scene.text.*?>
77

8-
<fx:root nodeOrientation="LEFT_TO_RIGHT" type="javafx.scene.layout.Pane" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.entryeditor.aichattab.components.chatmessage.ChatMessageComponent">
8+
<fx:root nodeOrientation="LEFT_TO_RIGHT" type="javafx.scene.layout.Pane" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.ai.components.chatmessage.ChatMessageComponent">
99
<children>
1010
<VBox fx:id="vBox" maxWidth="500.0" spacing="10.0">
1111
<padding>

src/main/java/org/jabref/gui/entryeditor/aichattab/components/chatmessage/ChatMessageComponent.java renamed to src/main/java/org/jabref/gui/ai/components/chatmessage/ChatMessageComponent.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
package org.jabref.gui.entryeditor.aichattab.components.chatmessage;
2-
3-
import java.io.IOException;
1+
package org.jabref.gui.ai.components.chatmessage;
42

53
import javafx.fxml.FXML;
6-
import javafx.fxml.FXMLLoader;
74
import javafx.geometry.NodeOrientation;
8-
import javafx.geometry.Pos;
95
import javafx.scene.control.Label;
106
import javafx.scene.control.TextArea;
117
import javafx.scene.layout.HBox;
12-
import javafx.scene.layout.Pane;
13-
import javafx.scene.layout.Priority;
148
import javafx.scene.layout.VBox;
159

16-
import org.jabref.logic.ai.ChatMessage;
10+
import org.jabref.logic.ai.chathistory.ChatMessage;
1711
import org.jabref.logic.l10n.Localization;
1812

1913
import com.airhacks.afterburner.views.ViewLoader;

src/main/java/org/jabref/gui/entryeditor/aichattab/components/errorstate/ErrorStateComponent.fxml renamed to src/main/java/org/jabref/gui/ai/components/errorstate/ErrorStateComponent.fxml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<?import javafx.scene.layout.*?>
66
<?import javafx.scene.text.*?>
77

8-
<fx:root prefHeight="200.0" prefWidth="500.0" type="BorderPane" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.entryeditor.aichattab.components.errorstate.ErrorStateComponent">
8+
<fx:root prefHeight="200.0" prefWidth="500.0" type="BorderPane" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.ai.components.errorstate.ErrorStateComponent">
99
<center>
1010
<VBox alignment="CENTER" spacing="10.0">
1111
<children>

0 commit comments

Comments
 (0)