rag-llm-app / tests /test_phase_flags.py
babaralishah's picture
Add phase flags for ablation study and implement guardrails in query processing
de73c32
Raw History Blame Contribute Delete
3.1 kB
from unittest.mock import patch
import sys
from pathlib import Path
# Ensure project root is on sys.path so `src` imports work when running tests directly
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from src import config
from src.api import resolve_phase_flags, get_query_settings
from src.cache import get_cache_key
from src.rag_pipeline import rag_answer
import src.rag_pipeline as rag_module
def test_phase_keys_present():
expected = {"V1", "V2", "V3", "V4", "V5", "V6"}
assert set(config.PHASE_FLAGS.keys()) >= expected
def test_resolve_phase_flags_and_get_query_settings():
for phase_key, expected_flags in config.PHASE_FLAGS.items():
# resolve_phase_flags should return the same mapping
resolved = resolve_phase_flags(phase_key)
assert resolved == expected_flags
# get_query_settings should return phase flags when phase is provided
Q = type("Q", (), {})
req = Q()
req.phase = phase_key
req.use_hybrid = False
req.use_reranker = False
settings = get_query_settings(req)
assert settings == expected_flags
def test_cache_key_includes_phase():
k_none = get_cache_key("hello", use_hybrid=False, use_reranker=False, top_k=5, phase=None)
k_v1 = get_cache_key("hello", use_hybrid=False, use_reranker=False, top_k=5, phase="V1")
assert k_none != k_v1
def test_guardrail_abstain_and_allow():
# Patch generate_answer to avoid external LLM calls
with patch.object(rag_module, "generate_answer", return_value="STUB_ANSWER"):
# Low-confidence retrieval should trigger guardrail abstention
retrieved_low = [{"text": "x", "metadata": {}, "score": 0.2, "rerank_score": 0.0}]
out_low = rag_answer(
"what is x?",
retrieved_low,
use_reranker=False,
final_top_k=1,
use_guardrails=True,
)
assert isinstance(out_low, dict)
# Should either return no sources or a refusal message
assert out_low.get("sources", []) == [] or "don't have" in out_low.get("answer", "").lower()
# High-confidence retrieval should allow normal LLM call (patched)
retrieved_high = [
{
"text": "useful",
"metadata": {"source_file": "f", "page": 1},
"score": 0.95,
"rerank_score": 0.0,
"final_score": 0.95,
}
]
out_high = rag_answer(
"what is x?",
retrieved_high,
use_reranker=False,
final_top_k=1,
use_guardrails=True,
)
assert isinstance(out_high, dict)
assert "STUB_ANSWER" in out_high.get("answer", "")
assert out_high.get("sources")
if __name__ == "__main__":
# Simple runner for environments without pytest installed
test_phase_keys_present()
test_resolve_phase_flags_and_get_query_settings()
test_cache_key_includes_phase()
test_guardrail_abstain_and_allow()
print("All phase-flag smoke tests passed.")