ChatGPT Python SDK 实战:如何解决 API 调用中的并发与超时问题

1次阅读
没有评论

共计 2424 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

高并发场景下的典型问题

在实际项目中,我们经常遇到需要批量处理大量请求的场景。例如,一个客服系统需要同时处理数百条用户咨询,每条咨询都需要调用 ChatGPT API 获取回复。这种情况下,最常见的故障模式包括:

ChatGPT Python SDK 实战:如何解决 API 调用中的并发与超时问题

  • 429 Too Many Requests:短时间内发送过多请求触发了速率限制
  • 连接中断:网络波动导致请求失败
  • 超时未响应:服务器处理时间过长导致客户端等待超时

同步 vs 异步方案对比

传统的同步请求方式使用 requests 库,代码简单但性能有限。我们做了一个简单的基准测试:

  1. 发送 100 个请求,同步方式耗时约 15 秒
  2. 同样的请求量,异步方式 (aiohttp) 仅需 2 秒

异步 IO 的优势在于可以同时处理多个请求,特别适合 API 调用这种 IO 密集型操作。

核心解决方案实现

带连接池的异步客户端

import aiohttp
from typing import AsyncIterator

class AsyncChatGPTClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.session = None

    async def __aenter__(self):
        connector = aiohttp.TCPConnector(limit_per_host=10)  # 控制每个主机的连接数
        self.session = aiohttp.ClientSession(connector=connector)
        return self

    async def __aexit__(self, exc_type, exc, tb):
        await self.session.close()

    async def chat_completion(self, messages: list) -> dict:
        headers = {"Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }

        payload = {
            "model": "gpt-3.5-turbo",
            "messages": messages
        }

        async with self.session.post(
            "https://api.openai.com/v1/chat/completions",
            json=payload,
            headers=headers
        ) as response:
            return await response.json()

动态速率限制调节

import time
import math

class RateLimiter:
    def __init__(self, max_rate: int, time_window: float = 60.0):
        self.max_rate = max_rate
        self.time_window = time_window
        self.tokens = max_rate
        self.last_refill = time.monotonic()

    async def wait_for_token(self):
        now = time.monotonic()
        elapsed = now - self.last_refill

        # 根据耗时补充 token
        if elapsed > 0:
            self.tokens = min(
                self.max_rate,
                self.tokens + (self.max_rate * elapsed / self.time_window)
            )
            self.last_refill = now

        if self.tokens >= 1:
            self.tokens -= 1
            return

        # 采用指数退避算法等待
        sleep_time = (self.time_window / self.max_rate) * 1.5
        await asyncio.sleep(sleep_time)
        await self.wait_for_token()

错误处理装饰器

from functools import wraps
import asyncio

def retry(max_retries=3, base_delay=1.0):
    def decorator(f):
        @wraps(f)
        async def wrapper(*args, **kwargs):
            retries = 0
            while retries < max_retries:
                try:
                    return await f(*args, **kwargs)
                except (aiohttp.ClientError, asyncio.TimeoutError) as e:
                    retries += 1
                    if retries >= max_retries:
                        raise

                    delay = base_delay * (2 ** retries)  # 指数退避
                    await asyncio.sleep(delay)
        return wrapper
    return decorator

生产环境检查清单

1. 设置合理的 max_retries

  • 对于暂时性错误(429, 5xx),建议重试 3 - 5 次
  • 对于认证错误(401),不应该重试
  • 结合业务需求调整,关键业务可以适当增加重试次数

2. 监控埋点最佳实践

  • 记录每个请求的耗时、状态码
  • 监控 API 配额使用情况
  • 设置异常告警,当错误率超过阈值时通知

3. 敏感信息的安全存储

  • 不要将 API 密钥硬编码在代码中
  • 使用环境变量或密钥管理服务
  • 为每个环境 (开发、测试、生产) 使用不同的密钥

进阶思考

跨地域 API 端点切换

可以考虑以下策略:

  1. 维护多个地域的 API 端点列表
  2. 定期测试各端点的延迟
  3. 根据延迟自动选择最优端点
  4. 当主端点不可用时自动切换到备用端点

content-filter 拦截处理

当遇到内容过滤拦截时,可以尝试:

  1. 调整输入内容的措辞
  2. 添加更明确的上下文
  3. 对于高风险内容,可以预先进行本地过滤
  4. 记录被拦截的内容类型,优化输入策略

总结

通过异步 IO、速率限制和错误重试机制的结合,我们可以显著提升 ChatGPT API 的调用稳定性。在实际项目中,建议根据业务需求调整参数,并建立完善的监控体系。这些优化不仅能提高成功率,还能更好地利用 API 配额,降低使用成本。

正文完
 0
评论(没有评论)