Model-Optimizer 评估运行指南:基于 nemo-evaluator-launcher 的 INPUT → EXPLORE → ACT 三阶段实践

原创2026-09-26 17:08:061,748 阅读
文章标签:人工智能大模型模型优化模型量化模型压缩

Model-Optimizer 评估运行指南:基于 nemo-evaluator-launcher 的 INPUT → EXPLORE → ACT 三阶段实践

导读

本文围绕 nemo-evaluator-launcher(简称 NEL)展开,讲解如何在 Model-Optimizer 仓库中通过一条 uv run nemo-evaluator-launcher run --config <path.yaml> 命令,将 LLM 评估任务提交到 Slurm 集群上运行。文章以仓库内 launching-evals 技能 中定义的 INPUT → EXPLORE → ACT 三阶段工作流为主线,完整覆盖从收集配置、预检解析到提交运行的每一步操作,并结合同技能下的进度监控、失败调试与结果分析文档,给出可立即照做的命令与排查清单。读完本文,你将能独立完成一次评估任务的配置确认、干跑预检、正式提交、状态轮询与结果拉取。

1. 评估运行的整体工作流

在 Model-Optimizer 仓库的 launching-evals 技能中,评估运行被组织为一个必须按顺序执行的全流程:

  1. 使用 nel-assistant 技能创建或修改评估配置;若用户提供了历史运行,则以该次运行的 config.yml 产物作为起点;
  2. 运行评估(执行本文所述的 INPUT → EXPLORE → ACT 三阶段,见 run-evaluation.md);
  3. 监控进度(每次 nel run 之后强制执行):反复轮询状态直至 SUCCESS 或 FAILED,见 check-progress.md;
  4. 到达终态后的处理:SUCCESS 时分析结果(见 analyze-results.md),FAILED 时调试失败运行(见 debug-failed-runs.md)。

本仓库中,launching-evals 的定位是“运行、监控、分析、调试评估”,它不负责创建或修改评估配置——配置的增删改由 nel-assistant 类技能负责,这一点在技能描述中明确标注。

2. INPUT:收集运行需求

运行评估前,先以清单方式从用户处收集四项输入(对应 run-evaluation.md 的 Phase 1):

  • Config path(必填):要运行的 YAML 配置文件路径。注意,如果上一步骤已经处理过该配置,路径可能已存在于上下文中,无需重复询问。
  • Credentials(按需):部分任务需要环境变量(如 AWS_ACCESS_KEY_ID、HF_TOKEN)。先检查工作区根目录是否存在 .env 文件;若不存在,请用户创建并写入凭据。NEL 会自动从工作区根目录读取 .env,因此不需要手动 source。
  • Task filter(可选):通过 -t <task_name> 只运行指定任务。
  • Overrides(可选):通过 -o key=value 覆盖配置项。
  • Dry-run first?(可选):是否先用 --dry-run 预览解析后的配置与 sbatch 脚本,再正式提交。

一个完整的收集结果示例:config=examples/eval_config.yaml、无凭据需求、-t swebench-verified、无覆盖项、先干跑。

3. EXPLORE:干跑预检解析结果

进入第二阶段后,核心动作是把 --dry-run 标志加到最终命令上,预览两样东西:

  1. 解析后的完整配置(resolved config):即 YAML 合并所有继承、默认值与 -o 覆盖之后的最终形态;
  2. sbatch 脚本:NEL 将据此向 Slurm 提交的作业脚本内容。
uv run nemo-evaluator-launcher run --config <path.yaml> --dry-run

干跑的价值在于把错误前置:未填写的必填字段(MissingMandatoryValue,即未填充的 ???)、类型不匹配(ValidationError)、YAML 语法错误(ScannerError)都可以在这一步被捕获,而不必等到提交到集群后才失败(见 debug-failed-runs.md 的 Config validation 一节)。

4. ACT:提交评估任务

4.1 基本提交命令

确认干跑结果无误后,正式提交:

uv run nemo-evaluator-launcher run --config <path.yaml>

4.2 常用变体

场景 命令
只跑单个任务 uv run nemo-evaluator-launcher run --config <path.yaml> -t <a_single_task_to_be_run_by_name>
跑多个指定任务 uv run nemo-evaluator-launcher run --config <path.yaml> -t <task_name_1> -t <task_name_2> ...
覆盖采样数等参数 uv run nemo-evaluator-launcher run --config <path.yaml> -o evaluation.nemo_evaluator_config.config.params.limit_samples=10 ...
干跑预览 uv run nemo-evaluator-launcher run --config <path.yaml> --dry-run

注意 -o 覆盖使用的是 Hydra 风格的 ++ 语法:例如验证修复后的小样本冒烟测试写作 -o ++evaluation.nemo_evaluator_config.config.params.limit_samples=10。

