侧边栏壁纸
博主头像
龍騰博客 博主等级

行动起来,活在当下

  • 累计撰写 197 篇文章
  • 累计创建 31 个标签
  • 累计收到 12 条评论

目 录CONTENT

文章目录

用 quant_eval.py 对比 LFM2.5-24B-A2B 与 Qwen3.6-35B(保姆级)

管理员
2026-10-18 / 0 评论 / 0 点赞 / 0 阅读 / 0 字

适用机器:fnOS-Ser8。脚本版本:quant_eval.py v2.2。 目标:在同一套题、同一组参数下,让 LFM2.5(Q5_K_M / Q6_K)和你机器上的 Qwen3.6-35B 各跑一遍,然后并排对比。


0. 先看这里

0.1 能不能比?

能。脚本只做一件事:往一个 OpenAI 兼容的 /v1/chat/completions 端点发题、收答案、判分。只要模型是 llama-server 提供的,换端口就能比,不用改代码。

0.2 但要知道这几点,否则结论会失真

  1. 比的是"你机器上实际在跑的那个 qwen36",不是抽象的"Qwen3.6-35B"。它具体是官方权重还是社区改版、是什么量化档位,会影响结果。第 2.3 步会教你看模型文件名,对比结论要带上这个前提

  2. 一次只能开一个模型。内存不允许两个同时加载(你之前把 swap 打满就是这么来的)。流程是:跑完一个,停掉,再起下一个

  3. 所有模型必须用完全相同的条件:同一个脚本版本、同样的 --repeats、--temperature、--max-tokens。脚本在 compare 时会检查这些,不一致会打警告

  4. 同一温度不等于各自的最佳设置。默认温度 0.1 是 LFM2.5 官方推荐值,Qwen3.6 的推荐值我没核实过,可能更高。想更公平,可以去 Qwen3.6 的模型卡查推荐温度,用 --temperature 再单独跑一轮,当作补充参考

  5. 题目偏简单,两个模型都可能接近满分,主要用来发现明显的退化。想分出细微差别,要加你自己的真实任务(第 7 节)

  6. 每题只重复几次,样本小。相差一两题属于正常波动,别据此下结论

  7. 脚本版本变了,旧结果就不能混着比。v2.1 修正了判分规则(模型把城市名写成 Tokyo、Shanghai 也算对)、把日历题改成了绝对日期、默认 --max-tokens 提到 6000,并且会自动清理混在回答里的思考标签。你之前用旧版跑出的结果文件,都要重跑。

    • 例外:v2.1 → v2.2 只新增了题目,旧题一字未改,所以已有的 v2.1 结果可以用 --resume 续跑,只补新增的题(见 2.4A)。续跑要求 --repeats、--temperature、--max-tokens 与之前完全一致

0.3 这套对比能告诉你什么,不能告诉你什么

  • 能:工具调用是否规范、遇到缺参数时是追问还是编造、基础数学逻辑和指令遵循、平均输出 token 数和平均耗时(后两项直接关系到你用 Hermes 时的等待感)

  • 不能:长文本理解、复杂代码、深度推理这类更难的能力。这些要靠你自己加的真实任务和人工对比题


1. 准备工作

1.1 放好脚本 v2

把下载的 quant_eval.py 放到 SER8 的这个目录(scp 或 fnOS 文件管理器都行):

mkdir -p /vol3/1000/docker/lfm25-24b/eval
cd /vol3/1000/docker/lfm25-24b/eval
ls -l

如果这个目录里已经有旧版脚本和旧结果,先收起来,避免混淆:

mkdir -p old-v1
mv results-*.json old-v1/ 2>/dev/null
mv run-*.log old-v1/ 2>/dev/null

然后覆盖新版脚本。确认是 v2:

head -2 quant_eval.py
python3 --version
  • 第一条第二行应显示 quant_eval.py v2.2,不是的话重新放文件

  • 第二条能显示版本号,说明 python3 可用

1.2 确认磁盘和内存

df -h /vol3
free -h

评测本身占用很少,主要是模型加载的内存,参考之前的数据:LFM2.5 Q5_K_M 加载后 available 约 11Gi,Q6_K 约 8.8Gi。

每次评测前再确认一次 ollama 没有常驻模型,否则会悄悄吃掉约 8GB:

docker exec ollama ollama ps

输出空表才算干净,有模型就用 docker exec ollama ollama stop <模型名> 卸载。

1.3 评测期间别用 Hermes

评测期间不要在飞书里和 Hermes 对话。Hermes 的请求会和评测抢同一个服务,既干扰耗时数据,也可能触发 503。


2. 阶段 A:给 LFM2.5 评分

