diff --git a/chrome/content/zotero/preferences/preferences_advanced.xhtml b/chrome/content/zotero/preferences/preferences_advanced.xhtml
index cd4bb487a6..17e1afcdfd 100644
--- a/chrome/content/zotero/preferences/preferences_advanced.xhtml
+++ b/chrome/content/zotero/preferences/preferences_advanced.xhtml
@@ -311,6 +311,23 @@
+
+
+
+
+
+
+
+
+
+
+
[itemID, Zotero.Embeddings.getScoreFraction(score)]
+ ));
+ }
// A query the semantic engine can't embed ranks lexically alone
- if (!_useSemantic() || !Zotero.Embeddings.normalizeQuery(queryText || '')) {
+ if (engine == 'lexical' || !_useSemantic()
+ || !Zotero.Embeddings.normalizeQuery(queryText || '')) {
return await Zotero.Lexical.scoreItemIDs(queryText, itemIDs, options);
}
// Both engines score the same candidates concurrently. allSettled
@@ -160,9 +172,16 @@ Zotero.BestMatch = new function () {
* `strength`, plus chunk location fields or a lexical `source`
*/
this.getMatchingExcerpts = async function (queryText, itemID, options = {}) {
+ // Temporary, for testing: the bestMatchEngine pref keeps the pinned
+ // engine's excerpts alone -- no lexical excerpts or highlights when
+ // pinned semantic, no chunks when pinned lexical
+ let engine = Zotero.Prefs.get('search.bestMatchEngine');
let limit = options.limit ?? 5;
- let excerpts = await Zotero.Lexical.getMatchingExcerpts(queryText, itemID, options);
- if (!_useSemantic() || !Zotero.Embeddings.normalizeQuery(queryText || '')) {
+ let excerpts = engine == 'semantic'
+ ? []
+ : await Zotero.Lexical.getMatchingExcerpts(queryText, itemID, options);
+ if (engine == 'lexical' || !_useSemantic()
+ || !Zotero.Embeddings.normalizeQuery(queryText || '')) {
return excerpts;
}
let chunks = [];
@@ -180,8 +199,10 @@ Zotero.BestMatch = new function () {
if (!chunks.length) {
return excerpts;
}
- let ranges = await Zotero.Lexical.findMatchRanges(
- queryText, chunks.map(chunk => chunk.text));
+ let ranges = engine == 'semantic'
+ ? chunks.map(() => [])
+ : await Zotero.Lexical.findMatchRanges(
+ queryText, chunks.map(chunk => chunk.text));
chunks = chunks.map((chunk, i) => ({
...chunk,
ranges: ranges[i],
diff --git a/chrome/locale/en-US/zotero/preferences.ftl b/chrome/locale/en-US/zotero/preferences.ftl
index dfdab9942d..db8a03d7a3 100644
--- a/chrome/locale/en-US/zotero/preferences.ftl
+++ b/chrome/locale/en-US/zotero/preferences.ftl
@@ -105,6 +105,13 @@ preferences-advanced-semantic-search-multilingual =
preferences-advanced-semantic-search-model-description = “{ preferences-advanced-semantic-search-english.label }” and “{ preferences-advanced-semantic-search-chinese.label }” give the best results for libraries in those languages. “{ preferences-advanced-semantic-search-multilingual.label }” supports searching in and across many languages.
preferences-advanced-semantic-search-index-fulltext =
.label = Search full text of attachment files
+preferences-advanced-best-match-engine = Engine (temporary, for testing):
+preferences-advanced-best-match-engine-hybrid =
+ .label = Hybrid
+preferences-advanced-best-match-engine-lexical =
+ .label = Lexical
+preferences-advanced-best-match-engine-semantic =
+ .label = Semantic
preferences-advanced-semantic-search-downloading = Downloading…
preferences-advanced-semantic-search-downloading-progress = Downloading… { $percent }%
preferences-advanced-semantic-search-indexing = Indexing…
diff --git a/defaults/preferences/zotero.js b/defaults/preferences/zotero.js
index 8d6f9f671e..6f3e78478e 100644
--- a/defaults/preferences/zotero.js
+++ b/defaults/preferences/zotero.js
@@ -108,6 +108,9 @@ pref("extensions.zotero.keys.toggleRead", "`");
pref("extensions.zotero.keys.showTabsMenu", ";");
pref("extensions.zotero.search.quicksearch-mode", "fields");
+// Temporary, for testing: which engine best-match search runs -- 'lexical',
+// 'semantic', or 'hybrid' (both, fused)
+pref("extensions.zotero.search.bestMatchEngine", "hybrid");
// Fulltext indexing
pref("extensions.zotero.fulltext.textMaxLength", 500000);