Skip to content

Commit d684919

Browse files
committed
Merge remote-tracking branch 'origin/main'
# Conflicts: # src/main/java/org/jabref/gui/entryeditor/DeprecatedFieldsTab.java # src/main/java/org/jabref/gui/entryeditor/EntryEditor.java # src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java # src/main/java/org/jabref/gui/entryeditor/UserDefinedFieldsTab.java # src/main/java/org/jabref/preferences/JabRefPreferences.java # src/main/java/org/jabref/preferences/PreferencesService.java # src/main/resources/l10n/JabRef_en.properties
2 parents 120cbb0 + 302dbce commit d684919

File tree

89 files changed

+3595
-40
lines changed

Some content is hidden

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

89 files changed

+3595
-40
lines changed

build.gradle

+49-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ version = project.findProperty('projVersion') ?: '100.0.0'
4545
java {
4646
sourceCompatibility = JavaVersion.VERSION_21
4747
targetCompatibility = JavaVersion.VERSION_21
48+
4849
// Workaround needed for Eclipse, probably because of https://github.com/gradle/gradle/issues/16922
4950
// Should be removed as soon as Gradle 7.0.1 is released ( https://github.com/gradle/gradle/issues/16922#issuecomment-828217060 )
5051
modularity.inferModulePath.set(false)
@@ -97,6 +98,13 @@ application {
9798
// See also https://github.com/java9-modularity/gradle-modules-plugin/issues/165
9899
modularity.disableEffectiveArgumentsAdjustment()
99100

101+
// Required as workaround for https://github.com/langchain4j/langchain4j/issues/1066
102+
modularity.patchModule("langchain4j", "langchain4j-core-0.31.0.jar")
103+
modularity.patchModule("langchain4j", "langchain4j-embeddings-0.31.0.jar")
104+
modularity.patchModule("langchain4j", "langchain4j-embeddings-all-minilm-l6-v2-0.31.0.jar")
105+
modularity.patchModule("langchain4j", "langchain4j-embeddings-all-minilm-l6-v2-q-0.31.0.jar")
106+
modularity.patchModule("langchain4j", "langchain4j-open-ai-0.31.0.jar")
107+
100108
sourceSets {
101109
main {
102110
java {
@@ -231,12 +239,17 @@ dependencies {
231239
exclude module: 'commons-lang3'
232240
exclude group: 'org.apache.commons.validator'
233241
exclude group: 'org.apache.commons.commons-logging'
242+
exclude module: 'kotlin-stdlib-jdk8'
243+
exclude group: 'com.squareup.retrofit2'
234244
exclude group: 'org.openjfx'
235245
exclude group: 'org.apache.logging.log4j'
236246
exclude group: 'tech.units'
237247
}
238248
// Required by gemsfx
239249
implementation 'tech.units:indriya:2.2'
250+
implementation ('com.squareup.retrofit2:retrofit:2.11.0') {
251+
exclude group: 'com.squareup.okhttp3'
252+
}
240253

241254
implementation 'org.controlsfx:controlsfx:11.2.1'
242255

@@ -308,6 +321,23 @@ dependencies {
308321
// YAML formatting
309322
implementation 'org.yaml:snakeyaml:2.2'
310323

324+
// AI
325+
implementation 'dev.langchain4j:langchain4j:0.31.0'
326+
implementation 'dev.langchain4j:langchain4j-embeddings-all-minilm-l6-v2:0.31.0'
327+
implementation 'dev.langchain4j:langchain4j-embeddings-all-minilm-l6-v2-q:0.31.0'
328+
implementation('dev.langchain4j:langchain4j-open-ai:0.31.0') {
329+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
330+
}
331+
// openai depends on okhttp, which needs kotlin - see https://github.com/square/okhttp/issues/5299 for details
332+
// GemxFX also (transitively) depends on kotlin
333+
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.24'
334+
335+
implementation "one.jpro.platform:jpro-mdfx:0.3.3-SNAPSHOT"
336+
337+
implementation ('com.squareup.okhttp3:okhttp:4.12.0') {
338+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
339+
}
340+
311341
implementation 'commons-io:commons-io:2.16.1'
312342

313343
testImplementation 'io.github.classgraph:classgraph:4.8.174'
@@ -451,7 +481,22 @@ compileJava {
451481
// TODO: Remove access to internal api
452482
addExports = [
453483
'javafx.controls/com.sun.javafx.scene.control' : 'org.jabref',
454-
'org.controlsfx.controls/impl.org.controlsfx.skin' : 'org.jabref'
484+
'org.controlsfx.controls/impl.org.controlsfx.skin' : 'org.jabref',
485+
486+
'langchain4j/dev.langchain4j.data.document' : 'org.jabref',
487+
'langchain4j/dev.langchain4j.data.segment' : 'org.jabref',
488+
'langchain4j/dev.langchain4j.model.chat' : 'org.jabref',
489+
'langchain4j/dev.langchain4j.model.embedding' : 'org.jabref',
490+
'langchain4j/dev.langchain4j.model.openai' : 'org.jabref',
491+
'langchain4j/dev.langchain4j.rag.content.retriever' : 'org.jabref',
492+
'langchain4j/dev.langchain4j.store.embedding' : 'org.jabref',
493+
'langchain4j/dev.langchain4j.store.embedding.inmemory' : 'org.jabref',
494+
'langchain4j/dev.langchain4j.memory' : 'org.jabref',
495+
'langchain4j/dev.langchain4j.store.memory.chat' : 'org.jabref',
496+
'langchain4j/dev.langchain4j.data.message' : 'org.jabref',
497+
'langchain4j/dev.langchain4j.store.embedding.filter' : 'org.jabref',
498+
'langchain4j/dev.langchain4j.store.embedding.filter.comparison' : 'org.jabref',
499+
'langchain4j/dev.langchain4j.data.embedding' : 'org.jabref',
455500
]
456501
}
457502
}
@@ -470,6 +515,9 @@ run {
470515
'javafx.base/com.sun.javafx.event' : 'org.jabref.merged.module',
471516
'javafx.controls/com.sun.javafx.scene.control' : 'org.jabref',
472517

518+
'langchain4j/dev.langchain4j.model.chat' : 'org.jabref',
519+
'langchain4j/dev.langchain4j.model.chat' : 'org.jabref.merged.module',
520+
473521
// We need to restate the ControlsFX exports, because we get following error otherwise:
474522
// java.lang.IllegalAccessError:
475523
// class org.controlsfx.control.textfield.AutoCompletionBinding (in module org.controlsfx.controls)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
nav_order: 0031
3+
parent: Decision Records
4+
---
5+
<!-- markdownlint-disable-next-line MD025 -->
6+
# Store chats alongside database
7+
8+
## Context and Problem Statement
9+
10+
Chats with AI should be stored somewhere. But where and how?
11+
12+
## Considered Options
13+
14+
* Inside `.bib` file
15+
* In local user folder
16+
* Alongside `.bib` file
17+
18+
## Decision Outcome
19+
20+
Chosen option: "Alongside `.bib` file", because
21+
simple to implement and gives the user the ability to share or not to share the chats.
22+
23+
### Positive Consequences
24+
25+
* Simple implementation
26+
* The user can send the chats file alongside the `.bib` file if they want to share the chats. If users do not want
27+
to share the messages, then they can omit the chats file
28+
* `.bib` files is kept clean
29+
30+
### Negative Consequences
31+
32+
* User may not expect that a new file will be created alongside their `.bib` (or other LaTeX-related) files
33+
* It may be not convenient to share both files (`.bib` file and chats file) in order to share chat history.
34+
* If `.bib` files are edited externally (meaning, not inside the JabRef), then chats file will not be updated correspondingly
35+
* If user moves `.bib` file, they should move the chats file too
36+
37+
## Pros and Cons of the Options
38+
39+
### Inside `.bib` file
40+
41+
* Good, because we already have a machinery for managing the fields and other information of BIB entries
42+
* Good, because chats are stored inside one file, and if the `.bib` file is moved, the chat history is preserved
43+
* Bad, because there may be lots of chats and messages and `.bib` file become too cluttered and too big which slows down the processing of `.bib` file
44+
* Bad, because if user shares a `.bib` file, they will also share chat messages, but chats are not ideal, so user may not
45+
want to share them
46+
47+
### In local user folder
48+
49+
One can use `%APPDATA%`, where JabRef stores the Lucene index and other information.
50+
See `org.jabref.gui.desktop.os.NativeDesktop#getFulltextIndexBaseDirectory` for use in JabRef and
51+
<https://github.com/harawata/appdirs> for general information.
52+
53+
* Good, because `.bib` file is kept clean
54+
* Good, because chat messages are saved locally
55+
* Neutral, because may be a little harder to implement
56+
* Bad, because chat messages cannot be easily shared
57+
* Bad, because when path of a `.bib` file is changed, the chats are lost
58+
59+
### Alongside `.bib` file
60+
61+
Refer to positive and negative consequences of the decision outcome.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
nav_order: 0032
3+
parent: Decision Records
4+
---
5+
# Store chats in MVStore
6+
7+
## Context and Problem Statement
8+
9+
This is a follow-up to [ADR-031](0031-store-chats-alongside-database.md).
10+
11+
The chats with AI should be saved on exit from JabRef and retrieved on launch. We need to decide the format of
12+
the serialized messages.
13+
14+
## Decision Drivers
15+
16+
* Easy to implement and maintain
17+
* Memory-efficient (because JabRef is said to consume much memory)
18+
19+
## Considered Options
20+
21+
* JSON
22+
* MVStore
23+
* Custom format
24+
25+
## Decision Outcome
26+
27+
Chosen option: "MVStore", because it is simple and memory-efficient.
28+
29+
## Pros and Cons of the Options
30+
31+
### JSON
32+
33+
* Good, because allows for easy storing and loading of chats
34+
* Good, because cross-platform
35+
* Good, because widely used and accepted, so there are lots of libraries for JSON format
36+
* Good, because it is even possible to reuse the chats file for other purposes
37+
* Bad, because too verbose (meaning the file size could be much smaller)
38+
39+
### MVStore
40+
41+
* Good, because automatic loading and saving to disk
42+
* Good, because memory-efficient
43+
* Bad, because the order of messages need to be "hand-crafted" (e.g., by mapping from an Integer to the concrete message)
44+
45+
### Custom format
46+
47+
* Good, because we have the full control
48+
* Bad, because involves writing our own language and parser
49+
* Bad, because we need to implement optimizations found in databases on our own (storing some data in RAM, other on disk)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
nav_order: 0033
3+
parent: Decision Records
4+
---
5+
<!-- markdownlint-disable-next-line MD025 -->
6+
# Use citation key for grouping chat messages
7+
8+
## Context and Problem Statement
9+
10+
Because we store chat messages not inside a BIB entry in `.bib` filecc, the chats file is represented as a map to
11+
BIB entry and a list of messages. We need to specify the key of this map. Turns out, it is not that easy.
12+
13+
## Decision Drivers
14+
15+
* The key should exist for every BIB entry
16+
* The key should be unique along other BIB entries in one library file
17+
* The key should not change at run-time, between launches of JabRef, and should be cross-platform (most important)
18+
19+
## Considered Options
20+
21+
* `BibEntry` Java object
22+
* `BibEntry` ID
23+
* Citation key
24+
* Use `ShareId`
25+
26+
## Decision Outcome
27+
28+
Chosen option: "Citation key", because this is the only choice that complains to the third point in Decision Drivers.
29+
30+
### Positive Consequences
31+
32+
* Easy to implement
33+
* Cross-platform
34+
35+
### Negative Consequences
36+
37+
* If the citation key is changed externally, then the chats file becomes out-of-sync
38+
* Additional user interaction in order to make the citation key complain the first and second points of Decision Drivers
39+
40+
## Pros and Cons of the Options
41+
42+
### `BibEntry` Java object
43+
44+
Very bad, because it works only at run-time and is not stable.
45+
46+
### `BibEntry` ID
47+
48+
JabRef stores a unique identifier for each BibEntry.
49+
This identifier is created on each load of a library (and not stored permanently).
50+
51+
Very bad, for the same reasons as `BibEntry` Java object.
52+
53+
### Citation key
54+
55+
* Good, because it is cross-platform, stable (meaning stays the same across launches of JabRef)
56+
* Bad, because it is not guaranteed that citation key exists on BIB entry, and that it is unique across other
57+
BIB entries in the library
58+
59+
### Use `ShareId`
60+
61+
[ADR-0027](0027-synchronization.md) describes the procedure of synchronization of a Bib(La)TeX library with a server.
62+
Thereby, also local and remote entries need to be kept consistent.
63+
The solution chosen there is that the **server** creates a UUID for each entry.
64+
65+
This approach cannot be used here, because there is no server running which we can ask for an UUID of an entry.
66+
67+
## More Information
68+
69+
Refer to [issue #160](https://github.com/JabRef/jabref/issues/160) in JabRef main repository
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
nav_order: 0034
3+
parent: Decision Records
4+
---
5+
<!-- markdownlint-disable-next-line MD025 -->
6+
# Use TextArea for chat message content
7+
8+
## Context and Problem Statement
9+
10+
This decision record concerns the UI component that is used for rendering the content of chat messages.
11+
12+
## Decision Drivers
13+
14+
* Looks good (renders Markdown)
15+
* Can select and copy text
16+
* Have good performance
17+
18+
## Considered Options
19+
20+
* Use TextArea
21+
* Use a [third-party package](https://github.com/JPro-one/jpro-platform)
22+
* Use a Markdown parser and convert AST nodes to JavaFX TextFlow elements
23+
* Use a Markdown parser to convert content into HTML and use a WebView for one message
24+
* Use a Markdown parser and WebView for the whole chat history
25+
26+
## Decision Outcome
27+
28+
Chosen option: "Use TextArea".
29+
All other options require some time to implement.
30+
Some of the options doesn't support text selection and copying,
31+
which for now we value better than Markdown rendering.
32+
33+
## Pros and Cons of the Options
34+
35+
### Use TextArea
36+
37+
* Good, because it is easy to implement
38+
* Good, because it supports text selection and copying
39+
* Bad, because it cannot render Markdown
40+
* Bad, because default JavaFX's `TextArea` shrinks
41+
42+
### Use a third-party package
43+
44+
There seems to be only one package for JavaFX that provides a ready-to-use UI node for Markdown rendering.
45+
46+
* Good, because it is easy to implement
47+
* Good, because it renders Markdown
48+
* Good, because it renders Markdown to JavaFX nodes (does not use a `WebView`)
49+
* Good, because complex elements from Markdown are supported (tables, code blocks, etc.)
50+
* Bad, because it has very strange issues and architectural flaws with styling
51+
* Bad, because it does not support text selection and copying (because of underlying JavaFX `Text` nodes)
52+
53+
### Use a Markdown parser and convert AST nodes to JavaFX TextFlow elements
54+
55+
* Good, because we will support Markdown
56+
* Good, because no need to write a Markdown parser from scratch
57+
* Good, because does not use a WebView
58+
* Good, because easy styling
59+
* Bad, because we need some time to implement Markdown AST -> JavaFX nodes converter
60+
* Bad, because rendering tables and code blocks may be hard
61+
* Bad, because it will not support text selection and copying
62+
63+
### Use a Markdown parser to convert content into HTML and use a WebView for one message
64+
65+
* Good, because there are libraries to convert Markdown to HTML
66+
* Good, because may be easier to implement than other choices (except `TextArea`)
67+
* Good, because it supports text selection and copying
68+
* Bad, because it may be a problem to connect JavaFX CSS to `WebView`
69+
* Bad, because one `WebView` for one message is resourceful
70+
71+
### Use a Markdown parser and WebView for the whole chat history
72+
73+
* Good, because there are libraries to convert Markdown to HTML
74+
* Good, because it supports text selection and copying
75+
* Bad, because it may be a problem to connect JavaFX CSS to `WebView`
76+
* Bad, because it may be a problem to correctly communicate with Java code and `WebView` to add new messages
77+
78+
## More Information
79+
80+
Actually we used an `ExpandingTextArea` from `GemsFX` package so the content can occupy
81+
as much space as it needs in the `ScrollPane`.
82+
83+
About the selection and copying, this goes down to fundamental issue from JavaFX.
84+
`Text` and `Label` cannot be selected by any means.

settings.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pluginManagement {
1919
}
2020

2121
plugins {
22-
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
22+
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
2323
}
2424

2525
rootProject.name = "JabRef"

src/main/java/module-info.java

+9
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@
123123

124124
requires org.jooq.jool;
125125

126+
// AI
127+
requires langchain4j;
128+
requires kotlin.stdlib;
129+
126130
// fulltext search
127131
requires org.apache.lucene.core;
128132
// In case the version is updated, please also adapt SearchFieldConstants#VERSION to the newly used version
@@ -150,4 +154,9 @@
150154
requires dd.plist;
151155
requires mslinks;
152156
requires org.apache.httpcomponents.core5.httpcore5;
157+
requires com.dlsc.unitfx;
158+
requires org.checkerframework.checker.qual;
159+
requires jakarta.validation;
160+
requires one.jpro.platform.mdfx;
161+
requires scala.library;
153162
}

0 commit comments

Comments
 (0)