如果你想在 Q5_K_M 和 Q6_K 两个版本都评一遍,每个版本各做一轮(切换方法见《LFM2.5 Q5/Q6 保姆级教程》第 6 节)。下面以当前正在运行的版本为例。

2.1 确认现在加载的是哪个文件

curl -s http://localhost:8088/v1/models | grep -o 'LFM2.5-24B-A2B-[A-Za-z0-9_]*' | head -1

输出 LFM2.5-24B-A2B-Q5_K_M 或 LFM2.5-24B-A2B-Q6_K。下面命令里的 --label 要和它对应,不要贴错标签。

2.2 先自测工具调用能正常返回

这一步是为了排除"启动参数不对导致工具调用整类失败"的情况,对每个模型都要做一次:

curl -s http://localhost:8088/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "messages":[{"role":"user","content":"现在北京天气怎么样"}],
    "tools":[{"type":"function","function":{"name":"get_weather","description":"查询城市天气","parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}]
  }'

返回里应有 "finish_reason":"tool_calls" 和 {"city":"北京"} 这样的参数。如果没有,先别评测,工具调用类题目会整类失败,那是配置问题,不代表模型能力。

2.3 先试跑一轮,估算耗时

这个模型的思考过程很长,所以先用 --repeats 1 看看一轮要多久。参考:LFM2.5 Q5_K_M 在你机器上实测,28 题平均每题约 11 秒,全程约 5 分钟,所以 --repeats 3 大约 15 分钟(Qwen3.6 要多久取决于它自己的速度,先试跑再说):

cd /vol3/1000/docker/lfm25-24b/eval
pgrep -af quant_eval

必须没有输出再继续(防止重复启动,互相覆盖结果):

nohup python3 quant_eval.py run --url http://localhost:8088 --label LFM_Q5_K_M --repeats 1 > run-LFM_Q5_K_M.log 2>&1 &
tail -f run-LFM_Q5_K_M.log
  • 日志每行形如 [3/28] tool_weather #1 PASS 49tok 1.4s,前面是进度,后面是输出 token 数和耗时

  • 失败的题会多打印一行 ->,告诉你模型实际返回了什么,方便判断是模型答错还是格式问题

  • Ctrl+C 只是退出查看,评测不会停

跑完会自动打印汇总,并保存 results-LFM_Q5_K_M.json。

2.4A 你已经有 LFM_Q5_K_M 的 v2.1 结果:只补跑新增的题(推荐)

v2.2 新增了 4 类、共 16 道更难的题(多步推理 5、多约束指令 4、难工具调用 5、长文本检索 2),一共 48 次请求。已有的 84 次结果(75 次自动判分加 9 次人工题)不用重跑:

cd /vol3/1000/docker/lfm25-24b/eval
cp results-LFM_Q5_K_M.json results-LFM_Q5_K_M.v21.bak
pgrep -af quant_eval
nohup python3 quant_eval.py run --url http://localhost:8088 --label LFM_Q5_K_M --repeats 3 --resume > run-LFM_Q5_K_M-resume.log 2>&1 &
tail -f run-LFM_Q5_K_M-resume.log
  • 第一行 cp 先留一份备份

  • 开头会打印 续跑:已有 84 条有效结果,只补跑缺少的题,进度显示 [1/48]

  • 参数必须和上次一致(--repeats 3,温度和 --max-tokens 用默认值,上次也是默认值)。不一致会直接报错退出,不会写坏结果

  • 上次出过请求失败的题会自动重跑

  • 这一步我没有在你的真实模型上测过耗时。新增题里,长文本检索每题要先处理约 4000 字的提示,多步推理和多约束写作会思考得久一些,我粗估要 15~25 分钟,实际以你的日志为准

跑完汇总里会多出 4 类题的得分,这几类才是用来拉开差距的。

2.4 从头完整跑(--repeats 3)

没有旧结果,或者要给其他模型(Q6_K、Qwen3.6)跑的时候用这个。试跑的耗时可以接受的话,正式跑一遍,同样的标签会覆盖试跑结果。完整 44 题 × 3 次大约需要 30 分钟以上(旧的 28 题实测约 14 分钟,新增部分按上面的粗估,不是实测):

pgrep -af quant_eval
nohup python3 quant_eval.py run --url http://localhost:8088 --label LFM_Q5_K_M --repeats 3 > run-LFM_Q5_K_M.log 2>&1 &
tail -f run-LFM_Q5_K_M.log

之后所有模型都用同样的 --repeats 3。

2.5 看汇总里这几项

  • 因达到 max_tokens 被截断: N 次:默认上限是 6000 token。N 很大说明思考没写完就被截断了,自动题会被判失败,人工对比题则会拿到空回答。需要用更大的值(如 --max-tokens 10000)把所有模型都重跑一遍

  • content 里混入思考标签(已自动清理后再判分):只是提示,脚本已经处理了

  • 请求失败(已排除,不计入):服务偶发 503 或断连的次数,脚本已自动重试 6 次,这些不算模型成绩


3. 阶段 B:给 Qwen3.6-35B 评分

3.1 停掉 LFM2.5,腾出内存

docker stop lfm25-24b
docker ps --filter "name=llama" --filter "name=lfm25"

确认没有 llama.cpp 模型容器处于 Up。ollama 虽然不是 llama.cpp 容器,但它自己也会常驻模型占内存(你实际遇到过 gemma4:12b 占了约 8GB、默认保留 3 天),所以要再查一次:

docker exec ollama ollama ps

输出空表才算干净。列出了模型就卸载(模型名按 NAME 列填写,卸载只释放内存,不删模型):

docker exec ollama ollama stop gemma4:12b

3.2 启动 qwen36

用你平时切换到 qwen36 的方式启动(切换面板,或你的切换脚本都行)。如果直接起容器也可以:

docker start llama-qwen36

3.3 找到它的端口,确认模型名

docker ps --filter "name=llama-qwen36" --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'

PORTS 列形如 0.0.0.0:8083->8080/tcp,左边的数字就是宿主机端口。下面命令里的 8083 只是示例,换成你实际看到的。

等它加载完。注意 docker start 会沿用旧日志,看日志时只看最新的几行,别被旧的 listening on 迷惑:

docker logs --tail 20 -f llama-qwen36

最新几行出现 listening on 后 Ctrl+C 退出。然后看模型文件名:

curl -s http://localhost:8083/v1/models | head -c 600

记下返回里的模型文件名,这就是对比结论里 qwen36 的真实身份(官方权重还是社区改版、Q 几)。

3.4 自测工具调用

用 2.2 同样的命令,把端口换成 qwen36 的:

curl -s http://localhost:8083/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "messages":[{"role":"user","content":"现在北京天气怎么样"}],
    "tools":[{"type":"function","function":{"name":"get_weather","description":"查询城市天气","parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}]
  }'

同样要看到 tool_calls。

3.5 评分(参数必须和阶段 A 一模一样)

cd /vol3/1000/docker/lfm25-24b/eval
pgrep -af quant_eval
nohup python3 quant_eval.py run --url http://localhost:8083 --label Qwen3.6-35B --repeats 3 > run-Qwen3.6-35B.log 2>&1 &
tail -f run-Qwen3.6-35B.log

注意:--url 只写到端口,不要加 /v1,脚本会自己拼。

Qwen3.6 如果也有长思考,同样关注汇总里的"被截断"次数,处理方法同 2.5。


4. 对比

cd /vol3/1000/docker/lfm25-24b/eval
python3 quant_eval.py compare results-LFM_Q5_K_M.json results-Qwen3.6-35B.json

可以同时对比 2 个以上,比如 LFM 的两个量化加 Qwen3.6:

python3 quant_eval.py compare results-LFM_Q5_K_M.json results-LFM_Q6_K.json results-Qwen3.6-35B.json

输出分几块:

部分

怎么看

各模型汇总

每类题通过数、合计、被截断次数

条件警告

出现 [警告] ... 不一致 说明参数不统一,结果不公平,要重跑

分类对比表

每类题"通过数/总数",后面有"平均输出token"和"平均耗时"

通过率不完全相同的题

只列有差异的题,没有差异的不列

人工对比题

3 道题的原文并排,请自己先读再判断

怎么解读:

  • 旧的四类题(工具调用、数学逻辑、指令遵循、中文知识)LFM2.5 Q5_K_M 已经拿了满分,很可能所有模型都接近满分,参考价值有限。重点看新增的四类:多步推理、多约束指令、难工具调用、长文本检索

  • 先看"通过率不完全相同的题",列表很短就说明两边基本打平

  • 重点看 tool_flight_missing:缺必填参数时,是追问(通过),还是编造参数去调用(失败)。这类行为在实际使用中比答对一道算术题更重要

  • 看"平均输出token"和"平均耗时":同样答对,谁更啰嗦、谁让你等得更久,直接影响 Hermes 的体验

  • 人工题三道,你自己读完再下结论。想让我帮你盲评,把两份输出去掉标签贴给我,不过那只是参考

别做的事:

  • 差一两题就断言谁更强

  • 只看合计分数,不看失败的原因(失败行里有 -> 线索,区分"模型真的答错"和"格式没对上")

  • 工具调用类整类失败时直接归因于模型,先回头检查 2.2、3.4 的自测


5. 收尾:恢复服务

评测结束,把现场还原。同一时刻只留一个模型:

docker stop llama-qwen36
docker start lfm25-24b
docker logs --tail 20 -f lfm25-24b

看最新几行出现 listening on 后 Ctrl+C 退出(docker start 沿用旧日志,别看旧行)。再确认:

curl -s http://localhost:8088/v1/models | grep -o 'LFM2.5-24B-A2B-[A-Za-z0-9_]*' | head -1
free -h

如果你平时是用切换面板管理 qwen36,也可以用面板停掉它,效果一样。


6. 想追加测另一个版本

比如还想补测 LFM2.5 的 Q6_K:

  1. 停掉当前模型容器

  2. 按《LFM2.5 Q5/Q6 保姆级教程》第 6.3 步切到 Q6_K,等 listening on

  3. 用 2.1 确认文件名,用 --label LFM_Q6_K、同样的 --repeats 3 跑

  4. 最后用 compare 带上所有结果文件


7. 加你自己的真实任务(强烈建议)

默认题目偏简单,要分出差别,需要加你日常觉得"模型答得不好"的真实任务。

7.1 编辑脚本

cd /vol3/1000/docker/lfm25-24b/eval
nano quant_eval.py

在 nano 里搜索(Ctrl+W)man_rewrite,找到 CASES 列表里最后一道题,在它后面、列表结尾的 ] 之前,加上你的题。这里 nano 保存是 Ctrl+O 回车,退出是 Ctrl+X(注意和终端里中断命令用的 Ctrl+C 不同)。

7.2 两种格式

能自动判分的题(答案可以用关键词判断):

    dict(id="my_extract_date", cat="我的任务",
         prompt="从下面这句话里提取日期,只输出 YYYY-MM-DD:会议定在2026年11月3日下午三点。",
         check=has_any("2026-11-03")),

只做人工对比的题(长文本、写作、总结之类):

    dict(id="my_summary", cat="人工对比", manual=True,
         prompt="这里放你日常真实使用的任务原文……"),

规则:

  • id 不能和已有的重复

  • 自动判分题的 check 可以用现有的 has_any(...)、num_is(...),也可以自己写函数

  • 加完后保存,所有要对比的模型必须用同一份题集,不能新题只跑了其中一个

  • 只在列表末尾追加新题,不要改已有题的内容,这样已有结果还能用 --resume 补跑新题,不用全部重来。已有题一旦改动,对应的结果就必须重跑

7.3 语法检查

python3 -m py_compile quant_eval.py && echo 语法OK

输出 语法OK 再去跑评测,写错了会直接报错,不会误跑。


8. 常见问题

现象

原因

处理

全部题都显示 ERR,提示"请求失败(已重试6次)"

端口写错、模型还在加载、或容器没起来

先用 curl http://localhost:<端口>/v1/models 确认能通;确认 --url 没有带 /v1

评测中途个别题 ERR

服务偶发 503 "Loading model" 或断连

脚本已自动重试,ERR 不计入成绩;ERR 太多就换时间重跑

结果文件被覆盖

两次运行用了同一个 --label

标签要唯一,比如加上日期:LFM_Q5_K_M_1020

两次评测同时在跑,结果乱

重复启动

启动前先 pgrep -af quant_eval,必须无输出

--resume 失败:...与本次参数...不一致

续跑时的 --repeats、--temperature 或 --max-tokens 和已有结果不同

改成与之前完全一致;确实要换参数就别续跑,换个 --label 从头跑

一个模型工具调用类整类失败

启动参数或聊天模板不支持工具调用

回头做 2.2 / 3.4 的自测;失败行 -> 能看到模型实际返回了什么

大量题显示被截断

--max-tokens 太小,思考没写完

所有模型统一加大,如 --max-tokens 10000,全部重跑

compare 打出 [警告] ... 不一致

各结果的温度、重复次数或脚本版本不同

用相同参数重跑不一致的那个

跑完发现 swap 在涨、available 变小

内存吃紧

停掉不必要的服务,回到 LFM2.5 的更小量化或 Qwen 的更小版本


附:命令速查

# 评测(每次先 pgrep 确认没有残留)
pgrep -af quant_eval
nohup python3 quant_eval.py run --url http://localhost:<端口> --label <标签> --repeats 3 > run-<标签>.log 2>&1 &
tail -f run-<标签>.log

# 对比(2 个或更多)
python3 quant_eval.py compare results-A.json results-B.json [results-C.json]

# 切换模型前
docker stop <当前模型容器>
docker ps --filter "name=llama" --filter "name=lfm25"

# 确认当前加载的模型
curl -s http://localhost:<端口>/v1/models | head -c 600

0

评论区