555e282cc4
pi-agent-plugin checks / lint (push) Has been cancelled
pi-agent-plugin checks / test (20) (push) Has been cancelled
pi-agent-plugin checks / test (22) (push) Has been cancelled
pi-agent-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / check_changes (push) Has been cancelled
TypeScript SDK CI / changelog_check (push) Has been cancelled
ci / changelog_check (push) Has been cancelled
ci / check_changes (push) Has been cancelled
ci / build_mem0 (3.10) (push) Has been cancelled
ci / build_mem0 (3.11) (push) Has been cancelled
ci / build_mem0 (3.12) (push) Has been cancelled
CLI Node CI / lint (push) Has been cancelled
CLI Node CI / test (20) (push) Has been cancelled
CLI Node CI / test (22) (push) Has been cancelled
CLI Node CI / build (push) Has been cancelled
CLI Python CI / lint (push) Has been cancelled
CLI Python CI / test (3.10) (push) Has been cancelled
CLI Python CI / test (3.11) (push) Has been cancelled
CLI Python CI / test (3.12) (push) Has been cancelled
CLI Python CI / build (push) Has been cancelled
openclaw checks / lint (push) Has been cancelled
openclaw checks / test (20) (push) Has been cancelled
openclaw checks / test (22) (push) Has been cancelled
openclaw checks / build (push) Has been cancelled
opencode-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (22) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (22) (push) Has been cancelled
110 lines
4.2 KiB
Python
110 lines
4.2 KiB
Python
"""Regression tests for the reranker fallback path honoring ``config.top_k``.
|
|
|
|
When the underlying rerank call fails, the reranker falls back to returning the
|
|
documents in their original order. That fallback must still respect the
|
|
configured ``top_k`` limit, exactly like the success path does. The HuggingFace
|
|
and SentenceTransformer rerankers already behave this way; these tests pin the
|
|
same contract for the Cohere and ZeroEntropy rerankers.
|
|
"""
|
|
|
|
import sys
|
|
from types import ModuleType
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
|
|
from mem0.configs.rerankers.cohere import CohereRerankerConfig
|
|
from mem0.configs.rerankers.zero_entropy import ZeroEntropyRerankerConfig
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_cohere(monkeypatch):
|
|
"""Provide a fake ``cohere`` module so CohereReranker imports/constructs."""
|
|
fake_cohere = ModuleType("cohere")
|
|
fake_client = MagicMock()
|
|
fake_cohere.Client = MagicMock(return_value=fake_client)
|
|
monkeypatch.setitem(sys.modules, "cohere", fake_cohere)
|
|
|
|
import mem0.reranker.cohere_reranker as cohere_reranker
|
|
|
|
monkeypatch.setattr(cohere_reranker, "cohere", fake_cohere, raising=False)
|
|
monkeypatch.setattr(cohere_reranker, "COHERE_AVAILABLE", True, raising=False)
|
|
return cohere_reranker, fake_client
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_zero_entropy(monkeypatch):
|
|
"""Provide a fake ``zeroentropy`` module so ZeroEntropyReranker imports."""
|
|
fake_module = ModuleType("zeroentropy")
|
|
fake_client = MagicMock()
|
|
fake_module.ZeroEntropy = MagicMock(return_value=fake_client)
|
|
monkeypatch.setitem(sys.modules, "zeroentropy", fake_module)
|
|
|
|
import mem0.reranker.zero_entropy_reranker as zero_entropy_reranker
|
|
|
|
monkeypatch.setattr(zero_entropy_reranker, "ZeroEntropy", fake_module.ZeroEntropy, raising=False)
|
|
monkeypatch.setattr(zero_entropy_reranker, "ZERO_ENTROPY_AVAILABLE", True, raising=False)
|
|
return zero_entropy_reranker, fake_client
|
|
|
|
|
|
def _docs(n):
|
|
return [{"memory": f"doc{i}"} for i in range(n)]
|
|
|
|
|
|
class TestCohereFallbackTopK:
|
|
def test_fallback_respects_config_top_k(self, mock_cohere):
|
|
module, fake_client = mock_cohere
|
|
fake_client.rerank.side_effect = RuntimeError("API error")
|
|
|
|
reranker = module.CohereReranker(CohereRerankerConfig(api_key="test-key", top_k=2))
|
|
result = reranker.rerank("query", _docs(5))
|
|
|
|
assert len(result) == 2
|
|
|
|
def test_fallback_per_call_top_k_overrides_config(self, mock_cohere):
|
|
module, fake_client = mock_cohere
|
|
fake_client.rerank.side_effect = RuntimeError("API error")
|
|
|
|
reranker = module.CohereReranker(CohereRerankerConfig(api_key="test-key", top_k=4))
|
|
result = reranker.rerank("query", _docs(5), top_k=1)
|
|
|
|
assert len(result) == 1
|
|
|
|
def test_fallback_returns_all_when_no_top_k(self, mock_cohere):
|
|
module, fake_client = mock_cohere
|
|
fake_client.rerank.side_effect = RuntimeError("API error")
|
|
|
|
reranker = module.CohereReranker(CohereRerankerConfig(api_key="test-key"))
|
|
result = reranker.rerank("query", _docs(5))
|
|
|
|
assert len(result) == 5
|
|
|
|
|
|
class TestZeroEntropyFallbackTopK:
|
|
def test_fallback_respects_config_top_k(self, mock_zero_entropy):
|
|
module, fake_client = mock_zero_entropy
|
|
fake_client.models.rerank.side_effect = RuntimeError("API error")
|
|
|
|
reranker = module.ZeroEntropyReranker(ZeroEntropyRerankerConfig(api_key="test-key", top_k=2))
|
|
result = reranker.rerank("query", _docs(5))
|
|
|
|
assert len(result) == 2
|
|
|
|
def test_fallback_per_call_top_k_overrides_config(self, mock_zero_entropy):
|
|
module, fake_client = mock_zero_entropy
|
|
fake_client.models.rerank.side_effect = RuntimeError("API error")
|
|
|
|
reranker = module.ZeroEntropyReranker(ZeroEntropyRerankerConfig(api_key="test-key", top_k=4))
|
|
result = reranker.rerank("query", _docs(5), top_k=1)
|
|
|
|
assert len(result) == 1
|
|
|
|
def test_fallback_returns_all_when_no_top_k(self, mock_zero_entropy):
|
|
module, fake_client = mock_zero_entropy
|
|
fake_client.models.rerank.side_effect = RuntimeError("API error")
|
|
|
|
reranker = module.ZeroEntropyReranker(ZeroEntropyRerankerConfig(api_key="test-key"))
|
|
result = reranker.rerank("query", _docs(5))
|
|
|
|
assert len(result) == 5
|