4.3 提交后的必做动作

提交命令会打印 Invocation ID: <id>,这是后续所有监控与排查的锚点。每次 nel run 之后必须轮询状态,直到出现 SUCCESS 或 FAILED(技能将监控设为强制步骤)。轮询命令:

uv run nemo-evaluator-launcher status <invocation_id> --json

--json 用于机器可读输出。需要更详细信息(输出路径、Slurm 作业 ID、集群主机名等)时使用:

uv run nemo-evaluator-launcher info <invocation_id>

4.4 提交前必须知道的三个关键事实

  • Slurm 作业对(job pairs):NEL 会提交一对 Slurm 作业——一个 RUNNING 作业加一个 PENDING 的重启作业(用于 4 小时 walltime 到期后自动续跑)。不要取消 PENDING 重启作业,它们是预期且必需的。
  • data_parallel_size 是按节点计的:dp_size=1 配合 num_nodes=8 意味着总共 8 个模型实例(每节点一个),由 haproxy 负载均衡,不要把 dp_size 理解为全局副本数。
  • HF 离线缓存要求:配置了 HF_HUB_OFFLINE=1 的 config 需要模型已预下载到各集群的 HF 缓存中。在新集群上运行模型前,务必先询问用户该模型是否已缓存。若未缓存,在集群登录节点执行:
python3 -m venv hf_cli && source hf_cli/bin/activate && pip install huggingface_hub
HF_HOME=<your_hf_cache_path> hf download <model>

在 lustre 风格的 HPC 集群上,缓存路径通常在 /lustre/.../<group>/users/<username>/cache/huggingface 下。缺少该步骤时 vLLM 会以 LocalEntryNotFoundError 失败。

5. 运行中的状态机:RUNNING / SUCCESS / FAILED 分支

提交完成后进入监控阶段(check-progress.md),按状态分流:

  1. 获取状态与任务名:status <invocation_id> --json;
  2. 查基准专属文档:在 references/benchmarks/ 下寻找与任务名匹配的文档(如 terminal-bench-* 任务对应 terminal-bench-general-info.md),这些文档包含监控命令与基准特有上下文;
  3. 从配置取输出路径:info <invocation_id> 得到 output_dir 与集群主机名。

然后:

  • RUNNING:SSH 到集群查看 client-*.log 中的实时进度(优先使用基准文档中的监控命令);
  • SUCCESS:转入结果分析(analyze-results.md);
  • FAILED:转入失败调试(debug-failed-runs.md)。

仓库内的测试用例(tests.json)对状态语义做了额外约束:RUNNING 只表示 Slurm 作业在运行,不代表 vLLM 服务器已成功启动;且诊断根因时必须同时查看 client 日志与 server 日志——client 日志常只呈现症状(如 unknown_agent_error、failed_samples_policy),而 server 日志才揭示真正原因(如 CUDA OOM、上下文长度溢出、vLLM 校验错误)。

6. 失败运行的五步调试清单

当状态为 FAILED 时,按 debug-failed-runs.md 执行:

Step 1 收集信息:失败运行的 Invocation ID,以及用户观察到的症状(超时、OOM 等)。

Step 2 获取作业信息:

uv run nemo-evaluator-launcher status <invocation_id> --json
uv run nemo-evaluator-launcher info <invocation_id>

从中提取状态、日志远程路径、Slurm 作业 ID、集群登录主机名。

Step 3 本地复制并检查日志:优先把需要的日志复制到本地再分析(每次 SSH 命令都需要用户批准,远程逐条读取会打断流程,而复制过多又太慢):

uv run nemo-evaluator-launcher info <invocation_id> --copy-logs /tmp/debug-logs
LOGS=/tmp/debug-logs/<job_id>/logs
cat $LOGS/slurm-*.log                                  # 作业级错误:调度、walltime、抢占
tail -200 $LOGS/server-*-0.log                         # 部署错误:OOM、缺模型、坏参数、驱动不匹配
grep -i -E '(error|exception|failed|OOM|killed)' $LOGS/server-*-0.log | tail -50
cat $LOGS/proxy-*.log 2>/dev/null                      # 负载均衡错误(仅多实例时存在)
tail -200 $LOGS/client-*.log                           # 评估错误:数据集、评分器、超时、限流

四类日志的职责边界:slurm-*.log 覆盖作业级错误(健康检查超时、账号/分区错误、walltime 超限、抢占);server-*-N.log 覆盖部署错误(CUDA OOM、缺失模型/检查点、坏的 extra_args、GPU 驱动不匹配、镜像拉取失败);proxy-*.log 是 HAProxy 负载均衡器错误;client-*.log 覆盖评估错误(数据集访问、评分器错误、超时、限流)。

Step 4 应用修复(常见修复对照):

