2828import signal
2929import subprocess
3030import sys
31+ import time
3132import traceback
3233import uuid
3334from contextlib import contextmanager
@@ -561,6 +562,9 @@ def _aiperf(
561562)
562563_LMMS_EVAL_RESERVED_EXTRA_ARG_FLAGS = frozenset (
563564 {
565+ "--batch-size" ,
566+ "--batch_size" ,
567+ "--model" ,
564568 "--model_args" ,
565569 "--model-args" ,
566570 "--output_path" ,
@@ -570,6 +574,7 @@ def _aiperf(
570574)
571575_DEFAULT_LMMS_EVAL_TIMEOUT_SECONDS = 3600.0
572576_LMMS_EVAL_PROCESS_CLEANUP_TIMEOUT_SECONDS = 10.0
577+ _LMMS_EVAL_PROCESS_GROUP_POLL_INTERVAL_SECONDS = 0.1
573578
574579
575580def _as_cli_bool (value : bool ) -> str :
@@ -688,6 +693,8 @@ def _model_arg_string(values: Mapping[str, Any]) -> str:
688693def _merge_lmms_eval_model_args (settings : Mapping [str , Any ], checkpoint : str ) -> str :
689694 raw = settings .get ("model_args" )
690695 checkpoint_arg = str (settings .get ("checkpoint_arg" , "model" ))
696+ if checkpoint_arg != "model" :
697+ raise ValueError ("downstream_evaluation.config.checkpoint_arg must be 'model'" )
691698 topology = dict (settings .get ("topology" ) or {})
692699 canonical_topology = normalize_vllm_topology (topology ) if topology else {}
693700 reserved_fields = _lmms_eval_reserved_model_arg_fields (checkpoint_arg )
@@ -766,14 +773,17 @@ def _lmms_eval_command(
766773 * ,
767774 checkpoint : str ,
768775 output_path : Path ,
769- ) -> tuple [list [str ], dict [str , str ], float | None ]:
776+ ) -> tuple [list [str ], dict [str , str ], float ]:
770777 """Build a deterministic lmms-eval CLI invocation for one realized checkpoint."""
771778
779+ model = str (settings .get ("model" , "vllm" ))
780+ if model != "vllm" :
781+ raise ValueError ("downstream_evaluation.config.model must be 'vllm'" )
772782 tasks = "," .join (_configured_lmms_eval_tasks (settings ))
773783 argv = [
774784 * _command_prefix (settings ),
775785 "--model" ,
776- str ( settings . get ( " model" , "vllm" )) ,
786+ model ,
777787 "--model_args" ,
778788 _merge_lmms_eval_model_args (settings , checkpoint ),
779789 "--tasks" ,
@@ -816,10 +826,15 @@ def _lmms_eval_command(
816826 env [str (key )] = str (value )
817827 if settings .get ("cache_dir" ) is not None :
818828 env .setdefault ("LMMS_EVAL_HOME" , str (settings ["cache_dir" ]))
819- timeout = settings .get ("timeout_seconds" , settings .get ("timeout" ))
829+ timeout = settings .get ("timeout_seconds" )
830+ if timeout is None :
831+ timeout = settings .get ("timeout" )
820832 if timeout is None :
821833 timeout = _DEFAULT_LMMS_EVAL_TIMEOUT_SECONDS
822- return argv , env , float (timeout )
834+ timeout = float (timeout )
835+ if not math .isfinite (timeout ) or timeout <= 0 :
836+ raise ValueError ("lmms-eval timeout must be a finite positive number" )
837+ return argv , env , timeout
823838
824839
825840def _metric_key (value : Any ) -> str :
@@ -1002,12 +1017,22 @@ def _lmms_eval_process_group_exists(process: subprocess.Popen[str]) -> bool:
10021017 return True
10031018
10041019
1020+ def _wait_for_lmms_eval_process_group_exit (
1021+ process : subprocess .Popen [str ], * , deadline : float
1022+ ) -> None :
1023+ while _lmms_eval_process_group_exists (process ):
1024+ remaining = deadline - time .monotonic ()
1025+ if remaining <= 0 :
1026+ return
1027+ time .sleep (min (_LMMS_EVAL_PROCESS_GROUP_POLL_INTERVAL_SECONDS , remaining ))
1028+
1029+
10051030def _run_lmms_eval_process (
10061031 argv : list [str ],
10071032 * ,
10081033 cwd : str ,
10091034 env : Mapping [str , str ],
1010- timeout : float | None ,
1035+ timeout : float ,
10111036) -> subprocess .CompletedProcess [str ]:
10121037 process = subprocess .Popen (
10131038 argv ,
@@ -1026,15 +1051,21 @@ def _run_lmms_eval_process(
10261051 stdout , stderr = process .communicate (timeout = _LMMS_EVAL_PROCESS_CLEANUP_TIMEOUT_SECONDS )
10271052 except subprocess .TimeoutExpired :
10281053 _signal_lmms_eval_process_group (process , signal .SIGKILL )
1054+ cleanup_deadline = time .monotonic () + _LMMS_EVAL_PROCESS_CLEANUP_TIMEOUT_SECONDS
10291055 try :
10301056 stdout , stderr = process .communicate (
10311057 timeout = _LMMS_EVAL_PROCESS_CLEANUP_TIMEOUT_SECONDS
10321058 )
10331059 except subprocess .TimeoutExpired as kill_error :
10341060 stdout , stderr = kill_error .output , kill_error .stderr
1061+ _wait_for_lmms_eval_process_group_exit (process , deadline = cleanup_deadline )
10351062 else :
10361063 if _lmms_eval_process_group_exists (process ):
10371064 _signal_lmms_eval_process_group (process , signal .SIGKILL )
1065+ _wait_for_lmms_eval_process_group_exit (
1066+ process ,
1067+ deadline = time .monotonic () + _LMMS_EVAL_PROCESS_CLEANUP_TIMEOUT_SECONDS ,
1068+ )
10381069 raise subprocess .TimeoutExpired (
10391070 argv ,
10401071 error .timeout ,
0 commit comments