给 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,确认退避会增加并最终停止。

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

相关推荐
东鹏特饮2 分钟前
系统运维(传统/通用运维)面试题
开发语言·php
其实防守也摸鱼3 分钟前
个人学习 Pwn 思路:从基础到漏洞利用的进阶路径
大数据·前端·人工智能·chrome·算法·安全·网络安全
甲维斯4 分钟前
Workbuddy+HY4 略超预期!
人工智能
今天要早睡_27 分钟前
C++01_入门基础复习
开发语言·c++
天远API42 分钟前
零信任架构实战:基于天远运营商三要素详版V即时版构建自动化消费电子大促电商平台高价值权益秒杀与优惠券防羊毛高并发实名核验网关
运维·人工智能·架构·自动化
朱涛的自习室1 小时前
212 个需求、22 万行代码:Agent 接管开源项目的 19 天
android·前端·人工智能
美林数据Tempodata1 小时前
高职大数据技术专业升级的六个落地样本:从产业链需求库到实训室数据链路
大数据·人工智能·数字化转型·产教融合·ai教育
美好世界1 小时前
OpenAI Codex 源码深度剖析(三):执行引擎与内核沙箱深度剖析
人工智能
敖老师1 小时前
Dify 接入高德地图 MCP:Agent 策略、新旧节点与配置全流程避坑指南
人工智能
Front_Yue1 小时前
在 Rokid AIUI 上做「拍照识花」:图像链路与踩坑记录
人工智能