(
dataset: pd.DataFrame,
metadata: EvalMetadata | None,
output_file: str,
num_workers: int,
process_instance_func: Callable[
[pd.Series, EvalMetadata, bool], Awaitable[EvalOutput]
],
max_retries: int = 3, # number of retries for each instance
)
| 128 | # queue.close() |
| 129 | |
| 130 | def run_evaluation( |
| 131 | dataset: pd.DataFrame, |
| 132 | metadata: EvalMetadata | None, |
| 133 | output_file: str, |
| 134 | num_workers: int, |
| 135 | process_instance_func: Callable[ |
| 136 | [pd.Series, EvalMetadata, bool], Awaitable[EvalOutput] |
| 137 | ], |
| 138 | max_retries: int = 3, # number of retries for each instance |
| 139 | ): |
| 140 | logger = LoggerManager.get_logger() |
| 141 | use_multiprocessing = num_workers > 1 |
| 142 | |
| 143 | if metadata is not None: |
| 144 | logger.info( |
| 145 | f'Evaluation started with Agent {metadata.agent_func}\n' |
| 146 | ) |
| 147 | else: |
| 148 | logger.info('Running evaluation without metadata.', title='Warning', color='red') |
| 149 | logger.info(f'Evaluation started with {num_workers} workers.') |
| 150 | |
| 151 | total_instances = len(dataset) |
| 152 | pbar = tqdm(total=total_instances, desc='Instances processed') |
| 153 | output_fp = open(output_file, 'a') |
| 154 | |
| 155 | try: |
| 156 | if use_multiprocessing: |
| 157 | # 使用队列来收集结果 |
| 158 | results_queue = mp.Queue() |
| 159 | active_processes = [] |
| 160 | instances_iter = dataset.iterrows() |
| 161 | instances_completed = 0 |
| 162 | |
| 163 | while instances_completed < total_instances: |
| 164 | # 启动新进程,直到达到worker数量限制 |
| 165 | while len(active_processes) < num_workers and instances_completed < total_instances: |
| 166 | try: |
| 167 | _, instance = next(instances_iter) |
| 168 | # 创建非守护进程 |
| 169 | p = mp.Process( |
| 170 | target=_process_and_queue, |
| 171 | args=(process_instance_func, instance, metadata, True, max_retries, results_queue), |
| 172 | daemon=False # 关键:设置为非守护进程 |
| 173 | ) |
| 174 | p.start() |
| 175 | time.sleep(3) |
| 176 | active_processes.append((p, time.time())) # 记录进程启动时间 |
| 177 | except StopIteration: |
| 178 | break |
| 179 | |
| 180 | # 检查完成的进程 |
| 181 | for p, start_time in active_processes[:]: |
| 182 | if not p.is_alive(): |
| 183 | try: |
| 184 | # 给进程1分钟时间来清理资源 |
| 185 | p.join(timeout=60) |
| 186 | if p.is_alive(): |
| 187 | logger.warning(f"Process {p.pid} cleanup timeout, force terminating...") |
no test coverage detected