Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions tr_sys/conftest.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@

import pytest
from pytest_factoryboy import register
from unittest.mock import MagicMock
from factories import AgentFactory, ActorFactory, MessageFactory, ChannelFactory

register(AgentFactory)
register(ActorFactory)
register(ChannelFactory)
register(MessageFactory)
try:
from pytest_factoryboy import register
from factories import AgentFactory, ActorFactory, MessageFactory, ChannelFactory
except ImportError:
register = None

if register is not None:
register(AgentFactory)
register(ActorFactory)
register(ChannelFactory)
register(MessageFactory)

@pytest.fixture
def new_user(db, user_factory):
Expand Down
220 changes: 220 additions & 0 deletions tr_sys/tests/unit/test_ranker_fusion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
import importlib.util
from pathlib import Path


def load_ranker_fusion():
module_path = Path(__file__).parents[2] / "tr_ars" / "ranker_fusion.py"
spec = importlib.util.spec_from_file_location("ranker_fusion", module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module


ranker_fusion = load_ranker_fusion()


def make_result(*ids):
return {
"node_bindings": {
"n%s" % index: [{"id": node_id}]
for index, node_id in enumerate(ids)
},
"analyses": [{"score": 0.1}],
}


def test_parse_ranker_config(monkeypatch):
monkeypatch.setenv("ARS_RRF_ARAGORN_WEIGHT", "0.8")
monkeypatch.setenv("ARS_RRF_C", "50")
monkeypatch.setenv("ARS_RRF_ENABLED", "true")

rf_config = ranker_fusion.get_config()

weights = {
"infores:shepherd-aragorn": 0.8,
"infores:shepherd-arax": 0.2,
}

assert rf_config == {
"enabled": True,
"weights": weights,
"c_value": 50,
}


def test_parse_ranker_config_derives_arax_weight(monkeypatch):
monkeypatch.setenv("ARS_RRF_ARAGORN_WEIGHT", "0.7")
monkeypatch.setenv("ARS_RRF_ARAX_WEIGHT", "0.9")

rf_config = ranker_fusion.get_config()

assert rf_config["weights"] == {
"infores:shepherd-aragorn": 0.7,
"infores:shepherd-arax": 0.3,
}


def test_parse_ranker_config_defaults_on_invalid(monkeypatch):
monkeypatch.setenv("ARS_RRF_ARAGORN_WEIGHT", "1.2")
monkeypatch.setenv("ARS_RRF_C", "-1")
monkeypatch.setenv("ARS_RRF_ENABLED", "true")

rf_config = ranker_fusion.get_config()

default_weights = {
"infores:shepherd-aragorn": 0.9,
"infores:shepherd-arax": 0.1,
}
default_c = 40

assert rf_config == {
"enabled": True,
"weights": default_weights,
"c_value": default_c,
}


def test_parse_ranker_config_defaults_on_nan_weight(monkeypatch):
monkeypatch.setenv("ARS_RRF_ARAGORN_WEIGHT", "nan")

rf_config = ranker_fusion.get_config()

assert rf_config["weights"] == {
"infores:shepherd-aragorn": 0.9,
"infores:shepherd-arax": 0.1,
}


def test_parse_ranker_config_reads_enabled_from_env(monkeypatch):
monkeypatch.setenv("ARS_RRF_ENABLED", "false")

rf_config = ranker_fusion.get_config()

assert rf_config["enabled"] is False


def test_configured_source_matches_infores_directly():
source = ranker_fusion.configured_source(
"infores:shepherd-arax",
"ara-shepherd-arax",
{"infores:shepherd-arax": 0.2},
)

assert source == "infores:shepherd-arax"


def test_configured_source_accepts_incoming_ara_agent_alias():
source = ranker_fusion.configured_source(
None,
"ara-shepherd-aragorn",
{"infores:shepherd-aragorn": 0.8},
)

assert source == "infores:shepherd-aragorn"


def test_weighted_rrf_sorts_results_and_adds_metadata():
result_a = make_result("CHEBI:1", "MONDO:1")
result_b = make_result("CHEBI:2", "MONDO:1")
result_c = make_result("CHEBI:3", "MONDO:1")
data = {"message": {"results": [result_a, result_b, result_c]}}

summary = ranker_fusion.apply_weighted_rrf(
data,
{
"infores:shepherd-aragorn": [result_a, result_b],
"infores:shepherd-arax": [result_b, result_c],
},
{"infores:shepherd-aragorn": 0.5, "infores:shepherd-arax": 0.5},
60,
)

assert summary["applied"] is True
assert [r["node_bindings"]["n0"][0]["id"] for r in data["message"]["results"]] == [
"CHEBI:2",
"CHEBI:1",
"CHEBI:3",
]
assert data["message"]["results"][0]["rrf_rank"] == 1
assert data["message"]["results"][0]["rrf_ranker_ranks"] == {
"infores:shepherd-aragorn": 2,
"infores:shepherd-arax": 1,
}
assert data["message"]["results"][0]["rrf_score"] > data["message"]["results"][1]["rrf_score"]


def test_weighted_rrf_keeps_unmatched_results_at_end_stably():
result_a = make_result("CHEBI:1")
result_b = make_result("CHEBI:2")
result_c = make_result("CHEBI:3")
data = {"message": {"results": [result_c, result_b, result_a]}}

summary = ranker_fusion.apply_weighted_rrf(
data,
{"infores:shepherd-aragorn": [result_a]},
{"infores:shepherd-aragorn": 1.0},
60,
)

assert summary["applied"] is True
assert [r["node_bindings"]["n0"][0]["id"] for r in data["message"]["results"]] == [
"CHEBI:1",
"CHEBI:3",
"CHEBI:2",
]
assert data["message"]["results"][1]["rrf_score"] == 0.0
assert data["message"]["results"][2]["rrf_score"] == 0.0


def test_weighted_rrf_tied_scores_share_rank():
result_a = make_result("CHEBI:1")
result_b = make_result("CHEBI:2")
data = {"message": {"results": [result_b, result_a]}}

summary = ranker_fusion.apply_weighted_rrf(
data,
{
"infores:shepherd-aragorn": [result_a, result_b],
"infores:shepherd-arax": [result_b, result_a],
},
{"infores:shepherd-aragorn": 0.5, "infores:shepherd-arax": 0.5},
60,
)

assert summary["applied"] is True
assert data["message"]["results"] == [result_b, result_a]
assert data["message"]["results"][0]["rrf_score"] == data["message"]["results"][1]["rrf_score"]
assert data["message"]["results"][0]["rrf_rank"] == 1
assert data["message"]["results"][1]["rrf_rank"] == 1


def test_weighted_rrf_noops_without_matching_ranker_results():
result_a = make_result("CHEBI:1")
data = {"message": {"results": [result_a]}}

summary = ranker_fusion.apply_weighted_rrf(
data,
{"infores:other": [result_a]},
{"infores:shepherd-aragorn": 1.0},
60,
)

assert summary == {"applied": False, "reason": "missing_ranker_results"}
assert data["message"]["results"] == [result_a]


def test_weighted_rrf_noops_without_matching_answers():
result_a = make_result("CHEBI:1")
result_b = make_result("CHEBI:2")
data = {"message": {"results": [result_a]}}

summary = ranker_fusion.apply_weighted_rrf(
data,
{"infores:shepherd-aragorn": [result_b]},
{"infores:shepherd-aragorn": 1.0},
60,
)

assert summary == {"applied": False, "reason": "no_matching_results"}
assert data["message"]["results"] == [result_a]
assert "rrf_score" not in result_a
Loading
Loading