Skip to content

Commit bcb2867

Browse files
authored
fix: prune deleted BM25 vocabulary entries (#11997)
1 parent af7ec4a commit bcb2867

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

haystack/document_stores/in_memory/document_store.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,9 @@ def delete_documents(self, document_ids: list[str]) -> None:
507507
doc_len = doc_stats.doc_len
508508

509509
self._freq_vocab_for_idf.subtract(Counter(freq.keys()))
510+
for token in freq:
511+
if self._freq_vocab_for_idf[token] <= 0:
512+
del self._freq_vocab_for_idf[token]
510513
try:
511514
self._avg_doc_len = (self._avg_doc_len * (len(self._bm25_attr) + 1) - doc_len) / len(self._bm25_attr)
512515
except ZeroDivisionError:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fixes:
2+
- |
3+
Remove zero-frequency vocabulary entries after deleting documents from
4+
``InMemoryDocumentStore`` so previous document history no longer changes
5+
BM25Okapi scores for the active corpus.

test/document_stores/test_in_memory.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,26 @@ def test_bm25_avg_doc_len_after_delete(self, in_memory_doc_store):
763763
# After removing "hello world" (2 tokens), only "foo bar baz" (3 tokens) remains
764764
assert in_memory_doc_store._avg_doc_len == pytest.approx(3.0)
765765

766+
def test_bm25_okapi_scores_do_not_depend_on_deleted_documents(self):
767+
active_documents = [
768+
Document(id="d1", content="common alpha"),
769+
Document(id="d2", content="common beta"),
770+
Document(id="d3", content="common gamma"),
771+
]
772+
fresh_store = InMemoryDocumentStore(bm25_algorithm="BM25Okapi", shared=False)
773+
reused_store = InMemoryDocumentStore(bm25_algorithm="BM25Okapi", shared=False)
774+
deleted_document = Document(content="one two three four five six seven eight nine ten")
775+
776+
reused_store.write_documents([deleted_document])
777+
reused_store.delete_documents([deleted_document.id])
778+
fresh_store.write_documents(active_documents)
779+
reused_store.write_documents(active_documents)
780+
781+
fresh_scores = {doc.id: doc.score for doc in fresh_store.bm25_retrieval(query="common", top_k=3)}
782+
reused_scores = {doc.id: doc.score for doc in reused_store.bm25_retrieval(query="common", top_k=3)}
783+
784+
assert reused_scores == pytest.approx(fresh_scores)
785+
766786

767787
class TestMemoryDocumentStoreNotShared(TestMemoryDocumentStore):
768788
"""

0 commit comments

Comments
 (0)