Ollama API 用量

2026-10-29 19:01 更新

Ollama 的每个推理响应都带性能指标:耗时、token 数、缓存命中情况。这些字段既能算吞吐量,也能定位性能瓶颈。

版本基线 v0.40.12,官方 docs.ollama.com/api/usage。

一、七个指标字段

字段 含义 单位
total_duration 整个响应耗时 纳秒
load_duration 模型加载耗时 纳秒
prompt_eval_count 输入 token 数 个
prompt_eval_cached_count 从缓存读取的输入 token 数 个
prompt_eval_duration 评估未缓存输入 token 的耗时 纳秒
eval_count 输出 token 数 个
eval_duration 生成输出 token 的耗时 纳秒

所有时间单位都是纳秒(1 ms = 1,000,000 ns)。忘了换算会得到离谱的结论。

二、完整响应示例

{
  "model": "gemma4",
  "created_at": "2025-10-17T23:14:07.414671Z",
  "response": "Hello! How can I help you today?",
  "done": true,
  "done_reason": "stop",
  "total_duration": 174560334,
  "load_duration": 101397084,
  "prompt_eval_count": 11,
  "prompt_eval_cached_count": 8,
  "prompt_eval_duration": 13074791,
  "eval_count": 18,
  "eval_duration": 52479709
}

读一下这组数据就能看出不少信息:

  • 总耗时 174.6 ms,其中模型加载占 101.4 ms——大头是冷启动
  • 输入 11 token,其中 8 个命中缓存——前缀复用生效了
  • 输出 18 token 用了 52.5 ms,约 2.9 ms/token

三、流式响应的指标在哪

流式模式下,这七个字段只出现在最后一个 chunk 里(done: true 那一行)。中间行只有 response 和 done: false。

所以想统计用量必须读到流结束,中途断开就拿不到指标。

四、三个实用计算

生成速度(tokens/s)

eval_count / (eval_duration / 1e9)

用示例数据:18 / (52479709 / 1e9) ≈ 343 tok/s。

这是最硬的性能指标——只算生成部分,不掺加载和输入处理。

首 token 延迟(估算)

(load_duration + prompt_eval_duration) / 1e6   # 毫秒

示例:约 114 ms。这个值决定用户点击到看到第一个字之间的等待感。

缓存命中率

prompt_eval_cached_count / prompt_eval_count

示例:8/11 ≈ 73%。

这个指标值得单独盯。多轮对话里前缀(系统提示 + 历史消息)是重复的,缓存命中率高意味着每次请求实际要重算的 token 少,响应快、成本低。命中率突然掉到 0,通常说明提示词前缀结构被改了(比如在开头插了变化的时间戳)。

五、指标的局限

  • token 数是模型 tokenizer 的结果,不同模型对同一段文字计数不同,不能跨模型比较
  • 纳秒精度不代表纳秒准确度,测量值受系统负载影响,做基准测试要多次取中位数
  • load_duration 在模型已加载时为 0(或极小),所以冷启动和热调用要分开测

六、代码示例

import requests

r = requests.post("http://localhost:11434/api/generate", json={
    "model": "gemma4",
    "prompt": "用一句话解释什么是向量",
    "stream": False,
})
d = r.json()

tok_s = d["eval_count"] / (d["eval_duration"] / 1e9)
print(f"输出 {d['eval_count']} tokens,{tok_s:.1f} tok/s")
print(f"模型加载 {(d['load_duration'])/1e6:.0f} ms")
if d["prompt_eval_count"]:
    hit = d["prompt_eval_cached_count"] / d["prompt_eval_count"]
    print(f"缓存命中率 {hit:.0%}")

动手试

连跑两次同一条命令,看 load_duration 的变化:

## 第一次:冷启动
curl -s http://localhost:11434/api/generate -d '{"model":"gemma4","prompt":"hi","stream":false}'

## 第二次:模型已在内存
curl -s http://localhost:11434/api/generate -d '{"model":"gemma4","prompt":"hi","stream":false}'

第二次的 load_duration 会接近 0,total_duration 大幅下降——这个对比能让你直观感受到 Keep-Alive 的价值。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号