vLLM GSM8K 精度评测实战:基于独立评测脚本与 OpenAI 兼容服务的正确性验证体系

发布时间:2026/9/7 3:39:42
vLLM GSM8K 精度评测实战:基于独立评测脚本与 OpenAI 兼容服务的正确性验证体系 vLLM GSM8K 精度评测实战基于独立评测脚本与 OpenAI 兼容服务的正确性验证体系【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm本文介绍 vLLM 仓库中tests/evals/gsm8k/目录下的独立 GSM8K 精度评测体系它作为 lm-eval-harness 的替代方案通过「独立评测脚本 vllm serve服务 YAML 模型配置 pytest 参数化」的组合将模型数学推理能力验证变成可复现的 CI 回归测试。读完本文后你可以掌握如何在本地手动运行 GSM8K 评测、如何编写一份新的模型评测配置并理解评测脚本在 prompt 构造、答案抽取、评分指标与通过判定上的完整实现细节。1. 定位与背景为什么需要独立的 GSM8K 评测GSM8K 是一个小学数学应用题数据集test 集共 1319 题5-shot 设置下的准确率是业界衡量 LLM 推理能力的常用回归指标。vLLM 的这套实现被明确定位为lm-eval-harness GSM8K 评测的替代品其目标是在 CI 中对大量模型/量化/并行配置做「精度不回归」把关同时获得更好的性能与更细的控制粒度见 README。整个目录由三类文件构成gsm8k_eval.py核心评测脚本既可通过命令行独立运行对接vllm serve的 HTTP 端点也提供evaluate_gsm8k_offline()供进程内直接调用test_gsm8k_correctness.py 与 conftest.pypytest 集成负责按配置清单拉起vllm serve服务、执行评测并按阈值断言configs/ 目录数百份 YAML 模型配置及若干按硬件/场景分组的配置清单文件models-small.txt、models-h200.txt、models-blackwell.txt等子目录 configs/humming/、configs/moe-refactor/、configs/moe-refactor-dp-ep/ 分别对应不同评测专项。此外test_gsm8k_offloading.py 复用了同一套evaluate_gsm8k()入口用于验证 CPU KV offloading 连接器在回载 KV 数据后精度不下降说明该脚本已成为 vLLM 多个正确性回归测试的公共评测底座。2. 两种运行方式2.1 pytest 方式与 Buildkite CI 一致pytest -s -v tests/evals/gsm8k/test_gsm8k_correctness.py \ --config-list-fileconfigs/models-small.txt--config-list-file选项由 conftest.py 通过pytest_addoption注册默认值就是configs/models-small.txt。pytest_generate_tests钩子会解析该清单文件每行一个 YAML 文件名#开头为注释以清单文件所在目录为基准解析出各配置文件的绝对路径并对config_filenamefixture 做参数化——即清单里有几份配置就会生成几个测试用例测试 id 取配置文件的 stem 名。相对路径解析规则值得注意conftest 先尝试「测试目录 相对路径」失败后再尝试「当前工作目录 相对路径」见 conftest.py 中pytest_generate_tests。因此configs/models-small.txt既可以配合cd tests/evals/gsm8k后运行也可以从仓库根目录写成tests/evals/gsm8k/configs/models-small.txt。以 models-small.txt 为例它当前包含 8 份小模型/多量化配置Qwen3-0.6B-FP8.yaml Llama-3.2-1B-Instruct-INT8-CT.yaml Llama-3-8B-Instruct-nonuniform-CT.yaml Qwen2.5-VL-3B-Instruct-FP8-dynamic.yaml Qwen1.5-MoE-W4A16-CT.yaml DeepSeek-V2-Lite-Instruct-FP8.yaml Qwen3-30B-A3B-MXFP4A16.yaml gemma-4-E4B-it-qat-mobile-ct.yaml2.2 独立脚本方式手动评测先启动一个 vLLM 服务再直接运行评测脚本# 先启动 vLLM 服务 vllm serve Qwen/Qwen2.5-1.5B-Instruct --port 8000 # 运行评测 python tests/evals/gsm8k/gsm8k_eval.py --port 8000gsm8k_eval.py的完整命令行参数来自 gsm8k_eval.py 中main()的 argparse 定义如下参数默认值说明--num-shots5few-shot 示例数量取自 GSM8K train 集前 N 条--num-questions1319评测题目数量1319 为 test 集全量会自动min截断--max-tokens256每题最大生成 token 数--hosthttp://127.0.0.1服务地址--port8000服务端口--temperature0.0采样温度默认贪心解码--seed42随机种子保证可复现--max-concurrency无不限流通过aiohttp.TCPConnector(limit...)限制并发请求数--save-results无将结果 dict 以 JSON 落盘评测输出包含 Accuracy、Invalid responses、总时延、Questions/s、总输出 token 数与 Output tokens/s 六项指标可整体保存为 JSON 便于归档对比。3. 评测配置 YAML 字段详解README 给出的基础格式如下model_name: Qwen/Qwen2.5-1.5B-Instruct accuracy_threshold: 0.54 # 最低期望精度 num_questions: 1319 # 题目数默认test 集全量 num_fewshot: 5 # 来自 train 集的 few-shot 示例数 server_args: --max-model-len 4096 --tensor-parallel-size 2 --moe-backend flashinfer_cutlass # 服务启动参数 env: # 环境变量可选 VLLM_LOGGING_LEVEL: DEBUG结合 test_gsm8k_correctness.py 中对eval_config的全部解析完整字段清单比 README 示例更丰富字段必填默认值/来源用途model_name是—传给vllm serve的模型 IDHF 仓库名或本地量化模型路径accuracy_threshold是—GSM8K 精度阈值低于threshold - tolerance则断言失败num_questions是1319评测题数num_fewshot是5few-shot 数server_args否任意vllm serve参数用shlex.split解析以支持引号env否{}dict注入到服务进程的环境变量tolerance否0.08精度容差实际判定式为measured threshold - tolerancemax_tokens否256每题最大生成 token 数temperature否0.0采样温度seed否42随机种子use_chat_completions否FalseTrue 时走/v1/chat/completions而非/v1/completions面向 instruction-tuned 模型gen_prefix否拼接在Answer:之后的生成前缀max_concurrency否不限并发请求上限request_timeout_seconds否600单请求超时rocm_request_timeout_seconds否—ROCm 平台专用的超时覆盖值startup_max_wait_seconds否1200服务启动最大等待同时注入VLLM_ENGINE_READY_TIMEOUT_Smin_acceptance_length否无投机解码配置的额外断言draft 平均接受长度下限配置示例可以取自仓库真实文件。Qwen3-0.6B-FP8.yaml 是一份典型的最小配置model_name: Qwen/Qwen3-0.6B-FP8 accuracy_threshold: 0.375 num_questions: 1319 num_fewshot: 5 server_args: --enforce-eager --max-model-len 4096而 Qwen3.5-397B-A17B-NVFP4-DEP2-MTP.yaml 展示了大模型 数据并行 MTP 投机解码的复杂写法YAML 折叠标量-可让server_args跨多行model_name: nvidia/Qwen3.5-397B-A17B-NVFP4 accuracy_threshold: 0.88 tolerance: 0.03 num_questions: 1319 num_fewshot: 5 max_tokens: 12000 server_args: - --max-model-len 16384 --data-parallel-size 2 --enable-expert-parallel --max-num-seqs 256 --spec-method mtp --spec-tokens 3use_chat_completions: true则出现在 chat 类模型的配置中例如 Laguna-XS.2-NVFP4.yaml 与 DiffusionGemma-26B-A4B-it-FP8-dynamic.yamlmax_concurrency: 100出现在 GLM-5.2-NVFP4-TP2-PCP2-EP.yaml 中。4. 评测脚本核心实现解析gsm8k_eval.py4.1 数据集加载与 prompt 构造评测数据并不打包在仓库中load_gsm8k_data()gsm8k_eval.py L47-L58从VLLM_S3_BUCKET_URL/ci-datasets/gsm8k/下载train.jsonl与test.jsonl并缓存在系统临时目录tempfile.gettempdir()下按 URL 末段命名已存在则直接复用重复运行无需再下载。_build_gsm8k_prompts()L149-L177完成 few-shot prompt 拼装从 train 集取前num_shots条按Question: ...\nAnswer:{gen_prefix} ...\n\n格式拼接为前缀遍历 test 集前num_questions题追加Question: {题目}\nAnswer:{gen_prefix}用get_answer_value()提取标准答案数值并assert所有 label 均非INVALID-9999999保证题目本身可判分。注意gen_prefix的用途对某些 chat 模板会把Assistant:前缀写进 chat template 的模型可在生成侧补一个前缀避免重复输出。4.2 答案抽取与判分get_answer_value()L69-L78的判分逻辑去掉逗号后用regex找全部数字串取最后一个数字做ast.literal_eval抽不到数字则记为INVALID。这与 lm-eval-harness 的extract_last_number思路一致invalid_rate指标即统计抽取失败的比例用于区分「答错」与「格式崩坏」。_score_gsm8k()L180-L207汇总的结果 dict 包含accuracy逐题数值相等判定后的均值、invalid_rate、latency整批墙钟时延、questions_per_second、total_output_tokens来自响应usage.completion_tokens累加、tokens_per_second、num_questions、num_shots、max_tokens与timestamp。4.3 异步批量请求evaluate_gsm8k()L210-L286内部用asyncioaiohttp为每道题建一个协程经tqdm.gather并发执行stop 序列固定为[Question, Assistant:, |separator|]防止模型把后续题目继续生成出来。默认对/v1/completions发原始 prompt配置use_chat_completions后改走/v1/chat/completions此时必须提供model参数见 test_gsm8k_correctness.py 中run_gsm8k_eval的传参。单请求超时由aiohttp.ClientTimeout(totalrequest_timeout_seconds)控制max_concurrency非空时通过TCPConnector(limit...)限流。脚本还保留了evaluate_gsm8k_offline()L289-L337对进程内的vllm.LLM对象走llm.generate()/llm.chat()后者面向 instruction-tuned 模型支持透传chat_template_kwargsprompt 构造与判分逻辑与在线版完全一致——这正是 test_gsm8k_offloading.py 直接复用evaluate_gsm8k的原因。5. pytest 集成流程从配置到断言test_gsm8k_correctness(config_filename)test_gsm8k_correctness.py L91 起对每份 YAML 的执行链路如下平台适配跳过若干配置依赖特定内核或平台如 MXFP4A16 的 Marlin 内核仅 CUDA、GFX950 上的 AITER 量化、ROCm 上的 DeepSeek 大模型因 agent 磁盘/驱逐问题命中即在非目标平台pytest.skip。组装服务参数shlex.split(server_args)解析 YAML 中的服务参数再统一追加--trust-remote-code --disable-uvicorn-access-log。启动服务用RemoteOpenAIServer来自 tests/utils.py以配置里的envdict 拉起vllm serve其中框架自动注入VLLM_ENGINE_READY_TIMEOUT_S startup_max_wait_seconds默认 1200s。执行评测run_gsm8k_eval()从服务 URL 拆出 host/port 后调用evaluate_gsm8k()ROCm 平台优先取rocm_request_timeout_seconds覆盖超时例如 DeepSeek-V2-Lite-Instruct-FP8.yaml 将 ROCm 超时放到 1800s。精度断言核心判定式为measured_metric expected_metric - toltol默认 0.08可在配置中收窄如 MTP 配置用 0.03。投机解码附加断言若配置了min_acceptance_length测试会请求服务的/metrics解析vllm:spec_decode_num_drafts_total与vllm:spec_decode_num_accepted_tokens_total计算平均接受长度1 accepted/drafts1.0 意味着所有 draft 全被拒绝投机解码没有收益理论上限为1 num_speculative_tokens并断言其不低于下限——这防止「精度达标但投机解码完全失效」的静默回归。6. 实践指南为我的模型添加一份 GSM8K 配置基于以上实现新增一份配置的操作步骤为在 configs/ 下新建模型名-量化/并行方式.yaml必填四要素model_name、accuracy_threshold、num_questions、num_fewshot先手动跑一遍标定基线vllm serve 模型 你的server_argspython tests/evals/gsm8k/gsm8k_eval.py --port 8000 --save-results result.json用实测精度留出余量后设定accuracy_threshold阈值语义是「允许最多tolerance的回退」chat 模板敏感、completion prompt 表现异常的模型加use_chat_completions: true生成链很长的大模型按需上调max_tokens参考 MTP 配置的 12000把文件名追加进对应的清单文件如models-small.txt、models-h200.txt、models-blackwell.txt或 humming/moe-refactor 专项清单的config-*.txt即可被 CI 的pytest --config-list-file...自动覆盖若服务冷启动慢调大startup_max_wait_seconds若单请求经常超 600s显式设置request_timeout_secondsROCm 用rocm_request_timeout_seconds。从源码结构看该目录的评测模式YAML 配置驱动 服务化评测 阈值容差断言已被 test_gsm8k_offloading.py 二次复用为 KV offloading 的回归护栏它用同一evaluate_gsm8k()连跑两轮 GSM8K中间通过/reset_prefix_cache丢弃 GPU 前缀缓存而保留 CPU 缓存迫使第二轮从 CPU 回载 KV以此验证回载路径不产生静默数据损坏。这也侧面说明了把评测逻辑收敛到独立脚本而非绑定某一测试框架带来的复用价值。适用前提与限制评测需要能访问VLLM_S3_BUCKET_URL指定的 S3 桶以下数据集文件首次运行会下载并缓存到系统临时目录pytest 模式会真实拉起vllm serve子进程需要本机具备配置中server_args要求的 GPU 数量如--tensor-parallel-size 2需要 2 卡与模型权重下载能力num_questions会按 test 集长度截断当前实现下该上限即 1319精度阈值是针对特定模型/量化组合的经验值跨模型不可直接借用新增配置务必先标定基线。【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