diff --git a/rag/evaluator/faithfulness_checker.py b/rag/evaluator/faithfulness_checker.py index 56c8bd0..25b4ad6 100644 --- a/rag/evaluator/faithfulness_checker.py +++ b/rag/evaluator/faithfulness_checker.py @@ -34,8 +34,8 @@ def check(self, feedback: str, context_chunks: list[dict]) -> float: logger.info("faithfulness_no_claims_extracted") return 0.5 # Default to neutral if no extractable claims - # Concatenate context text - context_text = " ".join([chunk.get("text", "") for chunk in context_chunks]) + # Concatenate context text; treat missing or None text as empty + context_text = " ".join([chunk.get("text") or "" for chunk in context_chunks]) # Check each claim for support supported = 0 diff --git a/tests/unit/test_faithfulness_checker.py b/tests/unit/test_faithfulness_checker.py index b92b29d..43e8720 100644 --- a/tests/unit/test_faithfulness_checker.py +++ b/tests/unit/test_faithfulness_checker.py @@ -222,10 +222,6 @@ def test_minimum_overlap_required(self, checker): assert isinstance(supported, bool) # Need at least 2 meaningful tokens for support - @pytest.mark.xfail( - strict=True, - reason="issue #60: faithfulness checker crashes when a context chunk has text: None", - ) def test_none_context_chunk_text(self, checker): """Test handling of None in context chunk text.""" feedback = "Has Python skills" @@ -233,10 +229,18 @@ def test_none_context_chunk_text(self, checker): score = checker.check(feedback, context_chunks) - # Should handle gracefully + # Should handle gracefully instead of raising TypeError assert isinstance(score, float) assert 0.0 <= score <= 1.0 + # Mixed None and real text must also be join-safe + mixed_score = checker.check( + "Knows Python.", + [{"text": None}, {"text": "Knows Python well"}], + ) + assert isinstance(mixed_score, float) + assert 0.0 <= mixed_score <= 1.0 + def test_missing_text_key_in_chunk(self, checker): """Test handling of missing 'text' key in context chunk.""" feedback = "Has Python skills"