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

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

相关推荐
天远数科39 分钟前
风险治理实战:基于天远车信盟出险构建自动化理赔核保流水线
java·网络·人工智能·自动化
Draw Stars1 小时前
Git BASH安装教程
开发语言·git·bash
lifallen1 小时前
Skill 的生命周期:问题消失以后
人工智能·学习·ai·ai编程
vortex51 小时前
一文讲透 Zsh 与 Bash 的区别
开发语言·bash
千谦阙听1 小时前
C++类和对象(中):默认成员函数、构造与析构、拷贝构造、运算符重载
开发语言·c++·学习
YaraMemo1 小时前
元启发式算法框架
人工智能·算法·5g·信息与通信·启发式算法·信号处理
草邦设计开发团队_媒体资源平台1 小时前
GEO 信源整合一键发布软文:从内容生产到流量获客的自动化实践
运维·人工智能·自动化
zzz_23681 小时前
个人 AI 记忆如何跨工具复用:用 Markdown、索引和 Skill 搭一个可治理的记忆库
前端·人工智能·react.js·前端框架·agent·agent测评
霸道流氓气质1 小时前
Spring AI 输出解析器进阶
人工智能·windows·spring