temp: pref to select hybrid/semantic/lexical mode
Some checks are pending
CI / Test (shard 1) (push) Waiting to run
CI / Test (shard 2) (push) Waiting to run
CI / Test (shard 3) (push) Waiting to run
CI / Test (shard 4) (push) Waiting to run
CI / Utilities Tests (push) Waiting to run
CI / Build, Upload (push) Waiting to run

To make it easier to experiment
This commit is contained in:
Bogdan Abaev 2026-08-18 17:25:27 -07:00
parent 3a1a582cca
commit 4f782d83bc
4 changed files with 53 additions and 5 deletions

View file

@ -311,6 +311,23 @@
</hbox>
<description id="semantic-search-model-description"
data-l10n-id="preferences-advanced-semantic-search-model-description"/>
<!-- Temporary, for testing: pin best-match search to one engine -->
<hbox align="center">
<label data-l10n-id="preferences-advanced-best-match-engine"
control="best-match-engine"/>
<menulist id="best-match-engine"
preference="extensions.zotero.search.bestMatchEngine"
native="true">
<menupopup>
<menuitem value="hybrid"
data-l10n-id="preferences-advanced-best-match-engine-hybrid"/>
<menuitem value="lexical"
data-l10n-id="preferences-advanced-best-match-engine-lexical"/>
<menuitem value="semantic"
data-l10n-id="preferences-advanced-best-match-engine-semantic"/>
</menupopup>
</menulist>
</hbox>
<checkbox id="semantic-search-index-fulltext"
data-l10n-id="preferences-advanced-semantic-search-index-fulltext"
preference="extensions.zotero.embeddings.indexFulltext"

View file

@ -99,8 +99,20 @@ Zotero.BestMatch = new function () {
*/
this.scoreItemIDs = async function (queryText, itemIDs, options = {}) {
try {
// Temporary, for testing: the bestMatchEngine pref pins scoring to
// one engine instead of the hybrid default
let engine = Zotero.Prefs.get('search.bestMatchEngine');
if (engine == 'semantic') {
let semantic = await Zotero.Embeddings.scoreItemIDs(queryText, itemIDs, options);
// On the model's display band, so scores are 0-1 like the
// other modes'
return new Map([...semantic].map(
([itemID, score]) => [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],

View file

@ -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…

View file

@ -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);