"""MMLU evaluation runner for E2E tests. Simplified evaluation runner that uses local eval implementations with cleaner logging for CI/CD environments. Usage: from infra.run_eval import run_eval from types import SimpleNamespace args = SimpleNamespace( base_url="http://127.0.0.1:30000", model="meta-llama/Llama-3.1-8B-Instruct", eval_name="mmlu", num_examples=64, num_threads=32, temperature=0.1, ) metrics = run_eval(args) """ from __future__ import annotations import logging import os import time from dataclasses import dataclass from typing import TYPE_CHECKING, Any if TYPE_CHECKING: from .simple_eval_common import Eval from .simple_eval_common import ChatCompletionSampler, set_ulimit from .simple_eval_mmlu import MMLU_DATASET_URL logger = logging.getLogger(__name__) @dataclass class EvalConfig: """Configuration for running an evaluation.""" base_url: str model: str | None = None eval_name: str = "mmlu" num_examples: int = 64 num_threads: int = 32 temperature: float = 0.0 max_tokens: int = 2048 host: str = "127.0.0.1" port: int = 30000 def _get_eval(eval_name: str, num_examples: int, num_threads: int) -> "Eval": """Get the evaluation object by name.""" if eval_name == "mmlu": from .simple_eval_mmlu import MMLUEval return MMLUEval(MMLU_DATASET_URL, num_examples, num_threads) else: raise ValueError(f"Unknown eval: {eval_name}. Supported: mmlu") def run_eval(args: Any) -> dict: """Run an evaluation and return metrics. Args: args: Configuration object with attributes: - base_url: Base URL of the server (e.g., "http://127.0.0.1:30000") - model: Model name/path (optional, will be auto-detected) - eval_name: Evaluation name ("mmlu") - num_examples: Number of examples to evaluate - num_threads: Number of parallel threads - temperature: Sampling temperature Returns: Dict with metrics including 'score' key. """ set_ulimit() if "OPENAI_API_KEY" not in os.environ: os.environ["OPENAI_API_KEY"] = "EMPTY" # Build base URL base_url = getattr(args, "base_url", None) if base_url: base_url = base_url.rstrip("/") # Remove trailing slashes if not base_url.endswith("/v1"): base_url = f"{base_url}/v1" else: host = getattr(args, "host", "127.0.0.1") port = getattr(args, "port", 30000) base_url = f"http://{host}:{port}/v1" eval_name = getattr(args, "eval_name", "mmlu") num_examples = getattr(args, "num_examples", 64) num_threads = getattr(args, "num_threads", 32) temperature = getattr(args, "temperature", 0.0) max_tokens = getattr(args, "max_tokens", 2048) model = getattr(args, "model", None) logger.info( "Starting %s eval: %d examples, %d threads, temp=%.2f", eval_name, num_examples, num_threads, temperature, ) # Create sampler sampler = ChatCompletionSampler( model=model, max_tokens=max_tokens, base_url=base_url, temperature=temperature, ) # Get eval object eval_obj = _get_eval(eval_name, num_examples, num_threads) # Run evaluation start_time = time.perf_counter() result = eval_obj(sampler) latency = time.perf_counter() - start_time # Build metrics metrics = result.metrics.copy() if result.metrics else {} metrics["score"] = result.score metrics["latency"] = latency logger.info( "%s eval complete: score=%.3f, latency=%.1fs, model=%s", eval_name, result.score, latency, sampler.model, ) return metrics