ARM Linux + Ascend NPU 环境下基于 vLLM API 的 AISBench 遇到的实际问题实录~
主包准备的是文档推荐的数据集准备指南 — AISBench 评测工具 1.0 文档开源数据集。
小样本阶段: [0:8] accuracy = 87.50% [0:50] accuracy = 88.00%
分段评测阶段: [0:500]
原始 AISBench summary accuracy = 91.60% Post=500,Received=496,Failed=4,empty prediction=8。
对 8 条空预测样本进行手动补跑后,5 条补跑正确,修正 accuracy = 92.60%。
关键问题定位:
1. max_out_len 太小会导致模型只返回 reasoning,content 为空,prediction 为空;
2. 全量一次性 request_rate=0 会导致大量请求失败;
3. 分段评测 + request_rate 限速 + retry 增加可以显著提升稳定性;
4. 空预测需要单独检查,必要时补跑或降低请求速率。
一、问题 1:accuracy = 0.00,prediction 全是空
现象
一开始 BoolQ 8 条样本跑通了流程,但是结果是:
BoolQ accuracy = 0.00
查看 prediction 文件发现:
"prediction": "",
"gold": "B"
同时 infer 日志里有:
Request xxx has no output. Please check the server response.
Post: 8 | Received: 8 | Failed: 0
说明:
API 请求发出去了;
服务端也返回了;
但 AISBench 没拿到有效 prediction。
根因
手动 curl 调 API 后发现返回是:
"content": null,
"reasoning": "Thinking Process: ...",
"finish_reason": "length"
这说明模型一直在生成 reasoning,但是 max_tokens 太小,还没来得及生成最终 content,就被截断了。
AISBench 默认读取的是:
message["content"]
所以 content=null 时,AISBench 的 prediction 就变成空字符串。
解决方法
把 AISBench 模型配置里的:
max_out_len
调大。它对应 API 里的:
max_tokens
执行:
cd ~/benchmark
python - <<'PY'
from pathlib import Path
import re
p = Path("ais_bench/benchmark/configs/models/vllm_api/vllm_api_general_chat.py")
s = p.read_text(encoding="utf-8")
s = re.sub(r"max_out_len\s*=\s*\d+", "max_out_len=2048", s)
p.write_text(s, encoding="utf-8")
print("updated max_out_len to 2048")
PY
grep -n "max_out_len" ais_bench/benchmark/configs/models/vllm_api/vllm_api_general_chat.py
验证方法
手动 curl 测一条:
curl http://127.0.0.1:8006/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6-35b-a3b",
"messages": [
{
"role": "user",
"content": "Ethanol fuel -- The energy balance for corn ethanol produced in the US is about 1.3 output units for one input unit. Question: does ethanol take more energy to make than it produces?\nA. Yes\nB. No\nPlease answer with only A or B. /no_think\nAnswer:"
}
],
"temperature": 0.2,
"max_tokens": 2048
}'
成功后返回里出现:
"content": "\n\nB",
"finish_reason": "stop"
说明模型已经生成了正式答案,AISBench 可以解析 prediction。
二、问题 2:原始 prediction 看起来和 gold 不相等,但 AISBench accuracy 是对的
现象
跑完 8 条后,summary 显示:
accuracy = 87.50
但自己直接比较:
prediction == gold
发现全是 False,比如:
prediction: '\n\nA. Yes'
gold: 'A'
correct: False
根因
AISBench 不是直接用原始 prediction 和 gold 比较,而是先经过后处理函数:
first_capital_postprocess
BoolQ 配置里有:
pred_postprocessor=dict(type=first_capital_postprocess)
所以实际比较的是:
'\n\nA. Yes' -> 'A'
'\n\nB. No' -> 'B'
解决方法:用 AISBench 同样的后处理方式复现 accuracy
cd ~/benchmark
python - <<'PY'
import json
from pathlib import Path
from ais_bench.benchmark.utils.text_postprocessors import first_capital_postprocess
run = Path("outputs/default/20260713_132830")
p = run / "predictions/qwen36-35b-a3b-vllm-api/BoolQ.json"
data = json.load(open(p, "r", encoding="utf-8"))
correct = 0
total = 0
for k, v in data.items():
raw_pred = v.get("prediction", "")
gold = v.get("gold", "")
pred = first_capital_postprocess(raw_pred)
ok = pred == gold
correct += int(ok)
total += 1
print("=" * 80)
print("id:", k)
print("raw prediction:", repr(raw_pred[:120]))
print("processed prediction:", repr(pred))
print("gold:", repr(gold))
print("correct:", ok)
print("=" * 80)
print("accuracy:", correct / total * 100)
PY
得到:
accuracy: 87.5
说明 AISBench 的结果是对的。
三、问题 3:8 条样本太少,需要扩大验证
已完成结果
先跑 8 条:
BoolQ [0:8]
accuracy = 87.50
然后扩大到 50 条:
BoolQ [0:50]
accuracy = 88.00
说明 AISBench 调用 vLLM API 的评测链路已经稳定跑通。
小样本配置代码
新建 demo 配置:
cd ~/benchmark
cp ais_bench/benchmark/configs/datasets/SuperGLUE_BoolQ/SuperGLUE_BoolQ_gen_0_shot_str.py \
ais_bench/benchmark/configs/datasets/SuperGLUE_BoolQ/SuperGLUE_BoolQ_gen_0_shot_str_demo.py
然后加入:
test_range='[0:8]'
对应修改代码:
cd ~/benchmark
python - <<'PY'
from pathlib import Path
p = Path("ais_bench/benchmark/configs/datasets/SuperGLUE_BoolQ/SuperGLUE_BoolQ_gen_0_shot_str_demo.py")
s = p.read_text(encoding="utf-8")
old = """BoolQ_reader_cfg = dict(
input_columns=['question', 'passage'],
output_column='label',
)"""
new = """BoolQ_reader_cfg = dict(
input_columns=['question', 'passage'],
output_column='label',
test_range='[0:8]',
)"""
s = s.replace(old, new)
p.write_text(s, encoding="utf-8")
print("created demo config:", p)
PY
改成 50 条
cd ~/benchmark
python - <<'PY'
from pathlib import Path
import re
p = Path("ais_bench/benchmark/configs/datasets/SuperGLUE_BoolQ/SuperGLUE_BoolQ_gen_0_shot_str_demo.py")
s = p.read_text(encoding="utf-8")
s = re.sub(r"test_range=['\"]\[0:\d+\]['\"]", "test_range='[0:50]'", s)
p.write_text(s, encoding="utf-8")
print("updated test_range to [0:50]")
PY
运行:
ais_bench --models vllm_api_general_chat \
--datasets SuperGLUE_BoolQ_gen_0_shot_str_demo \
--summarizer example
结果:
BoolQ accuracy = 88.00
四、问题 4:直接跑全量时大量请求失败
现象
你直接跑全量 BoolQ:
nohup ais_bench --models vllm_api_general_chat \
--datasets SuperGLUE_BoolQ_gen_0_shot_str \
--summarizer example \
> boolq_full_$(date +%Y%m%d_%H%M%S).log 2>&1 &
跑到后面出现大量错误:
Request failed: Exceeded maximum retry attempts (2)
最终日志显示:
Post: 3270
Received: 333
Failed: 2937
根因
模型配置里原来是:
request_rate = 0
retry = 2
AISBench 日志也提示:
Request rate (0), sending all requests simultaneously
意思是它会尽可能同时发送所有请求。
全量 3270 条一起压到 127.0.0.1:8006,vLLM 服务承受不了,于是大量请求超时或失败。
解决方法:限速 + 分段跑
把模型配置改成:
request_rate=0.1
retry=5
代码:
cd ~/benchmark
python - <<'PY'
from pathlib import Path
import re
p = Path("ais_bench/benchmark/configs/models/vllm_api/vllm_api_general_chat.py")
s = p.read_text(encoding="utf-8")
s = re.sub(r"request_rate\s*=\s*[\d.]+", "request_rate=0.1", s)
s = re.sub(r"retry\s*=\s*\d+", "retry=5", s)
p.write_text(s, encoding="utf-8")
print("updated request_rate=0.1, retry=5")
PY
grep -n "request_rate\|retry\|max_out_len" ais_bench/benchmark/configs/models/vllm_api/vllm_api_general_chat.py
最终目标配置:
request_rate=0.1
retry=5
max_out_len=2048
五、问题 5:全量太大,改成 [0:500] 分段评测
解决方法
新建 chunk 配置:
cd ~/benchmark
cp ais_bench/benchmark/configs/datasets/SuperGLUE_BoolQ/SuperGLUE_BoolQ_gen_0_shot_str.py \
ais_bench/benchmark/configs/datasets/SuperGLUE_BoolQ/SuperGLUE_BoolQ_gen_0_shot_str_chunk.py
加入:
test_range='[0:500]'
代码:
cd ~/benchmark
python - <<'PY'
from pathlib import Path
p = Path("ais_bench/benchmark/configs/datasets/SuperGLUE_BoolQ/SuperGLUE_BoolQ_gen_0_shot_str_chunk.py")
s = p.read_text(encoding="utf-8")
old = """BoolQ_reader_cfg = dict(
input_columns=['question', 'passage'],
output_column='label',
)"""
new = """BoolQ_reader_cfg = dict(
input_columns=['question', 'passage'],
output_column='label',
test_range='[0:500]',
)"""
s = s.replace(old, new)
p.write_text(s, encoding="utf-8")
print("created chunk config [0:500]")
PY
grep -n "test_range" ais_bench/benchmark/configs/datasets/SuperGLUE_BoolQ/SuperGLUE_BoolQ_gen_0_shot_str_chunk.py
后台运行 [0:500]
cd ~/benchmark
nohup ais_bench --models vllm_api_general_chat \
--datasets SuperGLUE_BoolQ_gen_0_shot_str_chunk \
--summarizer example \
> boolq_chunk_0_500_$(date +%Y%m%d_%H%M%S).log 2>&1 &
查看进程:
ps -ef | grep ais_bench | grep -v grep
查看最新输出目录:
cd ~/benchmark
LATEST=$(ls -td ~/benchmark/outputs/default/* | head -1)
echo "$LATEST"
查看实时 infer 日志:
tail -f "$LATEST/logs/infer/qwen36-35b-a3b-vllm-api/BoolQ.out"
退出日志查看:
Ctrl+C
不会停止后台任务。
六、问题 6:后台运行没反应 / 提交了两次
现象
运行 nohup ... & 后只显示:
[2] 3501773
以为没反应。
解释
这是正常的。nohup ... & 会把任务放到后台运行,终端不会继续刷 AISBench 日志。
其中:
[2] 后台任务编号
3501773 进程 PID
查看后台任务
jobs -l
查看 AISBench 进程:
ps -ef | grep ais_bench | grep -v grep
如果提交了两次,就保留一个,杀掉另一个:
kill PID
如果还在:
kill -9 PID
七、问题 7:[0:500] 跑到 50 条时有 4 条 failed
现象
日志显示:
Post: 50
Received: 45
Failed: 4
一开始担心是不是又炸了。
判断
这次不是全量那种大规模失败。后面继续观察,到 180 条时:
Failed 还是 4
说明失败没有继续增加,服务进入稳定状态。
最终 [0:500] 推理结果
Post: 500
Received: 496
Failed: 4
time elapsed: 6833.68s
含义:
500 条请求
496 条成功返回
4 条请求失败
总耗时约 6833 秒 ≈ 1小时53分54秒
成功率 99.2%
失败率 0.8%
八、问题 8:[0:500] summary accuracy = 91.60,但有 failed 样本
原始 summary
BoolQ accuracy = 91.60
对应:
458 / 500 = 91.60%
查看 prediction 空样本
执行后发现:
total: 500
correct by postprocess: 458
accuracy: 91.60
empty prediction count: 8
empty ids: ['0', '1', '2', '3', '20', '49', '88', '297']
这里说明:
日志里 Failed = 4
但 prediction 为空 = 8
原因是空预测有两类:
1. 请求真正失败,超过最大重试次数;
2. 请求成功但 content 为空,例如 finish_reason=length,只生成 reasoning 没生成 content。
查空预测代码
cd ~/benchmark
RUN=outputs/default/20260713_160953
python - <<'PY'
import json
from pathlib import Path
from ais_bench.benchmark.utils.text_postprocessors import first_capital_postprocess
run = Path("outputs/default/20260713_160953")
p = run / "predictions/qwen36-35b-a3b-vllm-api/BoolQ.json"
data = json.load(open(p, "r", encoding="utf-8"))
empty = []
correct = 0
for k, v in data.items():
raw = v.get("prediction", "")
gold = v.get("gold", "")
pred = first_capital_postprocess(raw) if raw else ""
ok = pred == gold
correct += int(ok)
if raw is None or raw.strip() == "":
empty.append((k, gold, v.get("origin_prompt", "")[:500]))
print("total:", len(data))
print("correct by postprocess:", correct)
print("accuracy:", correct / len(data) * 100)
print("empty prediction count:", len(empty))
print("empty ids:", [x[0] for x in empty])
print("\n===== empty cases =====")
for k, gold, prompt in empty:
print("=" * 80)
print("id:", k)
print("gold:", gold)
print("prompt head:", prompt.replace("\n", " "))
PY
九、问题 9:空预测样本需要补跑
手动补跑 8 条空预测
补跑样本:
0, 1, 2, 3, 20, 49, 88, 297
代码:
cd ~/benchmark
python - <<'PY'
import json
import time
import urllib.request
from pathlib import Path
from ais_bench.benchmark.utils.text_postprocessors import first_capital_postprocess
BASE_URL = "http://127.0.0.1:8006/v1/chat/completions"
MODEL_ID = "qwen3.6-35b-a3b"
run = Path("outputs/default/20260713_160953")
pred_path = run / "predictions/qwen36-35b-a3b-vllm-api/BoolQ.json"
out_path = run / "empty_retry_manual.json"
data = json.load(open(pred_path, "r", encoding="utf-8"))
empty_ids = ["0", "1", "2", "3", "20", "49", "88", "297"]
results = {}
correct = 0
for k in empty_ids:
v = data[k]
prompt = v["origin_prompt"]
gold = v["gold"]
payload = {
"model": MODEL_ID,
"messages": [
{
"role": "user",
"content": prompt + "\nPlease answer with exactly one letter: A or B. Do not explain. /no_think"
}
],
"temperature": 0.2,
"max_tokens": 2048
}
req = urllib.request.Request(
BASE_URL,
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST"
)
print("=" * 80)
print("retry id:", k, "gold:", gold)
try:
with urllib.request.urlopen(req, timeout=300) as resp:
res = json.loads(resp.read().decode("utf-8"))
msg = res["choices"][0]["message"]
content = msg.get("content") or ""
reasoning = msg.get("reasoning") or ""
finish_reason = res["choices"][0].get("finish_reason")
pred = first_capital_postprocess(content)
ok = pred == gold
correct += int(ok)
print("finish_reason:", finish_reason)
print("content:", repr(content[:300]))
print("processed pred:", pred)
print("gold:", gold)
print("correct:", ok)
results[k] = {
"gold": gold,
"content": content,
"processed_prediction": pred,
"correct": ok,
"finish_reason": finish_reason,
"reasoning_head": reasoning[:500],
}
except Exception as e:
print("retry failed:", repr(e))
results[k] = {
"gold": gold,
"error": repr(e),
}
time.sleep(3)
json.dump(results, open(out_path, "w", encoding="utf-8"), ensure_ascii=False, indent=2)
print("\nmanual retry correct:", correct, "/", len(empty_ids))
print("saved to:", out_path)
original_correct = 458
new_correct = original_correct + correct
print("corrected accuracy if using retry:", new_correct / 500 * 100)
PY
补跑结果
manual retry correct: 5 / 8
corrected accuracy if using retry: 92.60
具体:
id 0 B / B 对
id 1 A / A 对
id 2 A / A 对
id 3 A / A 对
id 20 B / B 对
id 49 B / A 错
id 88 空 / A 仍然 length 截断
id 297 B / A 错
所以:
原始正确数 = 458
补跑新增正确 = 5
修正正确数 = 463
修正 accuracy = 463 / 500 = 92.60%
更多推荐

所有评论(0)