Skip to content

Commit 2ea6d22

Browse files
fix(eval): fail closed on incomplete metric evidence
1 parent 0060acb commit 2ea6d22

2 files changed

Lines changed: 50 additions & 2 deletions

File tree

examples/optimization/eval_optimize_loop/run_pipeline.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,10 +1931,16 @@ def summarize_evaluate_result(result: Any, evalset_payload: dict[str, Any]) -> d
19311931
actual_text, expected_text = _extract_actual_expected(runs[0], case_by_id[eval_id])
19321932
error_message = None
19331933
for run in runs:
1934-
run_passed = run_passed and _is_passed_status(run.final_eval_status)
1934+
run_metrics = list(run.overall_eval_metric_results or [])
1935+
run_passed = (
1936+
run_passed
1937+
and _is_passed_status(run.final_eval_status)
1938+
and bool(run_metrics)
1939+
and all(_is_passed_status(metric.eval_status) for metric in run_metrics)
1940+
)
19351941
if run.error_message and error_message is None:
19361942
error_message = sanitize_report_text(run.error_message)
1937-
for metric in run.overall_eval_metric_results:
1943+
for metric in run_metrics:
19381944
score = metric.score
19391945
metric_passed = _is_passed_status(metric.eval_status)
19401946
details = getattr(metric, "details", None)

tests/evaluation/test_eval_optimize_loop_example.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,48 @@ def test_summary_omits_thoughts_and_redacts_provider_credentials_from_report_tex
829829
assert secret not in serialized_summary
830830

831831

832+
def test_summary_fails_closed_when_a_reported_metric_was_not_evaluated():
833+
module = load_pipeline_module()
834+
payload = load_report(EXAMPLE_DIR / "val.evalset.json")
835+
case = payload["eval_cases"][0]
836+
run = SimpleNamespace(
837+
eval_metric_result_per_invocation=[],
838+
final_eval_status="passed",
839+
error_message=None,
840+
overall_eval_metric_results=[
841+
SimpleNamespace(
842+
metric_name=ROUTE_TOOL_ARGS_METRIC,
843+
score=None,
844+
eval_status="not_evaluated",
845+
details=None,
846+
threshold=1.0,
847+
),
848+
SimpleNamespace(
849+
metric_name="llm_rubric_response",
850+
score=1.0,
851+
eval_status="passed",
852+
details=None,
853+
threshold=0.66,
854+
),
855+
],
856+
)
857+
result = SimpleNamespace(
858+
results_by_eval_set_id={
859+
payload["eval_set_id"]: SimpleNamespace(
860+
eval_results_by_eval_id={case["eval_id"]: [run]},
861+
)
862+
}
863+
)
864+
865+
summary = module.summarize_evaluate_result(result, payload)
866+
case_result = summary["case_results"][0]
867+
868+
assert case_result["passed"] is False
869+
assert case_result["root_cause"] in module.TAXONOMY
870+
assert case_result["reasons"]
871+
assert case["eval_id"] in summary["failed_case_ids"]
872+
873+
832874
@pytest.mark.parametrize(
833875
"sensitive_text",
834876
[

0 commit comments

Comments
 (0)