症状 修复
CUDA OOM 增大 deployment.tensor_parallel_size 跨更多 GPU 分片;多节点时增大 execution.num_nodes 并设置 deployment.pipeline_parallel_size;最后手段是在 deployment.extra_args 加 --max-model-len <lower_value>。不要把量化当作首选修复,应优先扩展算力
缺失模型/检查点 FileNotFoundError/RepositoryNotFoundError/GatedRepoError: 403 —— 核对 deployment.checkpoint_path 或 deployment.hf_model_handle;门控模型在 deployment.env_vars 设置 HF_TOKEN
坏的 extra_args unrecognized arguments/unexpected keyword argument —— 对照部署引擎版本检查参数(例如 --rope-scaling 在 vLLM > 0.11.0 中已移除)
镜像拉取失败 manifest not found/pyxis: child 1 failed —— 核实镜像 tag 存在;本地 GitLab 仓库需去掉 URL 中的端口后缀(如 :5005)
GPU 驱动不匹配 CUDA driver version is insufficient —— 换用与宿主机 CUDA 驱动匹配的旧版容器镜像
健康检查超时/连接拒绝 服务未启动——先查 server 日志;增大 execution.endpoint_readiness_timeout(秒),Slurm 默认 null(回退到 walltime)
评估中途服务器崩溃 Connection reset by peer —— 查 server 日志是否 OOM;降低 parallelism(并发请求数);查 Slurm 日志是否抢占或 walltime 超限
缺失数据集 DatasetNotFoundError/GatedRepoError: 403 —— 在 HuggingFace 接受许可,在 evaluation[].env_vars 设置 HF_TOKEN
评分器错误 ScorerError/KeyError —— 检查模型输出格式、adapter_config、max_new_tokens
超时 TimeoutError/Request timed out —— 增大 evaluation[].nemo_evaluator_config.config.params.request_timeout;过载时降低 max_new_tokens 或 parallelism
配置校验失败 MissingMandatoryValue/ValidationError/ScannerError —— 先跑 --dry-run 前置捕获
Walltime 超限 CANCELLED DUE TO TIME LIMIT —— NEL 的重启作业对会自动续跑,这通常是预期行为而非失败;仅当跨重启仍无进展时才增大 execution.walltime
抢占 CANCELLED DUE TO PREEMPTION —— 重启作业对应自动续跑;若无,改用不可抢占分区或重跑
容器找不到 同时适用于 deployment.image 与任务级 eval 容器;本地 GitLab 仓库去掉 URL 端口后缀

Step 5 验证修复,按序执行四条命令:

# 1. 干跑(只校验配置不运行)
uv run nemo-evaluator-launcher run --config <config> --dry-run

# 2. 冒烟测试(10 个样本)
uv run nemo-evaluator-launcher run --config <config> -o ++evaluation.nemo_evaluator_config.config.params.limit_samples=10

# 3. 只跑失败的那一个任务
uv run nemo-evaluator-launcher run --config <config> -t <failed_task> -o ++evaluation.nemo_evaluator_config.config.params.limit_samples=10

# 4. 监控
uv run nemo-evaluator-launcher status <new_invocation_id> --json

正确性警告:部分修复手段会改变评估结果——--max-model-len 限制上下文窗口可能截断提示词,temperature 影响采样随机性,top_p 是核采样阈值,max_new_tokens 过低会截断输出。因此在量化对比等场景中,必须用相同基准版本、任务配置、服务参数、token 限制与基础设施,差异才可归因于量化本身(见 analyze-results.md 的 Model baseline comparison 一节)。

7. 结果拉取与产物管理

运行成功后,产物按 Invocation ID 组织。核心原则:先用 nel info 发现路径——产物若在本地直接读取,若在远端则 SSH 探索后仅 rsync 所需内容。

# 快速复制日志(调试用,速度快)
uv run nemo-evaluator-launcher info <invocation_id> --copy-logs ./evaluation-results/

# 远端产物按需同步
rsync -avzP <user>@<hostname>:<artifacts_path>/{results.yml,eval_factory_metrics.json,config.yml} ./evaluation-results/<invocation_id>.<job_index>/artifacts/

技能文档特别警告:不要使用 nemo-evaluator-launcher export --dest local——它只写出汇总 JSON(processed_results.json),即使接受 --copy_logs/--copy-artifacts 标志也不会真正复制日志或产物。nel info --copy-artifacts 虽然可用,但对大型基准会复制所有内容(非常慢)。标准产物之外,基准还会在子目录产生额外产物,需主动探索。其他常用命令还包括:resume <invocation_id> 重新调度失败/中断运行(在原运行目录重新提交已有的 run.sub)、ls runs --since 1d 列出近期运行、ls tasks(以及 --from_container nvcr.io/nvidia/eval-factory/simple-evals:26.03 按容器列出任务)。

