Python调用ChatGPT API的实战指南:从鉴权到流式响应处理

2次阅读
没有评论

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

image.webp

背景痛点

在实际开发中,直接调用 OpenAI API 会遇到几个典型问题:

Python 调用 ChatGPT API 的实战指南:从鉴权到流式响应处理

  • 密钥管理风险 :很多开发者习惯将 API 密钥硬编码在代码中,这会导致安全风险。一旦代码泄露,密钥也会暴露。

  • 响应延迟 :尤其是在处理长文本或复杂请求时,API 的响应时间可能较长,影响用户体验。

  • Token 消耗监控 :缺乏有效的 Token 计数机制,可能导致意外的高额费用。

  • 错误处理不足 :常见的错误如 429(速率限制)或 503(服务不可用)如果没有妥善处理,会导致服务中断。

requests 库 vs. 官方 openai 库

  • requests 库 :灵活性高,可以自定义请求头和参数,但需要手动处理鉴权和错误重试。

  • 官方 openai 库 :封装了鉴权和部分错误处理逻辑,使用更方便,但某些高级功能需要手动扩展。

技术实现

1. 使用环境变量管理 API 密钥

最佳实践是将 API 密钥存储在环境变量中,避免硬编码。示例:

import os
from openai import OpenAI

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

2. 处理对话上下文

openai.ChatCompletion.create 可以处理多轮对话。以下是一个简单示例:

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Tell me a joke."}
    ]
)
print(response.choices[0].message.content)

3. 流式响应处理

通过设置 stream=True,可以实现流式响应,逐步接收数据:

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "Explain Python generators."}],
    stream=True
)

for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

生产级代码示例

以下是一个封装了错误处理和进度显示的 Python 类:

from typing import List, Dict, Optional
import time
from tqdm import tqdm
from openai import OpenAI, APIError

class ChatGPTClient:
    def __init__(self, api_key: str, max_retries: int = 3):
        self.client = OpenAI(api_key=api_key)
        self.max_retries = max_retries

    def send_message(
        self,
        messages: List[Dict[str, str]],
        model: str = "gpt-3.5-turbo",
        stream: bool = False,
    ) -> Optional[str]:
        retries = 0
        while retries < self.max_retries:
            try:
                response = self.client.chat.completions.create(
                    model=model,
                    messages=messages,
                    stream=stream,
                )
                if stream:
                    full_response = ""
                    for chunk in tqdm(response):
                        if chunk.choices[0].delta.content:
                            full_response += chunk.choices[0].delta.content
                    return full_response
                else:
                    return response.choices[0].message.content
            except APIError as e:
                if e.status_code in [429, 503]:
                    retries += 1
                    time.sleep(2 ** retries)  # Exponential backoff
                else:
                    raise e
        return None

进阶考量

1. 异步 IO 提升性能

使用 aiohttphttpx 可以实现异步请求,提升并发性能。示例:

import httpx

async def async_chat_completion(messages):
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "https://api.openai.com/v1/chat/completions",
            headers={"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}"},
            json={"model": "gpt-3.5-turbo", "messages": messages},
        )
        return response.json()

2. Token 计数与成本控制

OpenAI 的响应中包含 usage 字段,可以监控 Token 消耗:

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "Explain Python decorators."}]
)
print(f"Tokens used: {response.usage.total_tokens}")

3. 敏感数据过滤

在发送请求前,可以对输入内容进行过滤,避免泄露敏感信息:

def filter_sensitive_data(text: str) -> str:
    sensitive_keywords = ["password", "credit card", "SSN"]
    for keyword in sensitive_keywords:
        if keyword in text.lower():
            raise ValueError("Sensitive data detected in input.")
    return text

避坑指南

1. 中国地区 API 调用的特殊配置

由于网络限制,可能需要配置代理或使用第三方中转服务。示例:

import os

os.environ["HTTP_PROXY"] = "http://your-proxy-address:port"
os.environ["HTTPS_PROXY"] = "http://your-proxy-address:port"

2. 上下文窗口超限的检测

GPT 模型有 Token 限制(如 4096 Tokens),超出会报错。可以通过以下方式检测:

from transformers import GPT2Tokenizer
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
tokens = tokenizer.encode("Your input text here")
if len(tokens) > 4000:  # Leave some room for response
    print("Input too long, please shorten it.")

3. 冷启动延迟优化

首次调用 API 可能会有冷启动延迟。可以通过预热请求减少影响:

# 发送一个简单的预热请求
client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "Hello"}]
)

动手实验

尝试修改 temperature 参数,观察输出差异。temperature 控制生成文本的随机性,值越高输出越多样。示例:

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "Write a short story about a robot."}],
    temperature=0.7  # 尝试调整为 0.2 或 1.0
)
print(response.choices[0].message.content)

通过调整参数,可以更直观地理解模型的行为,从而更好地应用于实际场景。

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