Ollama API 流式响应

2026-10-29 19:01 更新

/api/generate、/api/chat 这类端点默认就是流式。它返回的不是一个 JSON,而是一串按行分隔的 JSON(NDJSON,Content-Type 为 application/x-ndjson)。这个格式理解错了,解析就会出问题。

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

一、流式响应长什么样

{"model":"gemma4","created_at":"2025-10-26T17:15:24.097767Z","response":"That","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:15:24.109172Z","response":"'","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:15:24.121485Z","response":"s","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:15:24.132802Z","response":" a","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:15:24.143931Z","response":" fantastic","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:15:24.155176Z","response":" question","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:15:24.166576Z","response":"!","done":true, "done_reason": "stop"}

三个要点:

  • 每行一个完整 JSON,不是数组,不需要逗号分隔
  • response 是增量片段,要自己拼接(注意 " a" 前面带空格)
  • 最后一行 done: true,同时带 done_reason

别把 response 当成整句去替换——它是累加的碎片,直接 += 拼接。

二、关掉流式

请求体里加 {"stream": false},返回就变成普通 JSON(application/json):

{"model":"gemma4","created_at":"2025-10-26T17:15:24.166576Z","response":"That's a fantastic question!","done":true}

三、什么时候用哪种

用流式(默认):

  • 需要实时显示生成过程
  • 想让用户感知延迟更低
  • 长文本生成——边生成边展示,体验差别很大

用非流式:

  • 处理逻辑更简单
  • 短响应
  • 结构化输出(JSON schema)——一次性拿到完整对象更安全
  • 需要精确的用量统计(流式下指标在最后一个 chunk)

四、代码里的处理方式

Shell(逐行读)

curl http://localhost:11434/api/generate -d '{
  "model": "gemma4",
  "prompt": "Why is the sky blue?"
}' | while IFS= read -r line; do
  echo "$line" | python -c "import sys,json; print(json.load(sys.stdin).get('response',''), end='')"
done
echo

Python(非流式取整句)

import requests

r = requests.post("http://localhost:11434/api/generate", json={
    "model": "gemma4",
    "prompt": "Why is the sky blue?",
    "stream": False,
})
print(r.json()["response"])

Python(流式逐块)

import json, requests

with requests.post("http://localhost:11434/api/generate", json={
    "model": "gemma4",
    "prompt": "Why is the sky blue?",
}, stream=True) as r:
    for line in r.iter_lines():
        if not line:
            continue
        chunk = json.loads(line)
        if "error" in chunk:
            raise RuntimeError(chunk["error"])
        print(chunk.get("response", ""), end="", flush=True)
        if chunk.get("done"):
            break

注意到里面有个 if "error" in chunk —— 流式过程中出错不会改 HTTP 状态码(响应已经开始发了),错误是作为一行 JSON 出现的。细节见 13.5 Ollama API 错误。

五、几个实操细节

细节 说明
空行 NDJSON 里可能出现空行,解析前先跳过
拼接方式 字符串累加即可,不需要处理重叠
done_reason 常见值 stop(正常结束)、length(达到 token 上限)
用量指标 只在 done: true 的那一行里
中断 客户端断开连接,服务端停止生成

动手试

一条命令看清流式的原始形态:

curl http://localhost:11434/api/generate -d '{
  "model": "gemma4",
  "prompt": "Count from 1 to 5"
}'

会看到一行一行的 JSON 陆续刷出。再把 "stream": false 加进去跑一次,对比返回结构的差别——这个对比比读文档更直观。

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

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号