给 Claude API 调用补上超时重试和错误分类

直接调用模型接口时,偶发超时、限流和上游 5xx 是最常见的异常。本文用一个小型 Python 客户端,把超时边界、有限重试和错误分类放到同一层,方便后续接入业务。

设置连接与读取超时

请求必须有明确的时间边界,连接超时和读取超时可以分别控制。

python 复制代码
import requests

session = requests.Session()
response = session.post(
    "https://your-api-endpoint.example/v1/messages",
    headers={
        "x-api-key": "sk-your-key",
        "anthropic-version": "2023-06-01",
        "content-type": "application/json",
    },
    json={
        "model": "claude-sonnet-4-6",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": "连通性测试"}],
    },
    timeout=(5, 60),
)
response.raise_for_status()

如果通过 jiekou.vip等接入平台调用,只需按照对应文档替换地址和认证配置,不要把配置写死在业务函数中。

按错误类型决定动作

认证失败和参数错误不适合重试;429、网络异常以及部分 5xx 则可以有限重试。

python 复制代码
import random
import time

RETRYABLE_STATUS = {429, 500, 502, 503, 504}


def request_with_retry(send, attempts=4):
    for attempt in range(attempts):
        try:
            response = send()
            if response.status_code not in RETRYABLE_STATUS:
                response.raise_for_status()
                return response
        except (requests.Timeout, requests.ConnectionError):
            if attempt == attempts - 1:
                raise
        else:
            if attempt == attempts - 1:
                response.raise_for_status()

        time.sleep(min(8, 2 ** attempt) + random.uniform(0, 0.3))

指数退避配合随机抖动,可以避免多个实例同时重试。

统一错误分类

业务层只需要关心错误类别,不必到处判断底层异常文本。

python 复制代码
from dataclasses import dataclass


@dataclass
class ApiError:
    category: str
    status_code: int | None
    retryable: bool
    message: str


def classify_error(exc=None, response=None):
    if isinstance(exc, requests.Timeout):
        return ApiError("timeout", None, True, str(exc))
    if isinstance(exc, requests.ConnectionError):
        return ApiError("connection", None, True, str(exc))

    status = response.status_code
    if status == 401:
        return ApiError("authentication", status, False, response.text)
    if status == 429:
        return ApiError("rate_limit", status, True, response.text)
    if status >= 500:
        return ApiError("upstream", status, True, response.text)
    return ApiError("request", status, False, response.text)

日志和告警可以按 category 聚合,比依赖变化的错误文案更稳定。

记录调用边界

至少记录请求 ID、模型、耗时、状态码和最终错误类别。密钥不能写入日志,用户提示词也不应整段落盘。

python 复制代码
import logging
import time
import uuid

logger = logging.getLogger("model_api")


def call_model(send, model):
    request_id = uuid.uuid4().hex
    started = time.perf_counter()
    try:
        response = request_with_retry(send)
        logger.info(
            "model_call_ok",
            extra={
                "request_id": request_id,
                "model": model,
                "status_code": response.status_code,
                "duration_ms": round((time.perf_counter() - started) * 1000),
            },
        )
        return response.json()
    except Exception:
        logger.exception(
            "model_call_failed",
            extra={
                "request_id": request_id,
                "model": model,
                "duration_ms": round((time.perf_counter() - started) * 1000),
            },
        )
        raise

验证故障路径

上线前至少模拟三种情况:把读取超时调小,确认超时会重试;使用错误密钥,确认 401 只失败一次;模拟 429 和 503,确认退避会增加并最终停止。

把这些边界补齐后,模型调用就有了明确的失败处理方式,后续接入业务时也更容易定位问题。

相关推荐
damoluomu3 天前
挑 PHP CMS 之前,先学会看它的协议
php
回眸&啤酒鸭3 天前
【回眸】Minicart 电商购物车核心功能落地指南
人工智能
一隅论数智3 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
AI的探索之旅3 天前
97 个 OpenCV 实例(三十):双目立体,从标定到点云
人工智能·opencv·计算机视觉
AlbertZein3 天前
Step-5-Preview 上手实测:3D 游戏、金融分析、网页设计一次跑完
人工智能·aigc
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
LaughingZhu3 天前
Product Hunt 每日热榜 | 2026-09-19
人工智能·深度学习·神经网络·搜索引擎·百度
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
wukangjupingbb4 天前
智能网联汽车安全能力框架
人工智能