Fix reset and import of AiPreferences#15843
Conversation
Review Summary by QodoRefactor AI preferences initialization and reset handling
WalkthroughsDescription• Refactor AI preferences initialization to use default factory pattern • Remove unused AiProviderDefaultChatModels class and consolidate defaults • Add getDefault() and setAll() methods to AiPreferences for proper reset/import • Simplify preferences loading by delegating to getAiPreferencesFromBackingStore() • Remove hardcoded CONTEXT_WINDOW_SIZE constant from AiDefaultExpertSettings Diagramflowchart LR
A["AiPreferences<br/>with defaults"] -->|"getDefault()"| B["Default instance"]
C["JabRefCliPreferences<br/>clear/import"] -->|"setAll()"| A
D["AiProviderDefaultChatModels<br/>removed"] -->|"consolidate to"| A
E["PredefinedChatModelUtil"] -->|"getContextWindowSize()"| F["Dynamic lookup"]
File Changes1. jablib/src/main/java/org/jabref/logic/ai/chatting/PredefinedChatModelUtil.java
|
Code Review by Qodo
1. setAll loses expert values
|
| this.customizeExpertSettings.set(preferences.getCustomizeExpertSettings()); | ||
|
|
||
| this.openAiApiBaseUrl.set(preferences.getOpenAiApiBaseUrl()); | ||
| this.mistralAiApiBaseUrl.set(preferences.getMistralAiApiBaseUrl()); | ||
| this.geminiApiBaseUrl.set(preferences.getGeminiApiBaseUrl()); | ||
| this.huggingFaceApiBaseUrl.set(preferences.getHuggingFaceApiBaseUrl()); | ||
|
|
||
| this.summarizatorKind.set(preferences.getSummarizatorKind()); | ||
| this.tokenEstimatorKind.set(preferences.getTokenEstimatorKind()); | ||
| this.embeddingModel.set(preferences.getEmbeddingModel()); | ||
| this.temperature.set(preferences.getTemperature()); | ||
| this.contextWindowSize.set(preferences.getContextWindowSize()); | ||
| this.documentSplitterKind.set(preferences.getDocumentSplitterKind()); | ||
| this.documentSplitterChunkSize.set(preferences.getDocumentSplitterChunkSize()); | ||
| this.documentSplitterOverlapSize.set(preferences.getDocumentSplitterOverlapSize()); | ||
| this.answerEngineKind.set(preferences.getAnswerEngineKind()); | ||
| this.ragMaxResultsCount.set(preferences.getRagMaxResultsCount()); | ||
| this.ragMinScore.set(preferences.getRagMinScore()); | ||
| this.chattingSystemMessageTemplate.set(preferences.getChattingSystemMessageTemplate()); |
There was a problem hiding this comment.
1. Setall loses expert values 🐞 Bug ≡ Correctness
AiPreferences.setAll copies expert settings (e.g., temperature/contextWindow/embeddingModel/RAG thresholds) via getters that return defaults when customizeExpertSettings is false, so importing preferences can overwrite and persist non-default expert values even if they were present in the backing store/XML. This causes silent loss of the user’s previously configured expert settings when customization is currently disabled (but may be re-enabled later).
Agent Prompt
### Issue description
`AiPreferences.setAll` currently copies expert settings via getters (`getTemperature()`, `getContextWindowSize()`, `getEmbeddingModel()`, `getRagMinScore()`, etc.). These getters intentionally return defaults when `customizeExpertSettings` is `false`, so `setAll` can overwrite stored custom expert values during import/reset flows.
### Issue Context
This is especially harmful during preference import (`JabRefCliPreferences#importPreferences`) because the imported backing store may contain custom expert values while `AI_CUSTOMIZE_SETTINGS` is `false`. After `setAll`, the `EasyBind.listen(...)` handlers persist the overwritten defaults back into the backing store, losing the imported values.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[225-265]
### Implementation guidance
Update `setAll` to copy the *raw stored properties* for expert settings instead of the derived getters, e.g.:
- `this.embeddingModel.set(preferences.embeddingModelProperty().get());`
- `this.temperature.set(preferences.temperatureProperty().get());`
- `this.contextWindowSize.set(preferences.contextWindowSizeProperty().get());`
- `this.documentSplitterChunkSize.set(preferences.documentSplitterChunkSizeProperty().get());`
- `this.documentSplitterOverlapSize.set(preferences.documentSplitterOverlapSizeProperty().get());`
- `this.ragMaxResultsCount.set(preferences.ragMaxResultsCountProperty().get());`
- `this.ragMinScore.set(preferences.ragMinScoreProperty().get());`
(Keep using normal getters for non-derived fields like templates, provider, booleans, etc.)
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
* upstream/main: (29 commits) Chore(deps): Bump dev.langchain4j:langchain4j-bom in /versions (JabRef#15853) Chore(deps): Bump org.glassfish.jaxb:jaxb-runtime in /versions (JabRef#15854) Chore(deps): Bump com.gradleup.shadow:shadow-gradle-plugin (JabRef#15852) Chore(deps): Bump com.gradleup.shadow:shadow-gradle-plugin (JabRef#15849) Chore(deps): Bump com.autonomousapps:dependency-analysis-gradle-plugin (JabRef#15850) Update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.6 (JabRef#15844) Fix reset and import of AiPreferences (JabRef#15843) Fix Comparable Contract Violation in SharedBibEntryData (JabRef#15806) (JabRef#15842) Chore(deps): Bump com.dlsc.gemsfx:gemsfx from 4.0.5 to 4.1.0 in /versions (JabRef#15841) Chore(deps): Bump jablib/src/main/resources/csl-styles (JabRef#15840) New Crowdin updates (JabRef#15839) Add group pseudonymization support (fixes JabRef#14117) (JabRef#15258) Feature parse MeSH terms in PubMed MEDLINE records (JabRef#15529) Fix/non latin author parsed as name prefix (JabRef#15823) Fix not on fx thread cleanup (JabRef#15835) Fix garbled BibEntry Javadoc example (JabRef#15834) Revert "Fix cleanup operationn setFiles not on fx thread causes exceptiosn" Revert "changelog" changelog Fix cleanup operationn setFiles not on fx thread causes exceptiosn ...
Related issues and pull requests
Follow-up to #15827
PR Description
Fix import and reset by usual pattern
Very Little enhancements in the AiPreferences class about default
Steps to test
Run JabRef
Open Prefs
Reset Prefs
See AI Prefs reset
AI usage
Initial changes done by Claude Code (model claude-sonnet-4-6), heavily redacted by human intelligence
Checklist
CHANGELOG.mdin a way that can be understood by the average user (if change is visible to the user)