Reliability
错误码与重试
生产环境必看:每个状态码什么意思、能不能重试、怎么退避、context 超长怎么办。
错误响应格式
所有错误都返回 JSON,结构和 OpenAI 一致:
json{ "error": { "type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit reached. Please retry after 12s.", "param": null } }
状态码速查
| 码 | 类型 | 能否重试 | 说明 / 处理 |
|---|---|---|---|
| 400 | invalid_request | 否 | 参数错。看 message 字段,改请求再发。 |
| 401 | authentication | 否 | Key 缺失/错误/被禁用。检查 Authorization Header。 |
| 402 | payment_required | 否 | 余额耗尽。去控制台充值。 |
| 403 | permission_denied | 否 | IP 不在白名单 / 模型未开通。 |
| 404 | not_found | 否 | 模型 slug 不存在。看 /models 取最新清单。 |
| 408 | timeout | 是 | 客户端没在 5 分钟内读完响应。建议开 streaming。 |
| 429 | rate_limit | 是(带退避) | 触发限流。看 Retry-After Header 决定等多久。 |
| 500 | server_error | 是 | 我们这边出了状况。指数退避重试。 |
| 502 | upstream_error | 是(自动 fallback) | 上游模型供应商故障。我们已自动尝试切换路由——返回到你这层即说明所有路由都坏,重试或换模型。 |
| 503 | overloaded | 是 | 流量过载。等几秒重试。 |
重试策略
**通用规则**:
- **4xx 不重试**(除了 408、429)。
- **5xx 必须重试**。
- **最多 3 次**。再多就让它失败到上层逻辑去处理。
- **指数退避 + 抖动**:1s → 2s → 4s,每次 ±20% 随机偏移避免同步重试踩踏。
- **遵守 Retry-After**:429/503 响应里如果有这个 Header,按它说的等。
pythonimport time, random from openai import OpenAI, APIError, RateLimitError client = OpenAI(api_key="<KEY>", base_url="https://api.aicodedog.com/v1") def chat_with_retry(**kwargs): last_err = None for attempt in range(3): try: return client.chat.completions.create(**kwargs) except RateLimitError as e: wait = (2 ** attempt) * (1 + random.uniform(-0.2, 0.2)) time.sleep(wait) last_err = e except APIError as e: if e.status_code and 500 <= e.status_code < 600: wait = (2 ** attempt) * (1 + random.uniform(-0.2, 0.2)) time.sleep(wait) last_err = e else: raise # 4xx 不可恢复 raise last_err
Context 超长
如果你发的 messages + max_tokens 超过模型上下文上限,会立即返回 400 并附 code: "context_length_exceeded"。
- **短期**:截断历史消息(保留 system + 最近 N 轮)。
- **中期**:换个上下文更长的模型,例如
Kimi-K2.6(200K)或claude-opus-4-7(200K)。 - **长期**:上 RAG(见 Embeddings),把长文档分段索引、按需检索。
幂等性
我们的 API 是**幂等安全**的——重试同一个请求不会被重复扣费两次(每次失败都不计费,只有成功响应才计费)。 但你侧的业务逻辑可能不是幂等的(例如把回复发到下游 webhook);建议给关键调用加自己的
request_id 去重。