本地已经把模型跑起来了,但一写到 Python 里就卡住:不知道该装哪个包、服务地址填什么、流式输出怎么接、报连接错误又该先看哪一步。这篇按「先确认服务能用,再换成代码调」的顺序走一遍,给出可直接抄的调用骨架和排查顺序。涉及端口、模型名这类会变的参数,都告诉你到站内对应页面去核对。
本地已经把模型跑起来了,但一写到 Python 里就卡住:不知道该装哪个包、服务地址填什么、流式输出怎么接、报连接错误又该先看哪一步。这篇按「先确认服务能用,再换成代码调」的顺序走一遍,给出可直接抄的调用骨架和排查顺序。
涉及端口、模型名这类会变的参数,正文里不写死,一律告诉你到站内对应页面去核对当时的数字。下面每个小节都配了能立刻动手的动作,别只读不试。
先确认服务本身是通的,再写 Python
命令行里能用交互界面跑通模型,不代表后台的 HTTP 服务已经开着,这两件事是分开的。很多人第一次卡住就是这里:界面能用,脚本一跑就连接被拒。写代码之前先确认服务进程在监听本地端口。
- 确认进程在跑用系统自带的进程查看方式确认服务进程存在;不存在就先手动起一次,别在代码里瞎试。
- 打一次最简单接口用浏览器或 curl 访问服务根路径和模型列表接口,能看到返回就说明 HTTP 层通了。
- 确认模型名从模型列表里挑一个真实存在的名字,后面代码里只填这个名字,别凭记忆写。
- 再上生成先用最简单的一次生成请求打通全链路,成功之后才考虑流式。
服务地址和端口以站内「本地部署 ollama 服务的 api 地址」那页写的为准,别照抄别人博客里的默认值,别人改过配置或者跑在容器里,地址就不是你以为的那个。
两条调用路子:官方 Python 库和 HTTP 直连
Python 调本地模型,本质上就两条路。选哪条不看哪个高级,看你的使用场景:自己跑试验、写一次性脚本,用官方库最省事;要嵌进已有服务、要接自己的日志和重试中间件,就自己发 HTTP 请求。
- 官方 Python 库
- 装好包之后几行就能跑,适合快速验证和本地脚本;缺点是版本迭代快,参数名可能对不上你手上的文档
- HTTP 直连
- 用 requests 或 httpx 自己拼 JSON,好处是能直接复用你已有的重试、超时、日志中间件
- 共同前提
- 模型名一定要写成服务端真实存在的那个,写错会报找不到模型,而不是报参数错
| 场景 | 推荐路子 | 理由 |
|---|---|---|
| 本地试验、一次性脚本 | 官方库 | 代码最短,改起来快 |
| 嵌进已有服务 | HTTP 直连 | 超时、重试、并发上限自己控 |
| 需要自定义日志 | HTTP 直连 | 能挂在自己那套中间件上 |
| 批量跑离线任务 | 看情况 | 先测一次基线再决定,别凭感觉 |
依赖装哪个版本别抄文章里的版本号,到站内模型资料库对应页面看当时的说明。装完先写一个最小脚本跑通一次生成,再加参数。
import requests
BASE = "http://127.0.0.1:11434" # 以站内页面实际地址为准
resp = requests.post(
f"{BASE}/api/generate",
json={"model": "你的模型名", "prompt": "你好", "stream": False},
timeout=60,
)
resp.raise_for_status()
print(resp.json().get("response"))流式输出怎么接、怎么不卡住
流式的本质是服务端一段段吐 JSON 行,客户端要按行读、逐块解析,不能一次性等整个响应读完再处理。你要做的第一件事是把 stream 参数打开,然后改成逐行读,而不是继续用等完整响应那种写法。
- 按行迭代响应体,每一行单独解析,别把它当普通字符串直接拼
- 每段都可能是半截 JSON,解析失败先跳过或累积再试,不要直接抛异常退出
- 做打字机效果时,把「拼文本」和「渲染」拆到两层,渲染不要放在读网络那一层
- 处理完或中途退出,记得把响应和连接关掉,长跑脚本不关会堆积
- 对延迟敏感的场景先测一次基线,用站内接口测速页量一量首次响应和逐字吐字的大致水平
有个常见坑:把流式响应当普通字符串处理,结果只拿到第一段就以为模型只回了一句。另一个坑是超时按非流式设置,流式本来就更久,超时太短会在中间被掐断,表现出来像「模型卡住了」。
import json, requests
with requests.post(
f"{BASE}/api/generate",
json={"model": "你的模型名", "prompt": "你好", "stream": True},
stream=True, timeout=(10, 300),
) as r:
for line in r.iter_lines():
if not line:
continue
chunk = json.loads(line)
print(chunk.get("response", ""), end="", flush=True)连不上的排查顺序
连接失败是这类任务里最高频的问题,而且原因往往不在代码里。按下面的顺序从上往下查,别一上来就怀疑自己的 Python 写得不对。
- 看服务在不在进程没起或中途崩了,代码里报什么都是表象;先确认服务是活的。
- 看地址对不对本机脚本和服务不在同一台机器时,别用本机回环地址;跨机器要确认服务对外开放了监听。
- 看网络与防火墙容器里跑的脚本常常连不到宿主机端口,这类问题占排查时间的大头,先问清楚脚本跑在哪。
- 看代码层超时设太短、代理环境变量把本地请求也带走了,都会表现成「连不上」;临时清掉代理变量再试一次。
- 看错误原文把异常信息完整打出来,连接被拒和超时是两类问题,别用同一套办法硬治。
| 现象 | 优先怀疑 | 先做的动作 |
|---|---|---|
| 连接被拒 | 服务没起或端口不对 | 确认进程和监听地址 |
| 请求超时 | 流式被当非流式、超时太短 | 拉长超时并改逐行读 |
| 找不到模型 | 模型名写错 | 从模型列表里复制名字 |
| 一会儿通一会儿不通 | 并发或资源占用 | 降并发,先单请求跑通 |
| 容器里全失败 | 网络模式没配对 | 确认脚本能访问宿主机的服务端口 |
如果折腾半天还是失败,站内的连接失败排查清单可以直接照着走一遍,里面按错误类型分了常见原因和对应动作,比盲目改代码省时间。
最后提醒一句:接口地址、服务端口、模型名这些值会随部署方式变,文章里给的是结构不是常量。真要落地之前,到站内页面核对当时的那几个数字,再动手写。
下一步把地址、模型名和测速基线先在站内核对一遍,再回来跑上面的骨架,能省掉大半排查时间。→常见问题
用 Python 调本地 Ollama 需要 API Key 吗?
本地自建的服务通常不需要,因为请求根本没出你的机器。但如果你把它挂到公网、或者前面套了网关,就该按网关的要求带凭证。关于要不要设、怎么设,站内有专门的 api key 主题页面,先去核对再决定,别默认「本地就一定不用」。
为什么命令行能跑,Python 里就报连接失败?
大概率不是模型的问题,而是访问路径的问题:服务只监听了本机回环地址、你在容器或另一台机器里发请求;或者代码里配了全局代理,把本地请求也转发出去了。按「服务在不在→地址对不对→网络通不通→代码配置」这个顺序查,通常前三步就能定位。
流式返回和一次性返回,该用哪个?
看交互形态。要做聊天界面、让用户尽早看到字,用流式;要批量跑任务、把结果存库或再加工,用一次性返回更省事,代码也简单。同一条链路里别混着用,否则超时设置和错误处理会变得很难维护。