- 大模型
- 推理模型
- 微调
- 模型推理服务
【免费下载链接】s1
s1: Simple test-time scaling
本指南围绕 s1(Simple test-time scaling)仓库中eval/rebase/sglang/benchmark/multi_document_qa目录的官方基准测试方案展开,完整讲解如何从 PDF 语料构建多文档问答数据集,并在 SGLang、vLLM、Guidance 等多种推理后台上运行同一任务,量化对比各后端的准确率与延迟。读完本文,你将掌握该基准的完整命令链路、数据集生成原理、请求并发控制与结果输出格式,并能直接复跑实验。
一、基准测试背景与目录结构
多文档问答(Multi-Document QA)是检验长上下文推理与指令跟随能力的典型场景:系统需要从多篇给定文档中检索线索,并以极短的答案回答具体问题。在 s1 的评测体系中,该任务用于评估不同推理引擎在"长提示 + 多文档拼接"负载下的服务能力,是 sglang 基准目录 中专门针对长上下文场景设计的 benchmark 之一。
本基准位于 eval/rebase/sglang/benchmark/multi_document_qa/,包含 4 个文件:
| 文件 | 作用 |
|---|---|
| README.md | 官方运行说明:三个后端 + 数据集构建命令 |
| bench_sglang.py | 使用 SGLang 前端(sgl.function+fork/join)的评测脚本 |
| bench_other.py | 面向 vLLM、LightLLM、SRT-Raw、Guidance 等后端的通用评测脚本 |
| build_dataset.py | 从 Llama 2 论文 PDF 文本构建questions.jsonl数据集的脚本 |
整个流程分两步:先用build_dataset.py生成数据,再启动推理服务并运行 bench 脚本。下文按官方 README 的顺序展开,并深入到各脚本源码。
二、构建数据集:从 PDF 论文文本到 QA 样本
2.1 官方操作步骤
README 给出的数据集构建命令如下:
pip install PyPDF2 python3 build_dataset.py同时也给出了一个不依赖build_dataset.py、直接用 PyPDF2 抽取 PDF 文本的最小示例:
import PyPDF2 with open('llama2.pdf', 'rb') as file: reader = PyPDF2.PdfReader(file) text = '' for page_num in range(len(reader.pages)): text += reader.pages[page_num].extract_text() with open('output.txt', 'w') as text_file: text_file.write(text)2.2 源码级解析:token 切分与样本组装
build_dataset.py 内部完成的工作远不止 PDF 抽取,其核心流程为:
- 读取纯文本:从
llama2.txt读取全文(对应上一步抽取出的output.txt),合并空行(content.replace("\n\n", "\n")),得到连续的论文文本。 - 统计 token 数:加载
meta-llama/Llama-2-7b-chat-hf的 tokenizer(transformers.AutoTokenizer.from_pretrained),打印全文 token 总量,用于确定文档块尺寸。 - 按 token 长度切段:以空行
\n\n为自然段落边界把文本拆成parts,然后按segment_len = 1100(token)为单位聚合,累积超过阈值即切出一个文档片段,最终取前 30 个片段作为documents。 - 写入
questions.jsonl:每条记录是单行 JSON,包含documents(30 个片段)、questions(10 道问题)与answers(对应答案)。
值得注意的是,脚本内嵌的问题与答案均直接取材自 Llama 2 论文,例如:"What is the number of parameters in the largest Llama 2 model?"(答案70 B)、"What is the batch size of fine-tuning?"(答案64)、"Which activation function is used in Llama?"(答案SwiGLU)。这些问题都要求模型从多段文档中定位事实,且答案长度极短(三个词以内),便于自动化判分。
2.3 数据集格式约定
最终产物questions.jsonl的每行格式为:
{"documents": ["<segment0>", "<segment1>", ...], "questions": ["...", ...], "answers": ["...", ...]}该格式被 bench_sglang.py 与 bench_other.py 通过sglang.utils.read_jsonl(args.data_path)直接消费:两者都只读取lines[0]第一条记录,取前num_questions道问题,并从documents中取前 10 个片段作为上下文。
三、Benchmark SGLang:利用 fork/join 并行编码多文档
3.1 启动推理服务
README 要求先以 sglang 服务端模式启动模型(以 CodeLlama-7B-Instruct 为例):
python3 -m sglang.launch_server --model-path codellama/CodeLlama-7b-instruct-hf --port 30000默认端口30000与 test_utils.py 中add_common_sglang_args_and_parse设定的--port默认值一致,因此客户端脚本在未显式传--port时也能直连该服务。
3.2 运行评测脚本
python3 bench_sglang.py --num-questions 10 --parallel 1其中--num-questions 10表示评测前 10 个问题;--parallel 1表示并发线程数(默认值为 64,见add_common_sglang_args_and_parse,该函数同时提供--host(默认http://127.0.0.1)、--port(默认 30000)、--backend(默认srt)与--result-file(默认result.jsonl)等参数)。
3.3 提示词模板与 fork/join 机制
bench_sglang.py 的核心是@sgl.function装饰的多文档问答程序:
@sgl.function def multi_document_qa(s, docs, question): s += sgl.user_begin() s += "Pleaes answer a question according to given documents.\n" s += "Question:" + question + "Documents begin.\n" forks = s.fork(len(docs)) forks += lambda i: docs[i] forks.join("concate_and_append") s += "\nDocuments end." s += ("\n\nBased on the above documents, please answer this question:\n" + question + "\nAnswer in three words or fewer.") s += sgl.user_end() s += sgl.assistant(sgl.gen("answer", max_tokens=16))这段代码是 SGLang 结构化生成(structured generation)能力的典型体现,几个关键点:
s.fork(len(docs))与forks += lambda i: docs[i]:把 N 个文档分发到 N 个并行分支,每个分支独立编码一段文档;forks.join("concate_and_append"):将各分支编码得到的 KV cache 按顺序拼接并追加回主程序,实现"多文档一次性拼接进上下文"的长上下文构造。其底层实现在 interpreter.py 的ProgramStateGroup.join方法中:concate_and_append模式调用SglConcateAndAppend(self.states)拼接各分支状态,随后sync()同步执行流;而默认的gather_variable模式则是把子分支中新增的变量回收到父状态(见 interpreter.py)。sgl.gen("answer", max_tokens=16):声明一个命名生成点,限定答案最多 16 个 token。gen的完整签名定义在 api.py,支持temperature、top_p、top_k、stop、regex、choices等采样控制参数。- 提示词设计:明确要求 "Answer in three words or fewer."(三个词以内作答),与数据集答案极短的性质匹配,也方便后续判分。
3.4 批量请求、判分与结果落盘
主函数main的评测逻辑为:
tic = time.time() states = multi_document_qa.run_batch( arguments, temperature=0, num_threads=args.parallel) latency = time.time() - tic- 通过
run_batch批量执行,temperature=0保证结果可复现,num_threads=args.parallel控制并发; - 判分规则:将答案
answer.lower()与标签(label.lower().split(" "))做包含匹配——只要标签的每个词都出现在模型输出中即判对(见 bench_sglang.py),打印Accuracy与Latency; - 结果输出:状态快照写入
tmp_output_{backend}.txt,并把一条 JSON 记录追加到result.jsonl,字段包括task、backend、num_gpus、latency、num_requests、accuracy以及嵌套的other元信息(num_questions、parallel)。
后端选择由select_sglang_backend完成:srt前缀走RuntimeEndpoint(连接已启动的 sglang 服务),其中srt-no-parallel会额外关闭并行编解码;gpt-前缀则走 OpenAI 兼容接口(见 test_utils.py)。
四、Benchmark vLLM:通用评测脚本的 HTTP 调用方式
4.1 启动 vLLM 服务
python3 -m vllm.entrypoints.api_server --tokenizer-mode auto --model codellama/CodeLlama-7b-instruct-hf --disable-log-requests --port 21000 --gpu 0.97端口21000对应add_common_other_args_and_parse中 vLLM 后端的默认端口。--tokenizer-mode auto按模型自动匹配 tokenizer,--gpu 0.97限制显存利用率。
4.2 运行评测脚本
python3 bench_other.py --backend vllm --num-questions 64与 SGLang 版不同,bench_other.py 面向"裸 HTTP 服务"类后端,通过partial(call_generate_vllm, url=url, temperature=0)绑定生成函数。call_generate_vllm的请求体定义在 test_utils.py:向/generate发送prompt、temperature、max_tokens、stop、n等字段,并从返回的text中截掉输入 prompt 前缀得到生成结果。
由于 vLLM 原生 API 不提供多分支拼接能力,bench_other.py采用"串行拼接"等价实现:"".join(docs)把所有文档直接拼成一段长文本(见 bench_other.py),同时在提示词前后包裹 Llama 2 的 Chat 模板标记:
USER_PREFIX = "[INST] " USER_SUFFIX = " [/INST]" ASSISTANT_PREFIX = "" ASSISTANT_SUFFIX = " </s><s>"这保证了非 SGLang 后端也能生成与bench_sglang.py对齐的对话式提示词。并发控制方面,--parallel默认 64;等于 1 时串行tqdm遍历,大于 1 时用ThreadPoolExecutor并发执行(见 bench_other.py),判分与结果写入逻辑与bench_sglang.py完全一致。
4.3 其他可选后端
add_common_other_args_and_parse声明的合法后端还包括lightllm、srt-raw、lmql、llama.cpp(见 test_utils.py),其默认端口映射为:vLLM 21000、LightLLM 22000、LMQL 23000、SRT-Raw 30000。bench_other.py已实现的调用路径有:
- lightllm:
call_generate_lightllm发送inputs+parameters(temperature、max_new_tokens、stop_sequences)到/generate; - srt-raw:
call_generate_srt_raw发送text+sampling_params,直接面向 SGLang Runtime 原生生成接口,便于与bench_sglang.py的"纯前端结构化"路径做对照。
五、Benchmark Guidance:约束解码后端的对比评测
5.1 运行评测脚本
python3 bench_other.py --backend guidance --num-questions 32 --parallel 1Guidance 后端在bench_other.py中走独立代码路径(见 bench_other.py):加载 GGUF 格式的模型权重,并以内嵌闭包完成生成:
model = models.LlamaCpp("/home/ubuntu/model_weights/CodeLlama-7b-instruct-hf.gguf", n_gpu_layers=-1, n_ctx=11000) def generate(prompt, max_tokens, stop): out = model + prompt + gen(name="answer", max_tokens=max_tokens, temperature=0, stop=stop) return out["answer"] # warmup generate("Hello!", max_tokens=8, stop=None)几个必须注意的实操细节:
- 模型路径是硬编码的:
/home/ubuntu/model_weights/CodeLlama-7b-instruct-hf.gguf为脚本内写死的路径,复跑前需要把该路径替换为本地实际存放的 GGUF 文件(或先用llama.cpp转换工具从 HF 权重生成); - 上下文窗口需调大:
n_ctx=11000是因为任务要容纳 10 段 × 1100 token 的文档,默认上下文会溢出; --parallel 1的深层原因:README 中 Guidance 后端建议并行度取 1,同时源码显示 Guidance 后端会把文档数从 10 降为 7——注释明确写到 "due to OOM"(见 bench_other.py),这是本地 LlamaCpp 推理显存受限的工程折中;- 预热(warmup):正式评测前先调用一次
generate("Hello!", ...),避免首次推理的模型加载开销污染延迟统计。
六、指标解读与结果对比
无论使用哪个后端,脚本都会在终端打印两行关键指标:
Accuracy: 0.xxx Latency: 0.xxx- Accuracy(准确率):所有测试问题中,模型答案包含标签全部单词的占比。由于答案被限制在三个词以内、且多数为数字或专有名词,该判分对"检索到正确事实"相当敏感,但对排序、语法不做要求;
- Latency(延迟,秒):
run_batch/ 并发执行整体耗时,即从发出第一批请求到全部返回的墙钟时间。
所有后端的结果统一追加写入result.jsonl(可用--result-file自定义),单行 JSON 结构如:
{"task": "multi_document_qa", "backend": "vllm", "num_gpus": 1, "latency": 12.345, "num_requests": 64, "accuracy": 0.875, "other": {"num_questions": 64, "parallel": 1}}这种统一 schema 便于把 SGLang、vLLM、Guidance、LightLLM、SRT-Raw 各后端的指标汇总到同一文件做横向对比:在num_requests相同的条件下,latency反映引擎吞吐与并发能力,accuracy反映长上下文下的指令跟随质量(注意 Guidance 因 OOM 使用 7 个文档,与 10 文档的组别严格来说样本规模不同)。
七、快速复跑清单
以下是本基准的最小完整操作序列(在当前仓库eval/rebase/sglang/benchmark/multi_document_qa目录下执行):
- 准备语料:获取 Llama 2 论文 PDF(
llama2.pdf),参考 README 中的 PyPDF2 示例抽取为llama2.txt; - 构建数据集:
pip install PyPDF2与transformers,运行python3 build_dataset.py生成questions.jsonl; - 启动服务(任选其一):
- SGLang:
python3 -m sglang.launch_server --model-path codellama/CodeLlama-7b-instruct-hf --port 30000 - vLLM:
python3 -m vllm.entrypoints.api_server --tokenizer-mode auto --model codellama/CodeLlama-7b-instruct-hf --disable-log-requests --port 21000 --gpu 0.97 - Guidance:准备
CodeLlama-7b-instruct-hf.gguf并修改 bench_other.py 中的硬编码路径;
- SGLang:
- 运行评测:SGLang 用
python3 bench_sglang.py --num-questions 10 --parallel 1,其余后端用python3 bench_other.py --backend <vllm|guidance|lightllm|srt-raw> --num-questions 64 [--parallel 1]; - 查看结果:终端读取
Accuracy/Latency,汇总数据在result.jsonl,生成状态快照在tmp_output_<backend>.txt。
需注意的适用前提:脚本默认以codellama/CodeLlama-7b-instruct-hf与 Llama 2 系 tokenizer 为基准(bench_other.py的--model-path默认值为meta-llama/Llama-2-7b-chat-hf);若替换模型,需同步检查提示词中的 Chat 模板标记([INST] ... [/INST])是否匹配目标模型的对话格式。文档与源码均来自当前仓库,具体行级实现可进一步查阅 bench_sglang.py、bench_other.py 与 build_dataset.py。
- 大模型
- 推理模型
- 微调
- 模型推理服务
【免费下载链接】s1
s1: Simple test-time scaling
相关推荐
s1 项目 LLM Judge 多维度文章评分基准:基于 SGLang 与 vLLM 的端到端评测实践
s1 项目 LLM Judge 多维度文章评分基准:基于 SGLang 与 vLLM 的端到端评测实践 本文围绕 s1(Simple test time sca
大模型推理模型微调模型推理服务s1 项目多链推理(multi-chain reasoning)基准评测实战:基于 SGLang fork/join 的多数投票推理与多后端对比
s1 项目多链推理(multi chain reasoning)基准评测实战:基于 SGLang fork/join 的多数投票推理与多后端对比 导读 本篇文章
大模型推理模型微调模型推理服务SGLang 多后端 MT-Bench 基准测试实战:sglang / vllm / lightllm 两轮对话评测与源码解析
SGLang 多后端 MT Bench 基准测试实战:sglang / vllm / lightllm 两轮对话评测与源码解析 本指南以 s1 仓库中 eval
大模型推理模型微调模型推理服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考