使用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。
为什么捕获异常后后续请求持续失败
你的异常处理逻辑仅做了简单的睡眠和提示,未解决核心问题:
- 未排查具体错误原因,导致根本问题(比如速率限制仍在生效、token超限)持续存在
- 未验证API响应状态,盲目重试只会重复触发错误
- 未针对不同错误类型做差异化处理,比如速率限制需要等待指定时长,而密钥错误需要用户手动修正
修复方案
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
相关产品推荐
相关产品推荐

