mirror of
https://github.com/zotero/zotero.git
synced 2026-09-11 22:51:15 +00:00
Rerank best-match only on embeddings-index updates
The item tree reran the active best-match search on every 'refresh' item event, so unrelated bursts (e.g., full-text indexing) triggered a full re-search and re-score. Flag the embeddings indexer's own notifications and rerank only for those.
This commit is contained in:
parent
24524e1279
commit
2112da0766
4 changed files with 31 additions and 10 deletions
|
|
@ -930,11 +930,10 @@ class CollectionViewItemTreeRowProvider extends ItemTreeRowProvider {
|
|||
if (items.length == 0) return;
|
||||
}
|
||||
|
||||
if (action == 'refresh' && type == 'item'
|
||||
if (action == 'refresh' && type == 'item' && extraData && extraData.embeddingsUpdate
|
||||
&& collectionTreeRows.some(rowIsBestMatchSearch)) {
|
||||
// Under an active best-match search, a refresh event can mean new or
|
||||
// changed embeddings (the background indexer notifies after committing
|
||||
// batches), so rerun the search to update the scores and ranks
|
||||
// The background indexer committed new or changed embeddings, so
|
||||
// rerun the active best-match search to update the scores and ranks
|
||||
this.itemTree.invalidateRowCache(ids);
|
||||
refresh = true;
|
||||
madeChanges = true;
|
||||
|
|
|
|||
|
|
@ -1245,9 +1245,10 @@ Zotero.Embeddings.Indexing = new function () {
|
|||
|
||||
// Announce written or removed embeddings with a 'refresh' item event, so
|
||||
// an active best-match search reranks as vectors change (e.g. during
|
||||
// initial indexing, or after a clear). Coalesced, so a long indexing run
|
||||
// produces an update every couple of seconds rather than one per
|
||||
// committed batch.
|
||||
// initial indexing, or after a clear). The embeddingsUpdate flag lets the
|
||||
// item tree rerank only for these events, not for every refresh. Coalesced,
|
||||
// so a long indexing run produces an update every couple of seconds rather
|
||||
// than one per committed batch.
|
||||
function _notifyIndexed(itemIDs) {
|
||||
for (let id of itemIDs) {
|
||||
_indexedNotifyIDs.add(id);
|
||||
|
|
@ -1259,7 +1260,7 @@ Zotero.Embeddings.Indexing = new function () {
|
|||
_indexedNotifyTimer = null;
|
||||
let ids = [..._indexedNotifyIDs];
|
||||
_indexedNotifyIDs.clear();
|
||||
Zotero.Notifier.trigger('refresh', 'item', ids)
|
||||
Zotero.Notifier.trigger('refresh', 'item', ids, { embeddingsUpdate: true })
|
||||
.catch(e => Zotero.logError(e));
|
||||
}, INDEXED_NOTIFY_DELAY);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
Zotero.Notifier = new function () {
|
||||
// Options that apply to an entire event, not a specific object
|
||||
this.EVENT_LEVEL_OPTIONS = ['autoSyncDelay', 'skipAutoSync'];
|
||||
this.EVENT_LEVEL_OPTIONS = ['autoSyncDelay', 'skipAutoSync', 'embeddingsUpdate'];
|
||||
|
||||
var _observers = {};
|
||||
var _types = [
|
||||
|
|
|
|||
|
|
@ -530,10 +530,31 @@ describe("CollectionViewItemTree", function () {
|
|||
|
||||
// The indexer's coalesced notification after new/removed vectors
|
||||
best = itemB.id;
|
||||
await Zotero.Notifier.trigger('refresh', 'item', [itemA.id, itemB.id]);
|
||||
await Zotero.Notifier.trigger('refresh', 'item', [itemA.id, itemB.id], { embeddingsUpdate: true });
|
||||
await itemsView._refreshPromise;
|
||||
assert.deepEqual(itemsView._rows.map(row => row.id), [itemB.id, itemA.id]);
|
||||
});
|
||||
|
||||
it("shouldn't rerank on a refresh that isn't an embeddings update", async function () {
|
||||
let col = await createDataObject('collection');
|
||||
let itemA = await createDataObject('item', { title: "norerank A", collections: [col.id] });
|
||||
let itemB = await createDataObject('item', { title: "norerank B", collections: [col.id] });
|
||||
let best = itemA.id;
|
||||
stubs.push(sinon.stub(Zotero.Embeddings, 'scoreItemIDs').callsFake(
|
||||
async (query, itemIDs) => new Map(itemIDs.map(id => [id, id == best ? 0.9 : 0.5]))
|
||||
));
|
||||
|
||||
await select(win, col);
|
||||
itemsView = zp.itemsView;
|
||||
await itemsView.setFilter('search', 'some query');
|
||||
assert.deepEqual(itemsView._rows.map(row => row.id), [itemA.id, itemB.id]);
|
||||
|
||||
// An unrelated refresh (e.g. a field change) leaves the ranking alone
|
||||
best = itemB.id;
|
||||
await Zotero.Notifier.trigger('refresh', 'item', [itemA.id, itemB.id]);
|
||||
await itemsView._refreshPromise;
|
||||
assert.deepEqual(itemsView._rows.map(row => row.id), [itemA.id, itemB.id]);
|
||||
});
|
||||
});
|
||||
|
||||
it("should expand parent item and attachment for an annotation match", async function () {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue