Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
# 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
  • Loading branch information
InAnYan committed Jul 19, 2024
2 parents 120cbb0 + 302dbce commit d684919
Show file tree
Hide file tree
Showing 89 changed files with 3,595 additions and 40 deletions.
50 changes: 49 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ version = project.findProperty('projVersion') ?: '100.0.0'
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21

// Workaround needed for Eclipse, probably because of https://github.com/gradle/gradle/issues/16922
// Should be removed as soon as Gradle 7.0.1 is released ( https://github.com/gradle/gradle/issues/16922#issuecomment-828217060 )
modularity.inferModulePath.set(false)
Expand Down Expand Up @@ -97,6 +98,13 @@ application {
// See also https://github.com/java9-modularity/gradle-modules-plugin/issues/165
modularity.disableEffectiveArgumentsAdjustment()

// Required as workaround for https://github.com/langchain4j/langchain4j/issues/1066
modularity.patchModule("langchain4j", "langchain4j-core-0.31.0.jar")
modularity.patchModule("langchain4j", "langchain4j-embeddings-0.31.0.jar")
modularity.patchModule("langchain4j", "langchain4j-embeddings-all-minilm-l6-v2-0.31.0.jar")
modularity.patchModule("langchain4j", "langchain4j-embeddings-all-minilm-l6-v2-q-0.31.0.jar")
modularity.patchModule("langchain4j", "langchain4j-open-ai-0.31.0.jar")

sourceSets {
main {
java {
Expand Down Expand Up @@ -231,12 +239,17 @@ dependencies {
exclude module: 'commons-lang3'
exclude group: 'org.apache.commons.validator'
exclude group: 'org.apache.commons.commons-logging'
exclude module: 'kotlin-stdlib-jdk8'
exclude group: 'com.squareup.retrofit2'
exclude group: 'org.openjfx'
exclude group: 'org.apache.logging.log4j'
exclude group: 'tech.units'
}
// Required by gemsfx
implementation 'tech.units:indriya:2.2'
implementation ('com.squareup.retrofit2:retrofit:2.11.0') {
exclude group: 'com.squareup.okhttp3'
}

implementation 'org.controlsfx:controlsfx:11.2.1'

Expand Down Expand Up @@ -308,6 +321,23 @@ dependencies {
// YAML formatting
implementation 'org.yaml:snakeyaml:2.2'

// AI
implementation 'dev.langchain4j:langchain4j:0.31.0'
implementation 'dev.langchain4j:langchain4j-embeddings-all-minilm-l6-v2:0.31.0'
implementation 'dev.langchain4j:langchain4j-embeddings-all-minilm-l6-v2-q:0.31.0'
implementation('dev.langchain4j:langchain4j-open-ai:0.31.0') {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}
// openai depends on okhttp, which needs kotlin - see https://github.com/square/okhttp/issues/5299 for details
// GemxFX also (transitively) depends on kotlin
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.24'

implementation "one.jpro.platform:jpro-mdfx:0.3.3-SNAPSHOT"

implementation ('com.squareup.okhttp3:okhttp:4.12.0') {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}

implementation 'commons-io:commons-io:2.16.1'

testImplementation 'io.github.classgraph:classgraph:4.8.174'
Expand Down Expand Up @@ -451,7 +481,22 @@ compileJava {
// TODO: Remove access to internal api
addExports = [
'javafx.controls/com.sun.javafx.scene.control' : 'org.jabref',
'org.controlsfx.controls/impl.org.controlsfx.skin' : 'org.jabref'
'org.controlsfx.controls/impl.org.controlsfx.skin' : 'org.jabref',

'langchain4j/dev.langchain4j.data.document' : 'org.jabref',
'langchain4j/dev.langchain4j.data.segment' : 'org.jabref',
'langchain4j/dev.langchain4j.model.chat' : 'org.jabref',
'langchain4j/dev.langchain4j.model.embedding' : 'org.jabref',
'langchain4j/dev.langchain4j.model.openai' : 'org.jabref',
'langchain4j/dev.langchain4j.rag.content.retriever' : 'org.jabref',
'langchain4j/dev.langchain4j.store.embedding' : 'org.jabref',
'langchain4j/dev.langchain4j.store.embedding.inmemory' : 'org.jabref',
'langchain4j/dev.langchain4j.memory' : 'org.jabref',
'langchain4j/dev.langchain4j.store.memory.chat' : 'org.jabref',
'langchain4j/dev.langchain4j.data.message' : 'org.jabref',
'langchain4j/dev.langchain4j.store.embedding.filter' : 'org.jabref',
'langchain4j/dev.langchain4j.store.embedding.filter.comparison' : 'org.jabref',
'langchain4j/dev.langchain4j.data.embedding' : 'org.jabref',
]
}
}
Expand All @@ -470,6 +515,9 @@ run {
'javafx.base/com.sun.javafx.event' : 'org.jabref.merged.module',
'javafx.controls/com.sun.javafx.scene.control' : 'org.jabref',

'langchain4j/dev.langchain4j.model.chat' : 'org.jabref',
'langchain4j/dev.langchain4j.model.chat' : 'org.jabref.merged.module',

// We need to restate the ControlsFX exports, because we get following error otherwise:
// java.lang.IllegalAccessError:
// class org.controlsfx.control.textfield.AutoCompletionBinding (in module org.controlsfx.controls)
Expand Down
61 changes: 61 additions & 0 deletions docs/decisions/0031-store-chats-alongside-database.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
nav_order: 0031
parent: Decision Records
---
<!-- markdownlint-disable-next-line MD025 -->
# Store chats alongside database

## Context and Problem Statement

Chats with AI should be stored somewhere. But where and how?

## Considered Options

* Inside `.bib` file
* In local user folder
* Alongside `.bib` file

## Decision Outcome

Chosen option: "Alongside `.bib` file", because
simple to implement and gives the user the ability to share or not to share the chats.

### Positive Consequences

* Simple implementation
* The user can send the chats file alongside the `.bib` file if they want to share the chats. If users do not want
to share the messages, then they can omit the chats file
* `.bib` files is kept clean

### Negative Consequences

* User may not expect that a new file will be created alongside their `.bib` (or other LaTeX-related) files
* It may be not convenient to share both files (`.bib` file and chats file) in order to share chat history.
* If `.bib` files are edited externally (meaning, not inside the JabRef), then chats file will not be updated correspondingly
* If user moves `.bib` file, they should move the chats file too

## Pros and Cons of the Options

### Inside `.bib` file

* Good, because we already have a machinery for managing the fields and other information of BIB entries
* Good, because chats are stored inside one file, and if the `.bib` file is moved, the chat history is preserved
* 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
* Bad, because if user shares a `.bib` file, they will also share chat messages, but chats are not ideal, so user may not
want to share them

### In local user folder

One can use `%APPDATA%`, where JabRef stores the Lucene index and other information.
See `org.jabref.gui.desktop.os.NativeDesktop#getFulltextIndexBaseDirectory` for use in JabRef and
<https://github.com/harawata/appdirs> for general information.

* Good, because `.bib` file is kept clean
* Good, because chat messages are saved locally
* Neutral, because may be a little harder to implement
* Bad, because chat messages cannot be easily shared
* Bad, because when path of a `.bib` file is changed, the chats are lost

### Alongside `.bib` file

Refer to positive and negative consequences of the decision outcome.
49 changes: 49 additions & 0 deletions docs/decisions/0032-store-chats-in-mvstore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
nav_order: 0032
parent: Decision Records
---
# Store chats in MVStore

## Context and Problem Statement

This is a follow-up to [ADR-031](0031-store-chats-alongside-database.md).

The chats with AI should be saved on exit from JabRef and retrieved on launch. We need to decide the format of
the serialized messages.

## Decision Drivers

* Easy to implement and maintain
* Memory-efficient (because JabRef is said to consume much memory)

## Considered Options

* JSON
* MVStore
* Custom format

## Decision Outcome

Chosen option: "MVStore", because it is simple and memory-efficient.

## Pros and Cons of the Options

### JSON

* Good, because allows for easy storing and loading of chats
* Good, because cross-platform
* Good, because widely used and accepted, so there are lots of libraries for JSON format
* Good, because it is even possible to reuse the chats file for other purposes
* Bad, because too verbose (meaning the file size could be much smaller)

### MVStore

* Good, because automatic loading and saving to disk
* Good, because memory-efficient
* Bad, because the order of messages need to be "hand-crafted" (e.g., by mapping from an Integer to the concrete message)

### Custom format

* Good, because we have the full control
* Bad, because involves writing our own language and parser
* Bad, because we need to implement optimizations found in databases on our own (storing some data in RAM, other on disk)
69 changes: 69 additions & 0 deletions docs/decisions/0033-use-citation-key-for-grouping-chat-messages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
nav_order: 0033
parent: Decision Records
---
<!-- markdownlint-disable-next-line MD025 -->
# Use citation key for grouping chat messages

## Context and Problem Statement

Because we store chat messages not inside a BIB entry in `.bib` filecc, the chats file is represented as a map to
BIB entry and a list of messages. We need to specify the key of this map. Turns out, it is not that easy.

## Decision Drivers

* The key should exist for every BIB entry
* The key should be unique along other BIB entries in one library file
* The key should not change at run-time, between launches of JabRef, and should be cross-platform (most important)

## Considered Options

* `BibEntry` Java object
* `BibEntry` ID
* Citation key
* Use `ShareId`

## Decision Outcome

Chosen option: "Citation key", because this is the only choice that complains to the third point in Decision Drivers.

### Positive Consequences

* Easy to implement
* Cross-platform

### Negative Consequences

* If the citation key is changed externally, then the chats file becomes out-of-sync
* Additional user interaction in order to make the citation key complain the first and second points of Decision Drivers

## Pros and Cons of the Options

### `BibEntry` Java object

Very bad, because it works only at run-time and is not stable.

### `BibEntry` ID

JabRef stores a unique identifier for each BibEntry.
This identifier is created on each load of a library (and not stored permanently).

Very bad, for the same reasons as `BibEntry` Java object.

### Citation key

* Good, because it is cross-platform, stable (meaning stays the same across launches of JabRef)
* Bad, because it is not guaranteed that citation key exists on BIB entry, and that it is unique across other
BIB entries in the library

### Use `ShareId`

[ADR-0027](0027-synchronization.md) describes the procedure of synchronization of a Bib(La)TeX library with a server.
Thereby, also local and remote entries need to be kept consistent.
The solution chosen there is that the **server** creates a UUID for each entry.

This approach cannot be used here, because there is no server running which we can ask for an UUID of an entry.

## More Information

Refer to [issue #160](https://github.com/JabRef/jabref/issues/160) in JabRef main repository
84 changes: 84 additions & 0 deletions docs/decisions/0034-use-textarea-for-chat-content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
nav_order: 0034
parent: Decision Records
---
<!-- markdownlint-disable-next-line MD025 -->
# Use TextArea for chat message content

## Context and Problem Statement

This decision record concerns the UI component that is used for rendering the content of chat messages.

## Decision Drivers

* Looks good (renders Markdown)
* Can select and copy text
* Have good performance

## Considered Options

* Use TextArea
* Use a [third-party package](https://github.com/JPro-one/jpro-platform)
* Use a Markdown parser and convert AST nodes to JavaFX TextFlow elements
* Use a Markdown parser to convert content into HTML and use a WebView for one message
* Use a Markdown parser and WebView for the whole chat history

## Decision Outcome

Chosen option: "Use TextArea".
All other options require some time to implement.
Some of the options doesn't support text selection and copying,
which for now we value better than Markdown rendering.

## Pros and Cons of the Options

### Use TextArea

* Good, because it is easy to implement
* Good, because it supports text selection and copying
* Bad, because it cannot render Markdown
* Bad, because default JavaFX's `TextArea` shrinks

### Use a third-party package

There seems to be only one package for JavaFX that provides a ready-to-use UI node for Markdown rendering.

* Good, because it is easy to implement
* Good, because it renders Markdown
* Good, because it renders Markdown to JavaFX nodes (does not use a `WebView`)
* Good, because complex elements from Markdown are supported (tables, code blocks, etc.)
* Bad, because it has very strange issues and architectural flaws with styling
* Bad, because it does not support text selection and copying (because of underlying JavaFX `Text` nodes)

### Use a Markdown parser and convert AST nodes to JavaFX TextFlow elements

* Good, because we will support Markdown
* Good, because no need to write a Markdown parser from scratch
* Good, because does not use a WebView
* Good, because easy styling
* Bad, because we need some time to implement Markdown AST -> JavaFX nodes converter
* Bad, because rendering tables and code blocks may be hard
* Bad, because it will not support text selection and copying

### Use a Markdown parser to convert content into HTML and use a WebView for one message

* Good, because there are libraries to convert Markdown to HTML
* Good, because may be easier to implement than other choices (except `TextArea`)
* Good, because it supports text selection and copying
* Bad, because it may be a problem to connect JavaFX CSS to `WebView`
* Bad, because one `WebView` for one message is resourceful

### Use a Markdown parser and WebView for the whole chat history

* Good, because there are libraries to convert Markdown to HTML
* Good, because it supports text selection and copying
* Bad, because it may be a problem to connect JavaFX CSS to `WebView`
* Bad, because it may be a problem to correctly communicate with Java code and `WebView` to add new messages

## More Information

Actually we used an `ExpandingTextArea` from `GemsFX` package so the content can occupy
as much space as it needs in the `ScrollPane`.

About the selection and copying, this goes down to fundamental issue from JavaFX.
`Text` and `Label` cannot be selected by any means.
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pluginManagement {
}

plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}

rootProject.name = "JabRef"
9 changes: 9 additions & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@

requires org.jooq.jool;

// AI
requires langchain4j;
requires kotlin.stdlib;

// fulltext search
requires org.apache.lucene.core;
// In case the version is updated, please also adapt SearchFieldConstants#VERSION to the newly used version
Expand Down Expand Up @@ -150,4 +154,9 @@
requires dd.plist;
requires mslinks;
requires org.apache.httpcomponents.core5.httpcore5;
requires com.dlsc.unitfx;
requires org.checkerframework.checker.qual;
requires jakarta.validation;
requires one.jpro.platform.mdfx;
requires scala.library;
}
Loading

0 comments on commit d684919

Please sign in to comment.