You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Solara构建ChatGPT界面时如何解决KeyError: 'choices'?

问题分析与解决

为什么会出现KeyError: 'choices'

当OpenAI API调用失败时,返回的JSON响应里不会包含choices字段,取而代之的是error字段,常见触发原因包括:

  • API调用速率超限(超出免费额度或付费限额)
  • API密钥无效、过期或权限不足
  • 请求的prompt总token数超过模型上限(text-davinci-003最大支持4096token,当前max_tokens设为3000,叠加历史对话后容易超限)
  • 网络波动或OpenAI服务器临时故障

当前代码直接硬取response.json()['choices'][0]['text'],未做任何错误校验,一旦API返回错误响应就会触发KeyError。

为什么捕获异常后后续请求持续失败

你的异常处理逻辑仅做了简单的睡眠和提示,未解决核心问题:

  1. 未排查具体错误原因,导致根本问题(比如速率限制仍在生效、token超限)持续存在
  2. 未验证API响应状态,盲目重试只会重复触发错误
  3. 未针对不同错误类型做差异化处理,比如速率限制需要等待指定时长,而密钥错误需要用户手动修正

修复方案

1. 先明确错误详情

API调用后先获取完整响应,检查状态码并提取错误信息,方便定位问题。

2. 完善异常处理逻辑

  • 检查响应状态码,非200直接处理HTTP错误
  • 提取OpenAI返回的具体错误提示,给用户明确反馈
  • 根据错误类型决定后续操作(比如速率限制自动等待重试,密钥错误直接提示用户修正)
  • 确保对话历史gMemory不会因错误被污染

修改后的代码示例

import requests
import time

# 假设gMemory、gptResponse、submitButton为已定义的Solara响应式变量
try:
    global gMemory
    gptResponse.value = "==GENERATING-RESPONSE=="

    url = "https://api.openai.com/v1/completions"
    headers = {"Content-Type": "application/json", "Authorization": "Bearer [REDACTED]"}
    prompt = (gMemory + "\nUSER REQUEST: " + text).strip()
    data = {
        "model": "text-davinci-003",
        "prompt": prompt,
        "max_tokens": 3000,
        "temperature": 1.0
    }
    
    response = requests.post(url, headers=headers, json=data)
    response.raise_for_status()  # 触发HTTP状态码异常(如429速率限制、401认证失败)
    json_response = response.json()
    
    # 校验响应结构完整性
    if "choices" not in json_response or len(json_response["choices"]) == 0:
        raise ValueError("API未返回有效响应内容")
    
    out = json_response['choices'][0]['text'].strip()
    # 格式化对话历史,避免内容混淆
    gMemory += f"USER REQUEST: {text}\nAI RESPONSE: {out}\n"
    gptResponse.value = out
        
except requests.exceptions.HTTPError as e:
    # 提取OpenAI返回的错误详情
    error_info = response.json().get("error", {}).get("message", "未知HTTP错误")
    gptResponse.value = f"==API错误: {error_info}=="
    # 速率限制时按返回的等待时长处理
    if response.status_code == 429:
        wait_time = int(response.headers.get("Retry-After", 10))
        time.sleep(wait_time)
    submitButton.value = False
except (KeyError, ValueError) as e:
    gptResponse.value = f"==响应解析错误: {str(e)}=="
    submitButton.value = False
except Exception as e:
    # 捕获其他未知异常
    gptResponse.value = f"==未知错误: {str(e)}=="
    submitButton.value = False

额外优化建议

  • 限制gMemory的长度:用tiktoken库计算对话历史的token数,超过模型上限时自动截断旧对话,避免触发token超限错误
  • 规范对话历史格式:给用户请求和AI响应添加明确分隔符,避免模型混淆对话上下文
  • 替换全局变量:Solara推荐用solara.reactive管理状态,避免全局变量引发的状态异常

内容的提问来源于stack exchange,提问作者cameronmg-j

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:57:19