三项一起量:连通性 5/5、出字速度 25.0 tok/s、上下文超过 8192 就被截断。 只测第一项就宣布部署完成,是这一章最常见的翻车方式——因为后两项的失败方式都不报错。
上一节把最后一个坑填了。这一节做验收:怎么判断这套东西到底「能用」,而不是「看起来能用」。
一、三项指标,三种不同的失败
连通性:请求能不能成功返回。失败方式是报错,最容易被发现。 出字速度:每秒能出几个 token。失败方式是「慢」,不报错,但交互体感接近卡死。 上下文长度:能记住多长的内容。失败方式是「忘」,连慢都不算,它只是答得似是而非。 三种失败里,第一种会闹,第二种会烦,第三种会骗人。 所以验收必须三项一起做,只看第一项等于没验收。 这一节的三项,正好对应前面三节讲的三件事:服务在不在(2.1.3)、带宽够不够(2.1.5)、 配置对不对(2.1.6)。验收就是把它们合起来量一遍。
二、速度不要靠感觉,读它自己报的数
Ollama 的每个响应里都带着两个字段:
eval_count(生成了几个 token)和 eval_duration(生成花了多少纳秒)。
两个一除就是 tok/s。
不用秒表掐,也不用自己数汉字——它自己报的数比任何外部测量都准,因为不含网络和界面渲染的时间。
Demo 里读到的是 5 个 token、0.20 秒,算出来 25.0 tok/s。
这个数在假服务上没有意义(它没有真推理),但算法就是这两个字段相除,换成真模型直接就能用。
还有一个细节:第一次请求总是慢的,因为要把权重加载进显存。
所以判断速度要去掉第一次,用第二、三次的数。Demo 里那个「中位数比最小值更可信」说的就是这件事。
三、上下文被截断,它不会告诉你
模型有一个上下文窗口上限。超过的部分直接被丢掉,而且不报错、不警告、不提示。 表现是什么?你贴了一份十页的文档,问第十页的细节,它答得似是而非; 问第一页的内容,它说「文中没有提到」。你会以为是模型笨,其实是内容根本没进去。 Demo 里扫了三档:设 2048 吃进 2048,设 8192 吃进 8192, 设 32768 还是只吃进 8192——因为模型本身的上限就 8192。配置写得再大,也大不过模型。 所以判断方法是:贴一段开头带明显标记的长文,问它开头写了什么。答得出来,上下文够; 答不出来,就是被截了。这一招比看参数表可靠。
四、合格线怎么定
连通性 5/5,一次失败都不行。偶发失败比稳定失败更难查,通常是显存不够触发了换页。 出字速度 > 5 tok/s。这是交互的底线——再低,人就开始怀疑是不是卡死了。 对比一下:正常人打字约 3~5 个字每秒,一个汉字约 1.5 个 token, 所以 5 tok/s 大概是「跟你打字差不多快」。 上下文 ≥ 业务需要的长度。 这个数没有通用值,读一篇公众号文章 2000 字够,读合同、读代码库就不够。 按最长的那份材料定,不是按平均值。 三项都过,才算部署完成。 任何一项不过,都还有活要干——而这三项的修法完全不同:连通性查服务、速度换硬件、上下文改配置。
五、动手 Demo:5/5 连通、25.0 tok/s、上下文 8192 封顶——三项才算验收
连发五次请求统计成功率和延迟分布,读响应里的 eval_count 和 eval_duration 算出字速度, 再扫三档上下文看实际吃进多少;最后把三项指标和它们的合格线列成一张验收表。
lat, bad = [], 0
for _ in range(5):
st, body, _h, dt = post(url + u'/v1/chat/completions',
{u'model': u'deepseek-r1:7b',
u'messages': [{u'role': u'user',
u'content': u'你好'}],
u'stream': False})
bad += (st != 200)
lat.append(dt * 1000)
tps = ev / (evd / 1e9) # eval_count ÷ eval_duration(秒)
实跑输出:
--------------------------------------------------------------------
测试:三项指标一起量,才知道「能用」还是「不能用」
--------------------------------------------------------------------
第一项,连通性:连发 5 次,一次都不许失败。
成功/总次数 5/5
延迟 最小 1.6 毫秒
延迟 中位 1.6 毫秒
延迟 最大 2.4 毫秒
中位数比最小值更可信——**第一次请求总带着建连和加载模型的开销。**
第二项,出字速度。这个词不能靠感觉,得算:
生成 token 5
生成耗时 0.20 秒
出字速度 25.0 tok/s
Ollama 的每个响应里都有这两个字段(eval_count/eval_duration),
**不用秒表掐,直接读它自己报的数。**
第三项,上下文。发一段超长内容,看它记不记得开头:
设 2048,实际吃进 2048 token(超过模型上限就被截断)
设 8192,实际吃进 8192 token(超过模型上限就被截断)
设 32768,实际吃进 8192 token(超过模型上限就被截断)
真实环境里这一项最容易被忽略:**内容被悄悄截掉,模型不报错,
只是「忘」了开头几段。** 表现是答得似是而非,而不是报错。
三项合起来才叫「能用」:
指标 合格线 不合格的表现
---------------------------------------------------------
连通性 5/5 成功 有失败就是服务或地址问题
出字速度 > 5 tok/s 低于这个数,交互体感接近卡死
上下文 ≥ 业务需要的长度 不够就是被截断,不报错
只测第一项就宣布部署完成,是这一章最常见的翻车方式。
done -> _out_39d.txt
第一项:5/5 成功,延迟最小 1.8、中位 1.9、最大 2.7 毫秒。 这个量级说明请求走的是本机回环,没有真推理。 要说明的是:这个延迟数字不能当「模型快」的证据,因为假服务没有跑模型。 它能证明的是「链路是通的、脚本是对的」。 第二项:5 个 token、0.20 秒、25.0 tok/s。这个数同样是假服务自己报的。 要学的是算法:eval_count ÷ eval_duration。换成真模型,这两个字段照样在,直接除就行。 第三项最能说明问题:设 2048 吃进 2048、设 8192 吃进 8192、设 32768 还是只有 8192。 最后一行是关键——配置写大了,模型上限不会跟着变大。 最后那张三行表是这一节的结论。 「只测第一项就宣布部署完成」之所以是翻车方式,是因为它恰好是唯一会报错的那一项。后两项不报错, 要等到实际用起来才发现,那时候已经过了一周。
30 秒实验
- 把连发次数从 5 改成 50,再看延迟分布。 偶发的长尾延迟(比如某一次 50 毫秒)通常比平均值更有诊断价值。
- 把
eval_duration手改成 5 秒,看算出来的 tok/s 掉到 1.0。 体会一下「1 tok/s 是什么体感」——那就是比手写还慢。 - 给上下文那一项加一条判断:把「配置值」和「模型上限」取小的那个,显式打印出「实际能用多少」。 这就是配置校验该做的事。
常见误区
- 「能对话就算部署完成」。能对话只过了第一项。速度和上下文都还没量,而它们的失败不报错。
- 「出字慢是正常的,忍忍就好」。5 tok/s 是交互底线,低于它就不是「慢」而是「不能用」。 这时候要换档位或换硬件,不是忍着。
- 「上下文设得越大越好」。超过模型上限的部分直接被丢,还会白占显存。 设成模型上限,不是设成你以为的数。
自测三问(点开对答案)
1. 为什么只测连通性不够? —— 因为速度和上下文这两项的失败都不报错。 速度慢了只是体感差,上下文不够只是「忘事」——两个都要实际用起来才发现。 2. 出字速度怎么算才准? —— 读响应里的 `eval_count` 除以 `eval_duration`(注意单位是纳秒)。 不要用秒表掐,那会把网络和界面渲染也算进去。 3. 怎么快速判断上下文够不够? —— 贴一段开头带明显标记的长文,问它开头写了什么。答不出来就是被截断了——比查参数表可靠。第二章到这里结束:模型装好了、界面通了、三项指标也验过了。 第三章开始讲数据——模型能干什么,取决于你喂它什么。
- ☐ (本章完,下一节 3.1.1 通俗解读模型训练中的数据集)