"""Comparison and attribution for benchmark configurations. Produces delta tables and attribution reports to quantify how much of the apparent architecture gain comes from fixing the current request alone (temperature, schema constraints) versus the full v3 architecture. Validates: Requirements 16.2, 16.3, 16.5 """ from __future__ import annotations from pydantic import BaseModel, Field from services.intelligence_pipeline_v3.benchmark.runner import BenchmarkRun # --------------------------------------------------------------------------- # Result Models # --------------------------------------------------------------------------- class FieldDelta(BaseModel): """Per-field improvement between two configurations.""" field_name: str = Field(description="Name of the compared field/metric") baseline_value: float = Field(description="Value in the baseline configuration") comparison_value: float = Field(description="Value in the compared configuration") absolute_delta: float = Field(description="comparison - baseline") relative_delta_percent: float = Field( description="Percentage change from baseline ((comp - base) / base * 100)", ) improved: bool = Field( description="Whether the delta represents improvement (higher is better assumed unless inverted)", ) class ResourceDelta(BaseModel): """Resource usage comparison between configurations.""" metric_name: str = Field(description="Resource metric name") baseline_value: float = Field(description="Baseline resource usage") comparison_value: float = Field(description="Compared configuration resource usage") absolute_delta: float = Field(description="comparison - baseline") relative_delta_percent: float = Field(description="Percentage change") improved: bool = Field( description="Whether the delta represents improvement (lower is better for resources)", ) class ConfigDelta(BaseModel): """Comparison results between a baseline and one other configuration.""" baseline_config: str = Field(description="Baseline configuration name") comparison_config: str = Field(description="Compared configuration name") field_deltas: list[FieldDelta] = Field(default_factory=list) resource_deltas: list[ResourceDelta] = Field(default_factory=list) class ComparisonReport(BaseModel): """Full comparison report across multiple configurations. Attributes: configs_compared: Names of all configurations in this comparison. deltas: Per-configuration comparison against the baseline. attribution_summary: Human-readable attribution of improvement sources. """ configs_compared: list[str] = Field( description="All configuration names included in this comparison", ) deltas: list[ConfigDelta] = Field( default_factory=list, description="Delta tables for each non-baseline config vs baseline", ) attribution_summary: dict[str, float] = Field( default_factory=dict, description=( "Attribution percentages: maps source (e.g. 'temperature_fix', " "'schema_constraint', 'architecture') to fraction of total improvement" ), ) # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _compute_field_delta( field_name: str, baseline_val: float, comparison_val: float, *, higher_is_better: bool = True, ) -> FieldDelta: """Compute a single field delta with direction awareness.""" absolute = comparison_val - baseline_val relative = ( (absolute / baseline_val * 100.0) if baseline_val != 0.0 else 0.0 ) improved = absolute > 0.0 if higher_is_better else absolute < 0.0 return FieldDelta( field_name=field_name, baseline_value=baseline_val, comparison_value=comparison_val, absolute_delta=absolute, relative_delta_percent=relative, improved=improved, ) def _compute_resource_delta( metric_name: str, baseline_val: float, comparison_val: float, ) -> ResourceDelta: """Compute a resource delta (lower is better).""" absolute = comparison_val - baseline_val relative = ( (absolute / baseline_val * 100.0) if baseline_val != 0.0 else 0.0 ) improved = absolute < 0.0 # Lower resource usage is better return ResourceDelta( metric_name=metric_name, baseline_value=baseline_val, comparison_value=comparison_val, absolute_delta=absolute, relative_delta_percent=relative, improved=improved, ) def _run_metrics(run: BenchmarkRun) -> dict[str, float]: """Extract summary metrics from a benchmark run.""" n = len(run.results) or 1 # Avoid division by zero return { "schema_validity_rate": run.schema_validity_rate, "success_count": float(run.success_count), "failure_count": float(run.failure_count), "mean_duration_ms": run.mean_duration_ms, "total_input_tokens": float(run.total_input_tokens), "total_output_tokens": float(run.total_output_tokens), "mean_retries": sum(r.retries for r in run.results) / n, } # --------------------------------------------------------------------------- # Public API # --------------------------------------------------------------------------- def compare_configurations( baseline_run: BenchmarkRun, comparison_runs: list[BenchmarkRun], ) -> ComparisonReport: """Compare benchmark runs to produce delta tables and attribution. Computes per-field and per-resource deltas between the baseline and each comparison configuration, then attributes improvement sources. Args: baseline_run: The baseline (typically BASELINE_CURRENT) run results. comparison_runs: One or more comparison configuration runs. Returns: ComparisonReport with deltas and attribution percentages. """ configs_compared = [baseline_run.config_name] + [ r.config_name for r in comparison_runs ] baseline_metrics = _run_metrics(baseline_run) deltas: list[ConfigDelta] = [] # Fields where higher is better _higher_is_better = {"schema_validity_rate", "success_count"} # Fields where lower is better (resource-like) _resource_fields = { "mean_duration_ms", "total_input_tokens", "total_output_tokens", "mean_retries", "failure_count", } for comp_run in comparison_runs: comp_metrics = _run_metrics(comp_run) field_deltas: list[FieldDelta] = [] resource_deltas: list[ResourceDelta] = [] for metric_name, baseline_val in baseline_metrics.items(): comp_val = comp_metrics[metric_name] if metric_name in _resource_fields: resource_deltas.append( _compute_resource_delta(metric_name, baseline_val, comp_val) ) else: field_deltas.append( _compute_field_delta( metric_name, baseline_val, comp_val, higher_is_better=(metric_name in _higher_is_better), ) ) deltas.append( ConfigDelta( baseline_config=baseline_run.config_name, comparison_config=comp_run.config_name, field_deltas=field_deltas, resource_deltas=resource_deltas, ) ) # Attribution: estimate how much improvement comes from each fix attribution = _compute_attribution(baseline_metrics, comparison_runs) return ComparisonReport( configs_compared=configs_compared, deltas=deltas, attribution_summary=attribution, ) def _compute_attribution( baseline_metrics: dict[str, float], comparison_runs: list[BenchmarkRun], ) -> dict[str, float]: """Compute attribution percentages for improvement sources. Uses schema_validity_rate as the primary improvement signal. Attribution is computed as the fraction of total improvement each configuration step contributes. Returns a dict mapping source labels to fraction (0.0-1.0). """ attribution: dict[str, float] = {} if not comparison_runs: return attribution baseline_validity = baseline_metrics["schema_validity_rate"] # Find temp_zero and strict_schema runs by config name temp_zero_validity: float | None = None strict_schema_validity: float | None = None for run in comparison_runs: run_metrics = _run_metrics(run) if "temp_zero" in run.config_name: temp_zero_validity = run_metrics["schema_validity_rate"] elif "strict_schema" in run.config_name: strict_schema_validity = run_metrics["schema_validity_rate"] # Compute incremental gains # Total improvement = strict_schema - baseline (or best comparison - baseline) best_validity = max( _run_metrics(r)["schema_validity_rate"] for r in comparison_runs ) total_improvement = best_validity - baseline_validity if total_improvement <= 0.0: # No improvement detected; equal attribution attribution["temperature_fix"] = 0.0 attribution["schema_constraint"] = 0.0 return attribution # Temperature fix contribution if temp_zero_validity is not None: temp_gain = temp_zero_validity - baseline_validity attribution["temperature_fix"] = max(0.0, temp_gain / total_improvement) else: attribution["temperature_fix"] = 0.0 # Schema constraint contribution (incremental over temp fix) if strict_schema_validity is not None and temp_zero_validity is not None: schema_gain = strict_schema_validity - temp_zero_validity attribution["schema_constraint"] = max(0.0, schema_gain / total_improvement) elif strict_schema_validity is not None: schema_gain = strict_schema_validity - baseline_validity attribution["schema_constraint"] = max(0.0, schema_gain / total_improvement) else: attribution["schema_constraint"] = 0.0 # Remaining is attributed to other factors accounted = attribution.get("temperature_fix", 0.0) + attribution.get( "schema_constraint", 0.0 ) attribution["other"] = max(0.0, 1.0 - accounted) return attribution