8. 基准专项:SWE-bench 与 Terminal Bench 的进度与产物要点

8.1 SWE-bench(OpenHands harness)

  • 快速取分:artifacts/results.yml、artifacts/.../swebench_summary.json;官方逐实例结果看 artifacts/.../output.report.json(顶层键含 dataset、evaluation_method、resolved、resolved_count、results、total_instances,每行 results 含 instance_id、resolved、error、exit_code);逐实例 token 与调试数据看 output.jsonl / output_errors.jsonl / logs/instance_<id>.log。
  • 实时进度:运行期间官方结果文件尚未生成,应使用增量写入的 tasks.jsonl。该文件是 append-only 的,重启后同一 task_id 可多次出现,行数会超过基准规模——必须按 task_id 去重(最后一条生效)。技能提供了内置去重脚本(见 swebench-general-info.md),输出形如 success: 120, TOTAL unique: 123/500, REMAINING: 377。
  • 状态语义:tasks.jsonl 顶层的 success 表示最终官方评测判定已解决;failure 表示有可评估补丁但未解决;error 表示硬性运行时失败(超时、上下文超限等)。termination.reason=status=stuck 只是对话结束态(OpenHands 检测到无进展模式),SWE-bench 仍可能收集补丁并最终判定为 success 或 failure。

8.2 Terminal Bench(agentic 终端任务)

  • 产物结构:artifacts/terminal-bench/ 下的 tb.lock(完整解析后配置,最佳复现依据)、run_metadata.json、task_status.json(每任务一条,success 具有粘性——任务成功后后续失败不会覆盖)、tb_results.json(最丰富的单个产物,逐 trial 含 is_resolved、failure_mode、token 用量、trajectory_length、时间戳、asciinema recording_path,聚合含 pass_at_k、accuracy、failure_mode_counts 等)。逐 trial 子目录 artifacts/terminal-bench/<task>/<trial>/ 下还有 agent 日志 agent-logs/episode-N/(prompt.txt、response.txt、含思维链的 debug.json)和终端快照 panes/(pre-agent.txt、post-agent.txt、post-test.txt)。
  • 失败模式枚举(见 failure_mode.py):UNSOLVED、TOKEN_LIMIT_EXCEEDED、PARSE_ERROR、FATAL_LLM_PARSE_ERROR、CONTEXT_LENGTH_EXCEEDED、OUTPUT_LENGTH_EXCEEDED、TEST_TIMEOUT、AGENT_TIMEOUT、UNKNOWN_AGENT_ERROR、AGENT_INSTALLATION_FAILED、UNKNOWN。failed_samples_policy 默认 default,只对“不公平失败”(UNKNOWN、UNKNOWN_AGENT_ERROR、AGENT_INSTALLATION_FAILED)停跑。
  • 缓解 agent 超时:高 AGENT_TIMEOUT 率(85%+)源于推理争抢。推荐组合拳——把一次 n_samples: 8, parallelism: 100 的大运行拆成 8 个 n_samples: 1, parallelism: 24 的独立单样本运行,水平扩展多个小作业(8x1 模式)。监控 client-*.log 时因其含 ANSI 格式化内容,需用 grep -a。

9. 与仓库整体评估体系的衔接

launching-evals 并非孤立存在。在同一仓库的 evaluation 技能 及其 references/launcher-workflow.md、references/slurm.md 中,可以看到 NEL 在更大评估管线中的位置——包括按 Slurm 账号/项目组合码(PPP,即 cluster_config.yaml 的 account 字段)组织任务、payload_modifier 拦截器(通过 params_to_remove 列表如 <a href="https://link.gitcode.com/i/343351bcae65114b0efe4e7340d5a02b" target="_blank">max_tokens, max_completion_tokens] 剥离输出长度限制,让推理模型按需长思考)等机制。对评估结果感兴趣时,还可结合本仓库的 [llm_eval 示例(mmlu.py、lm_eval_hf.py、lm_eval_trtllm.py、simple_evals.py)了解非 NEL 路径下的轻量评估方式。

结语

运行一次可靠的 LLM 评估并不复杂,关键在于流程纪律:INPUT 阶段把配置、凭据、任务过滤与覆盖项收集齐;EXPLORE 阶段用 --dry-run 把配置与 sbatch 脚本前置校验;ACT 阶段提交后立即进入强制轮询,并依据 SUCCESS / FAILED 分别走结果分析或五步调试清单。文中所有命令与清单均可在 plugins/modelopt/skills/launching-evals 目录下找到对应文档原文,建议在实际提交前通读一遍 SKILL.md 的 Key Facts,尤其是 Slurm 作业对、data_parallel_size 按节点计、HF 离线缓存这三个容易踩坑的事实。

登录后查看全文
Model-Optimizer