Skip to content

Commit c2ad497

Browse files
committed
fix: handle unknown latency in optimization reports
1 parent 4ca9eaf commit c2ad497

3 files changed

Lines changed: 46 additions & 5 deletions

File tree

examples/optimization/eval_optimize_loop/loop/analysis.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,11 @@ def unique_proposals(
490490
raise RuntimeError("AgentOptimizer produced no auditable prompt candidate")
491491
return unique
492492

493+
@staticmethod
494+
def _pareto_latency_ms(resources: ResourceUsage) -> float:
495+
"""Return a dominance-safe latency value for Pareto comparisons."""
496+
return math.inf if resources.p95_latency_ms is None else resources.p95_latency_ms
497+
493498
@staticmethod
494499
def mark_pareto(candidates: list[CandidateEvaluation]) -> None:
495500
"""Mark gate-eligible candidates not dominated on quality, tokens, and latency."""
@@ -498,20 +503,20 @@ def mark_pareto(candidates: list[CandidateEvaluation]) -> None:
498503
if not candidate.gate.accepted:
499504
candidate.pareto_optimal = False
500505
continue
506+
candidate_latency = RegressionAnalyzer._pareto_latency_ms(candidate.audit.resources)
501507
dominated = False
502508
for other in eligible:
503509
if other is candidate:
504510
continue
511+
other_latency = RegressionAnalyzer._pareto_latency_ms(other.audit.resources)
505512
no_worse = (other.validation.pass_rate >= candidate.validation.pass_rate
506513
and other.validation.average_score >= candidate.validation.average_score
507514
and other.audit.resources.total_tokens <= candidate.audit.resources.total_tokens
508-
and (other.audit.resources.p95_latency_ms
509-
or 0.0) <= (candidate.audit.resources.p95_latency_ms or 0.0))
515+
and other_latency <= candidate_latency)
510516
strictly_better = (other.validation.pass_rate > candidate.validation.pass_rate
511517
or other.validation.average_score > candidate.validation.average_score
512518
or other.audit.resources.total_tokens < candidate.audit.resources.total_tokens
513-
or (other.audit.resources.p95_latency_ms
514-
or 0.0) < (candidate.audit.resources.p95_latency_ms or 0.0))
519+
or other_latency < candidate_latency)
515520
if no_worse and strictly_better:
516521
dominated = True
517522
break

examples/optimization/eval_optimize_loop/loop/reporting.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,9 @@ def render_markdown(report: OptimizationReport) -> str:
145145
for item in report.candidates:
146146
usage = item.audit.resources
147147
cost = "unavailable" if usage.cost_usd is None else f"${usage.cost_usd:.4f}"
148+
latency = "unavailable" if usage.p95_latency_ms is None else f"{usage.p95_latency_ms:.1f} ms"
148149
lines.append(f"| `{item.candidate_id}` | {usage.metric_calls} | {usage.judge_calls} | "
149-
f"{usage.total_tokens} | {usage.p95_latency_ms or 0.0:.1f} ms | "
150+
f"{usage.total_tokens} | {latency} | "
150151
f"{usage.duration_seconds:.3f} s | {cost} | `{usage.cost_measurement}` |")
151152
lines.append("")
152153
return "\n".join(lines)

tests/evaluation/test_eval_optimize_loop_example.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,41 @@ async def test_report_includes_paired_bootstrap_uncertainty_and_pareto_selection
486486
assert robust_checks["validation_gain_ci_lower_bound"].passed is True
487487

488488

489+
@pytest.mark.asyncio
490+
async def test_unknown_latency_is_not_treated_as_zero_for_pareto_or_markdown(tmp_path: Path, ) -> None:
491+
EvalOptimizePipeline, PipelineSpec = _load_public_interface()
492+
report = await EvalOptimizePipeline(
493+
PipelineSpec.from_file(
494+
_EXAMPLE_DIR / "pipeline.json",
495+
output_dir=tmp_path / "unknown-latency",
496+
)).run()
497+
498+
from eval_optimize_loop.loop.analysis import RegressionAnalyzer
499+
from eval_optimize_loop.loop.reporting import render_markdown
500+
501+
robust = next(item for item in report.candidates if item.candidate_id == "robust")
502+
unknown_latency = robust.model_copy(deep=True)
503+
measured_latency = robust.model_copy(deep=True)
504+
unknown_latency.candidate_id = "unknown-latency"
505+
measured_latency.candidate_id = "measured-latency"
506+
unknown_latency.audit.resources.p95_latency_ms = None
507+
measured_latency.audit.resources.p95_latency_ms = 8.0
508+
509+
RegressionAnalyzer(seed=91, bootstrap_samples=100,
510+
confidence_level=0.95).mark_pareto([unknown_latency, measured_latency])
511+
assert unknown_latency.pareto_optimal is False
512+
assert measured_latency.pareto_optimal is True
513+
514+
report_for_rendering = report.model_copy(deep=True)
515+
rendered_robust = next(item for item in report_for_rendering.candidates if item.candidate_id == "robust")
516+
rendered_robust.audit.resources.p95_latency_ms = None
517+
markdown = render_markdown(report_for_rendering)
518+
resource_section = markdown.split("### Candidate evaluation resources", maxsplit=1)[1]
519+
resource_row = next(line for line in resource_section.splitlines() if line.startswith("| `robust` |"))
520+
assert "| unavailable |" in resource_row
521+
assert "0.0 ms" not in resource_row
522+
523+
489524
@pytest.mark.asyncio
490525
async def test_data_quality_fails_closed_on_cross_split_near_duplicate(tmp_path: Path, ) -> None:
491526
EvalOptimizePipeline, PipelineSpec = _load_public_interface()

0 commit comments

Comments
 (0)