Ouzhang's picture
Add files using upload-large-folder tool
d91766b verified
Raw
History Blame Contribute Delete
5.61 kB
from __future__ import annotations
import argparse
import json
import os
import re
import shutil
import sys
import tempfile
import time
from pathlib import Path
from typing import Optional
from examples.engine_lm_eval.config import BenchmarkConfig
try:
from lm_eval.__main__ import cli_evaluate
except ImportError:
cli_evaluate = None
from examples.engine_lm_eval.lm_eval_model import EngineOpenAILM # noqa: F401
def _slugify(value: str) -> str:
value = re.sub(r"[^A-Za-z0-9._-]+", "_", value.strip())
value = re.sub(r"_+", "_", value).strip("_.")
return value or "unknown"
def _resolve_include_path(config: BenchmarkConfig) -> Optional[Path]:
raw = config.eval.include_path
if raw is not None and str(raw).strip() == "":
return None
if raw:
p = Path(raw).expanduser()
if not p.is_absolute():
p = Path(os.getcwd()) / p
return p.resolve()
return (Path(__file__).resolve().parents[2] / "diffulex_bench" / "tasks").resolve()
def _task_name_to_yaml_map(include_root: Path) -> dict[str, Path]:
mapping: dict[str, Path] = {}
for yml in include_root.rglob("*.yaml"):
try:
text = yml.read_text(encoding="utf-8")
except Exception:
continue
m = re.search(r"(?m)^\s*task:\s*([^\s#]+)\s*$", text)
if m:
mapping.setdefault(m.group(1).strip(), yml)
return mapping
def _rewrite_task_data_files(task_yaml: Path, data_files: str) -> bool:
text = task_yaml.read_text(encoding="utf-8")
replacement_value = json.dumps(str(Path(data_files).expanduser().resolve()))
replaced, n = re.subn(r"(?m)^(\s*data_files:\s*).*$", rf"\1{replacement_value}", text, count=1)
if n == 0:
return False
task_yaml.write_text(replaced, encoding="utf-8")
return True
def _resolve_include_path_with_override(config: BenchmarkConfig) -> tuple[Optional[Path], Optional[Path]]:
include_path = _resolve_include_path(config)
data_files = config.eval.dataset_data_files
if not data_files:
return include_path, None
if include_path is None or not include_path.is_dir():
return include_path, None
tmp_root = Path(tempfile.mkdtemp(prefix="engine_lm_eval_tasks_")).resolve()
tmp_tasks = tmp_root / "tasks"
shutil.copytree(include_path, tmp_tasks, dirs_exist_ok=True)
task_map = _task_name_to_yaml_map(tmp_tasks)
for task_name in [name.strip() for name in config.eval.dataset_name.split(",") if name.strip()]:
task_yaml = task_map.get(task_name)
if task_yaml is not None:
_rewrite_task_data_files(task_yaml, data_files)
return tmp_tasks, tmp_root
def _run_output_dir(config: BenchmarkConfig) -> Path:
engine_name = _slugify(config.endpoint.engine_name)
root = Path(config.eval.output_dir).expanduser() / engine_name
if not config.eval.use_run_subdirectory:
root.mkdir(parents=True, exist_ok=True)
return root.resolve()
stamp = time.strftime("%Y%m%d_%H%M%S")
model_name = _slugify(Path(config.endpoint.model).name)
task_name = _slugify(config.eval.dataset_name.replace(",", "_"))
out = root / f"run_{stamp}_{engine_name}_{model_name}_{task_name}"
out.mkdir(parents=True, exist_ok=True)
return out.resolve()
def config_to_model_args(config: BenchmarkConfig, save_dir: Path) -> str:
args = {
"engine_name": config.endpoint.engine_name,
"base_url": config.endpoint.base_url,
"model": config.endpoint.model,
"api_key": config.endpoint.api_key,
"tokenizer_path": config.endpoint.tokenizer_path or config.endpoint.model,
"batch_size": 1,
"max_new_tokens": config.eval.max_tokens,
"temperature": config.eval.temperature,
"ignore_eos": config.eval.ignore_eos,
"add_bos_token": config.eval.add_bos_token if config.eval.add_bos_token is not None else False,
"apply_chat_template": config.endpoint.apply_chat_template,
"chat_completions": config.endpoint.chat_completions,
"timeout": config.endpoint.timeout,
"verify": config.endpoint.verify,
"save_dir": str(save_dir),
"trust_remote_code": config.endpoint.trust_remote_code,
}
return ",".join(f"{k}={v}" for k, v in args.items() if v is not None)
def main() -> None:
parser = argparse.ArgumentParser(description="Minimal lm-eval runner backed by an OpenAI-compatible API engine")
parser.add_argument("--config", required=True, help="Path to YAML config.")
args = parser.parse_args()
if cli_evaluate is None:
raise RuntimeError("lm-evaluation-harness is not installed.")
config = BenchmarkConfig.from_yaml(args.config)
output_dir = _run_output_dir(config)
include_path, cleanup_root = _resolve_include_path_with_override(config)
model_args = config_to_model_args(config, output_dir)
output_file = output_dir / f"{_slugify(config.endpoint.engine_name)}_lm_eval_results.json"
sys.argv = [
"lm_eval",
"--model",
"engine_oai",
"--model_args",
model_args,
"--tasks",
config.eval.dataset_name,
"--output_path",
str(output_file),
]
if include_path is not None:
sys.argv.extend(["--include_path", str(include_path)])
if config.eval.dataset_limit:
sys.argv.extend(["--limit", str(config.eval.dataset_limit)])
try:
cli_evaluate()
finally:
if cleanup_root is not None:
shutil.rmtree(cleanup_root, ignore_errors=True)
if __name__ == "__main__":
main()