Files
comet-ml--opik/sdks/opik_optimizer/benchmarks/check_results.py
T
wehub-resource-sync 5a558eb09e
TypeScript SDK Compatibility V1.x E2E Tests / Select Node version matrix (push) Has been cancelled
TypeScript SDK Compatibility V1.x E2E Tests / TypeScript SDK Compatibility V1.x E2E Tests Node ${{matrix.node_version}} (push) Has been cancelled
TypeScript SDK E2E Tests / TypeScript SDK E2E Tests Node ${{matrix.node_version}} (push) Has been cancelled
Opik Optimizer - E2E Tests / build-opik (push) Has been cancelled
TypeScript SDK Compatibility V1.x E2E Tests / build-opik (push) Has been cancelled
Python SDK E2E Tests / Select Python version matrix (push) Has been cancelled
Python SDK E2E Tests / Python SDK E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Python SDK E2E Tests / build-opik (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / Select Python version matrix (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / Python SDK Compatibility V1.x E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / build-opik (push) Has been cancelled
TypeScript SDK E2E Tests / Select Node version matrix (push) Has been cancelled
TypeScript SDK E2E Tests / build-opik (push) Has been cancelled
Opik Optimizer - E2E Tests / Opik Optimizer E2E Tests Python ${{matrix.python_version}} (push) Has been cancelled
Opik Optimizer - E2E Tests / Opik Optimizer Integration Smoke Tests (push) Has been cancelled
🐙 Code Quality / detect (push) Has been cancelled
🐙 Code Quality / lint (${{ matrix.leg.name }}) (push) Has been cancelled
🐙 Code Quality / summary (push) Has been cancelled
TypeScript SDK Library Integration Tests / Check Secrets (push) Has been cancelled
TypeScript SDK Library Integration Tests / opik-vercel (Vercel AI SDK / eve) (push) Has been cancelled
SDK Library Integration Tests Runner / Check Secrets (push) Has been cancelled
SDK Library Integration Tests Runner / Missed OpenAI API Key Warning (push) Has been cancelled
SDK Library Integration Tests Runner / Build (push) Has been cancelled
SDK Library Integration Tests Runner / openai_tests (push) Has been cancelled
SDK Library Integration Tests Runner / langchain_tests (push) Has been cancelled
SDK Library Integration Tests Runner / langchain_legacy_tests (push) Has been cancelled
SDK Library Integration Tests Runner / llama_index_tests (push) Has been cancelled
SDK Library Integration Tests Runner / anthropic_tests (push) Has been cancelled
SDK Library Integration Tests Runner / mistral_tests (push) Has been cancelled
SDK Library Integration Tests Runner / groq_tests (push) Has been cancelled
SDK Library Integration Tests Runner / aisuite_tests (push) Has been cancelled
SDK Library Integration Tests Runner / haystack_tests (push) Has been cancelled
SDK Library Integration Tests Runner / dspy_tests (push) Has been cancelled
SDK Library Integration Tests Runner / crewai_v0_tests (push) Has been cancelled
SDK Library Integration Tests Runner / crewai_v1_tests (push) Has been cancelled
SDK Library Integration Tests Runner / genai_tests (push) Has been cancelled
SDK Library Integration Tests Runner / adk_tests (push) Has been cancelled
SDK Library Integration Tests Runner / adk_legacy_1_3_0_tests (push) Has been cancelled
SDK Library Integration Tests Runner / evaluation_metrics_tests (push) Has been cancelled
SDK Library Integration Tests Runner / bedrock_tests (push) Has been cancelled
SDK Library Integration Tests Runner / litellm_tests (push) Has been cancelled
SDK Library Integration Tests Runner / harbor_tests (push) Has been cancelled
SDK Library Integration Tests Runner / Slack Notification (push) Has been cancelled
Lint Opik Helm Chart / render-equality (push) Has been cancelled
Opik Optimizer - Unit Tests / Opik Optimizer Unit Tests Python ${{matrix.python_version}} (push) Has been cancelled
Python BE E2E Tests / Python BE E2E (push) Has been cancelled
Python Backend Tests / run-python-backend-tests (push) Has been cancelled
Python SDK Unit Tests / Python SDK Unit Tests ${{matrix.python_version}} (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
SDK E2E Libraries Integration Tests / Check Secrets (push) Has been cancelled
SDK E2E Libraries Integration Tests / Missed OpenAI API Key Warning (push) Has been cancelled
SDK E2E Libraries Integration Tests / build-opik (push) Has been cancelled
SDK E2E Libraries Integration Tests / E2E Lib Integration Python ${{matrix.python_version}} (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-gemini) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-langchain) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-openai) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-otel) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-vercel) (push) Has been cancelled
TypeScript SDK Build & Publish / build-and-publish (push) Has been cancelled
TypeScript SDK Unit Tests / Test on Node ${{ matrix.node-version }} (push) Has been cancelled
Backend Tests / discover-tests (push) Has been cancelled
Backend Tests / ${{ matrix.name }} (push) Has been cancelled
Build and Publish SDK / build-and-publish (push) Has been cancelled
Build Opik Docker Images / set-version (push) Has been cancelled
Build Opik Docker Images / build-backend (push) Has been cancelled
Build Opik Docker Images / build-sandbox-executor-python (push) Has been cancelled
Build Opik Docker Images / build-python-backend (push) Has been cancelled
Build Opik Docker Images / build-frontend (push) Has been cancelled
Build Opik Docker Images / create-git-tag (push) Has been cancelled
ClickHouse Migration Cluster Check / validate-clickhouse-migrations (push) Has been cancelled
Docs - Publish / run (push) Has been cancelled
E2E Tests - Post Merge (v2) / 🧪 E2E v2 Tests (${{ github.event.inputs.tier || 't1' }}) (push) Has been cancelled
E2E Tests - Post Merge (v2) / 📢 Slack Notification (push) Has been cancelled
Frontend Unit Tests / Test on Node 20 (push) Has been cancelled
Guardrails E2E Tests / Select Python version matrix (push) Has been cancelled
Guardrails E2E Tests / Guardrails E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Guardrails E2E Tests / 📢 Slack Notification (push) Has been cancelled
Guardrails Backend Unit Tests / Guardrails Backend Unit Tests (push) Has been cancelled
Guardrails Backend Unit Tests / 📢 Slack Notification (push) Has been cancelled
Lint Opik Helm Chart / lint-helm-chart (Helm v3.21.0) (push) Has been cancelled
Lint Opik Helm Chart / lint-helm-chart (Helm v4.2.0) (push) Has been cancelled
Lint Opik Helm Chart / unittest-helm-chart (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:25:44 +08:00

433 lines
14 KiB
Python

"""
Check and display benchmark results from Modal Volume.
This script retrieves results from completed benchmark runs and generates reports.
It can be run at any time to check the status of running or completed benchmarks.
Usage:
# Check results for a specific run
modal run benchmarks/check_results.py --run-id run_20250423_153045
# Watch for new results (live monitoring)
modal run benchmarks/check_results.py --run-id run_20250423_153045 --watch
# List all available runs
modal run benchmarks/check_results.py --list-runs
# Generate detailed report with all metrics
modal run benchmarks/check_results.py --run-id run_20250423_153045 --detailed
"""
import argparse
import os
import sys
import time
from typing import Any
import modal
from rich.console import Console
from rich.live import Live
from rich.table import Table
from rich.panel import Panel
# Define Modal app
app = modal.App("opik-optimizer-benchmarks-results")
# Create image with rich and local benchmarks directory
image = (
modal.Image.debian_slim(python_version="3.12")
.pip_install("opik_optimizer>=2.1.3", "rich")
.add_local_dir(
local_path=os.path.dirname(os.path.abspath(__file__)),
remote_path="/root/benchmarks",
ignore=["__pycache__", ".venv", "benchmark_results"],
)
)
# Access the results volume
results_volume = modal.Volume.from_name(
"opik-benchmark-results", create_if_missing=True
)
# Initialize console
console: Console | None = None
@app.function(image=image, volumes={"/results": results_volume})
def list_available_runs() -> list[dict]:
"""List all available benchmark runs in the Volume."""
sys.path.insert(0, "/root/benchmarks")
from benchmarks.engines.modal.volume import list_available_runs_from_volume
return list_available_runs_from_volume()
@app.function(image=image, volumes={"/results": results_volume})
def load_run_results(run_id: str) -> dict:
"""
Load all results for a specific run.
Returns:
Dictionary containing:
- metadata: Run configuration
- tasks: List of task results
- call_ids: List of function call IDs
"""
sys.path.insert(0, "/root/benchmarks")
from benchmarks.engines.modal.volume import load_run_results_from_volume
return load_run_results_from_volume(run_id)
@app.local_entrypoint()
def main(
run_id: str | None = None,
list_runs: bool = False,
watch: bool = False,
detailed: bool = False,
raw: bool = False,
show_errors: bool = False,
task: str | None = None,
watch_interval: int = 30,
) -> None:
"""
Check and display benchmark results.
Args:
run_id: ID of the run to check
list_runs: List all available runs
watch: Continuously monitor for new results
detailed: Show detailed metrics breakdown
show_errors: Show full error messages for failed tasks
task: Filter to specific task ID (can be partial match)
watch_interval: Seconds between updates when watching (default: 30)
"""
global console
console = Console()
if list_runs:
_list_runs()
return
if run_id is None:
# In non-interactive environments (e.g., modal run), refuse to prompt.
if not sys.stdin.isatty():
assert console is not None
console.print(
"\n[red]No run-id provided and interactive input is unavailable.[/red]\n"
"Pass a run id explicitly, e.g.:\n"
" modal run benchmarks/check_results.py --run-id <run_id>\n"
"or list runs first:\n"
" modal run benchmarks/check_results.py --list-runs\n"
)
sys.exit(1)
run_id = _select_run()
if run_id is None:
sys.exit(1)
if show_errors or task:
_show_errors(run_id, task)
elif watch:
_watch_results(run_id, watch_interval, detailed)
else:
_display_results(run_id, detailed, raw)
def _list_runs() -> None:
"""Display list of all available runs."""
from benchmarks.utils.display import display_runs_table
assert console is not None
console.print("\n[bold]📋 Available Benchmark Runs[/bold]\n")
runs = list_available_runs.remote()
display_runs_table(runs, console)
def _select_run() -> str | None:
"""Interactively select a run from the most recent runs."""
assert console is not None
runs = list_available_runs.remote()
if not runs:
console.print("[red]No runs found in the volume.[/red]")
return None
console.print("\n[bold]📋 Select a run[/bold]\n")
# Show top 15
recent = runs[:15]
table = Table(show_header=True, header_style="bold", box=None, padding=(0, 1))
table.add_column("#", style="dim", width=3)
table.add_column("Run ID", no_wrap=True)
table.add_column("Timestamp", no_wrap=True)
table.add_column("Datasets")
for idx, meta in enumerate(recent, 1):
table.add_row(
str(idx),
meta.get("run_id", "?"),
meta.get("timestamp", "?"),
", ".join(meta.get("demo_datasets", [])) or "-",
)
console.print(table)
choice = console.input("\nSelect run number (or 'q' to quit): ").strip()
if choice.lower() == "q":
return None
try:
choice_idx = int(choice)
if 1 <= choice_idx <= len(recent):
return recent[choice_idx - 1].get("run_id")
except ValueError:
pass
console.print("[red]Invalid selection[/red]")
return None
def _watch_results(run_id: str, interval: int, detailed: bool) -> None:
"""Continuously monitor and display results."""
assert console is not None
console.print(f"\n[bold]👀 Watching results for run: {run_id}[/bold]")
console.print(f"Refreshing every {interval} seconds. Press Ctrl+C to stop.\n")
try:
with Live(console=console, refresh_per_second=1) as live:
while True:
display = _generate_results_display(
run_id, detailed, is_live=True, raw=False
)
live.update(display)
time.sleep(interval)
except KeyboardInterrupt:
console.print("\n[yellow]Stopped watching[/yellow]")
def _display_results(run_id: str, detailed: bool, raw: bool) -> None:
"""Display results once."""
assert console is not None
display = _generate_results_display(run_id, detailed, is_live=False, raw=raw)
console.print(display)
def _show_errors(run_id: str, task_filter: str | None = None) -> None:
"""Display error messages and info for tasks."""
from rich.syntax import Syntax
assert console is not None
if task_filter:
console.print(f"\n[bold cyan]📋 Task Info: {task_filter}[/bold cyan]\n")
# Load results to find the task and call_id
results = load_run_results.remote(run_id)
if "error" in results:
console.print(
Panel(f"[red]❌ {results['error']}[/red]", border_style="red")
)
return
# Find the task in results
tasks = results.get("tasks", [])
task = None
for t in tasks:
if t.get("id") == task_filter:
task = t
break
if not task:
console.print(f"[red]❌ Task '{task_filter}' not found[/red]\n")
console.print("[yellow]Available tasks:[/yellow]")
for t in tasks[:20]:
status_color = "green" if t.get("status") == "Success" else "red"
console.print(
f" [{status_color}]•[/{status_color}] {t.get('id', 'unknown')}"
)
if len(tasks) > 20:
console.print(f" [dim]... and {len(tasks) - 20} more[/dim]")
return
# Find the call_id
console.log("results")
console.log(results)
call_ids = results.get("call_ids", [])
call_id = None
for cid in call_ids:
if cid.get("task_id") == task_filter:
call_id = cid.get("call_id")
break
# Display task info
status = task.get("status", "Unknown")
status_color = "green" if status == "Success" else "red"
console.print(f"[bold]Status:[/bold] [{status_color}]{status}[/{status_color}]")
console.print(f"[bold]Dataset:[/bold] {task.get('dataset_name', 'unknown')}")
console.print(
f"[bold]Optimizer:[/bold] {task.get('optimizer_name', 'unknown')}"
)
console.print(f"[bold]Model:[/bold] {task.get('model_name', 'unknown')}\n")
# Show error if failed
if status == "Failed":
error_msg = task.get("error_message", "No error message available")
console.print(
Panel(
Syntax(error_msg, "python", theme="monokai", word_wrap=True),
title="[red]Error Message[/red]",
border_style="red",
)
)
console.print()
# Show call_id and try to construct logs URL
if call_id:
# Try to get workspace from metadata
metadata = results.get("metadata", {})
workspace = metadata.get("workspace")
if workspace:
# Construct the logs URL
logs_url = f"https://modal.com/apps/{workspace}/main/deployed/opik-optimizer-benchmarks?&&activeTab=logs&fcId={call_id}"
console.print(
Panel(
f"[bold]Function Call ID:[/bold]\n[cyan]{call_id}[/cyan]\n\n[bold]View Logs:[/bold]\n[link={logs_url}]{logs_url}[/link]",
title="[cyan]📋 Logs[/cyan]",
border_style="cyan",
)
)
else:
console.print(
Panel(
f"[cyan]{call_id}[/cyan]\n\n[dim]Search for this call ID in your Modal dashboard to view logs[/dim]",
title="[cyan]📋 Function Call ID[/cyan]",
border_style="cyan",
)
)
return
# No filter - show all failed tasks
console.print(f"\n[bold red]🔍 Error Details for Run: {run_id}[/bold red]\n")
results = load_run_results.remote(run_id)
if "error" in results:
console.print(Panel(f"[red]❌ {results['error']}[/red]", border_style="red"))
return
tasks = results.get("tasks", [])
failed_tasks = [t for t in tasks if t.get("status") == "Failed"]
if not failed_tasks:
console.print("[green]✅ No failed tasks found![/green]")
return
console.print(f"[yellow]Found {len(failed_tasks)} failed task(s)[/yellow]\n")
for i, task in enumerate(failed_tasks, 1):
task_id = task.get("id", "unknown")
error_msg = task.get("error_message", "No error message available")
console.print(
Panel(
Syntax(error_msg, "python", theme="monokai", word_wrap=True),
title=f"[{i}/{len(failed_tasks)}] {task_id}",
border_style="red",
expand=False,
)
)
console.print() # Empty line between errors
def _generate_results_display(
run_id: str, detailed: bool, is_live: bool, raw: bool
) -> Any:
"""Generate rich display of results."""
from benchmarks.utils.display import generate_results_display
results = load_run_results.remote(run_id)
return generate_results_display(run_id, detailed, is_live, results, raw)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Check and display benchmark results from Modal",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# List all available runs
modal run benchmarks/check_results.py --list-runs
# Check results for a specific run
modal run benchmarks/check_results.py --run-id run_20250423_153045
# Watch for new results (live monitoring)
modal run benchmarks/check_results.py --run-id run_20250423_153045 --watch
# Show detailed metrics breakdown
modal run benchmarks/check_results.py --run-id run_20250423_153045 --detailed
# Show full error messages for failed tasks
modal run benchmarks/check_results.py --run-id run_20250423_153045 --show-errors
# Show full logs and details for a specific task (exact task ID)
modal run benchmarks/check_results.py --run-id run_20250423_153045 --task "ai2_arc_evolutionary_optimizer_openai/gpt-4o-mini"
""",
)
parser.add_argument(
"--run-id",
type=str,
default=None,
help="ID of the benchmark run to check",
)
parser.add_argument(
"--list-runs",
action="store_true",
help="List all available benchmark runs",
)
parser.add_argument(
"--watch",
action="store_true",
help="Continuously monitor for new results",
)
parser.add_argument(
"--detailed",
action="store_true",
help="Show detailed metrics breakdown",
)
parser.add_argument(
"--show-errors",
action="store_true",
help="Show full error messages for all failed tasks",
)
parser.add_argument(
"--raw",
action="store_true",
help="Show raw JSON payload (otherwise a concise summary table is shown)",
)
parser.add_argument(
"--task",
type=str,
default=None,
help="Show full logs and details for specific task ID (exact match required)",
)
parser.add_argument(
"--watch-interval",
type=int,
default=30,
help="Seconds between updates when watching (default: 30)",
)
args = parser.parse_args()
main(
run_id=args.run_id,
list_runs=args.list_runs,
watch=args.watch,
detailed=args.detailed,
raw=args.raw,
show_errors=args.show_errors,
task=args.task,
watch_interval=args.watch_interval,
)