2026年 AI API 超时解决 示例代码 实操:Python 请求超时与流式中断处理
2026年 AI API 超时解决 示例代码 实操:Python 请求超时与流式中断处理
AI API 超时很少是单一原因。多数情况是客户端等待策略、网络链路和流式读取三方配合出了问题,按类型拆开处理,比盲目把超时时间调大更有效。
排查之前先记录两个基线:正常请求的响应时间分布,以及报错发生的时间点。没有基线,“偶尔超时”就无法判断是模型侧变慢、链路抖动,还是自己的代码卡在了某个数据块上。下面的示例以 Python 为例,接口地址与模型名称请以你所用平台控制台显示的信息为准。
先把“超时”拆成三类
Python 抛出的超时异常往往只有一个笼统的名字,但成因完全不同。分不清类型,就会出现“把 read 超时调到 300 秒,结果还是报错”的情况。
| 类型 | 典型表现 | 常见原因 | 排查动作 |
|---|---|---|---|
| 连接超时 | 请求还没发出就失败 | 域名解析、代理配置或出网策略异常 | 用 curl 或 ping 验证基础连通性 |
| 读取超时 | 请求已发出,长时间等不到完整响应 | 长文本生成耗时较长,或输入过大 | 区分首字节耗时与整体耗时 |
| 流式中断 | 已经吐出部分内容后连接断开 | 空闲超时、代理缓冲或服务端主动断开 | 打印每个数据块的到达时间 |
为什么读取超时最容易误判
流式模式下,服务端会先返回响应头,再一段一段推送内容。如果客户端把读取超时理解成“整个请求的总时长”,长文本任务就很容易被自己掐断。更合理的做法是:连接超时设短(几秒),读取超时按单次数据块等待时间设,再在业务层自己控制总时长上限。
Python 中的超时参数怎么设
使用 httpx 可以分别设置各阶段超时,这是排查问题的第一步。把阶段拆开,报错信息才有意义。
import httpx
timeout = httpx.Timeout(connect=5.0, read=60.0, write=10.0, pool=5.0)
with httpx.Client(timeout=timeout) as client:
resp = client.post(
url,
headers={'Authorization': 'Bearer ' + api_key},
json=payload,
)
resp.raise_for_status()
print(resp.json())
如果使用 requests,则通过元组形式指定“连接超时”和“读取超时”,它无法区分写入与连接池等待,排查粒度会粗一些。对大多数对话类请求,连接 5 秒、读取 60 秒是一个常见的起点,具体数值仍需结合你自己的响应时间分布来定。
OpenAI 兼容 SDK 的写法
如果你使用的是 OpenAI 兼容 SDK,超时和重试通常可以直接在客户端上配置。Base URL 指向你实际使用的接口地址即可,统一入口能减少多套地址切换带来的配置错误。
from openai import OpenAI
client = OpenAI(
api_key='YOUR_API_KEY',
base_url='https://你的接口地址/v1', # 以控制台显示为准
timeout=60.0,
max_retries=2,
)
resp = client.chat.completions.create(
model='控制台列出的模型名称',
messages=[{'role': 'user', 'content': '你好'}],
)
print(resp.choices[0].message.content)
流式中断的处理方式
流式输出最怕的不是报错,而是静默中断:前端已经渲染了一半文字,用户以为还在生成。解决办法是显式判断结束标记,并把已接收内容落盘,便于断点续写。
import json
import httpx
t = httpx.Timeout(connect=5.0, read=30.0)
buffer = []
with httpx.stream('POST', url, headers=headers, json=payload, timeout=t) as r:
for line in r.iter_lines():
if not line:
continue
if line.startswith('data: '):
chunk = line[6:].strip()
if chunk == '[DONE]':
break
buffer.append(chunk)
handle(json.loads(chunk))
print('已接收数据块:', len(buffer))
断点续写要考虑的两件事
第一,把已生成内容保存下来,续写时作为上下文传入,而不是从头再来,避免重复消耗。第二,续写前先判断上一次中断是客户端主动断开还是服务端断开;如果是业务逻辑主动取消,就不要触发续写,否则会形成循环。
重试不是万能药。对于已经产生计费的生成类请求,盲目重试可能造成重复扣费;更稳妥的策略是首次失败后短暂退避重试一次,仍失败则记录任务标识,改为人工确认或异步补偿。
上线前的排查清单
- 超时分层:连接、读取、写入、连接池分别设置,不要只用一个总超时。
- 日志完整:记录请求开始时间、首字节时间、结束时间、状态码与错误类型。
- 代理检查:中间代理可能开启缓冲,导致流式内容被攒到最后一次性下发。
- 请求体大小:过长的上下文会显著拉长响应时间,必要时先做摘要压缩。
- 并发控制:并发过高可能触发限速,表现和超时非常相似,需要看状态码区分。
- 降级方案:准备一个更短输出或非流式的备用路径,保证页面不完全不可用。
用统一入口减少排查变量
超时排查最难的地方,是同时接入多个平台时不知道该怀疑哪一段。把调用收敛到统一入口,可以让地址、鉴权和模型名称只维护一份。你可以到 通联AI中转站 查看模型广场与接口文档,确认 Base URL、可用模型和兼容协议后,用同一套代码结构做对比测试。
如果需要在团队内共享调用能力,统一管理 API Key、余额与调用记录会比每个成员各自申请账号更容易控制成本与排查问题。具体的模型清单、计费方式和调用限制,请以 通联官网 控制台中的实时说明为准。
把超时问题挡在上线之前
如果你正在为流式中断和读取超时反复调参,可以在通联注册账号,先查看接口文档与可用模型,用一条最小请求确认链路耗时,再逐步加上重试与降级逻辑。