发送大文本至OpenAI API时遭遇400 Bad Request错误求助
解决方案:OpenAI API大文本400 Bad Request问题
问题核心原因
你遇到的400错误本质是模型上下文长度限制:
gpt-3.5-turbo默认版本(如gpt-3.5-turbo-0301)的上下文上限为4096 token,约对应3000-4000个英文单词(1字符≈0.75 token),20000字符远超该限制,触发API请求校验失败。- 原代码未捕获API返回的具体错误信息,无法直接确认问题根源。
具体解决方案
1. 切换到大上下文模型
最简单的解决方式是改用支持更大容量的模型:
- 将代码中的
model变量改为gpt-3.5-turbo-16k(支持16384 token,约12000个英文单词),足以容纳20000字符的文本。 - 若需要更大容量,可选择
gpt-4-32k(支持32768 token),但成本更高。
修改代码示例:
// 在chatGPT方法中更新model值 String model = "gpt-3.5-turbo-16k";
2. 添加错误信息捕获
原代码仅抛出RuntimeException,无法获取OpenAI返回的具体错误提示。修改代码读取错误流,明确问题:
// 替换chatGPT方法中的try-catch逻辑 try { URL openAIUrl = new URL(url); HttpURLConnection connection = (HttpURLConnection) openAIUrl.openConnection(); connection.setRequestMethod("POST"); connection.setRequestProperty("Authorization", "Bearer " + apiKey); connection.setRequestProperty("Content-Type", "application/json"); chatGptRequest.setModel(model); Gson gson = new Gson(); String body = gson.toJson(chatGptRequest); connection.setDoOutput(true); OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); writer.write(body); writer.flush(); writer.close(); // 新增:处理非200响应 int responseCode = connection.getResponseCode(); BufferedReader br; if (responseCode == HttpURLConnection.HTTP_OK) { br = new BufferedReader(new InputStreamReader(connection.getInputStream())); } else { br = new BufferedReader(new InputStreamReader(connection.getErrorStream())); } String line; StringBuffer response = new StringBuffer(); while ((line = br.readLine()) != null) { response.append(line); } br.close(); // 非200响应时抛出包含具体错误的异常 if (responseCode != HttpURLConnection.HTTP_OK) { throw new RuntimeException("OpenAI API Error: " + response.toString()); } return response.toString(); } catch (IOException e) { throw new RuntimeException(e); }
3. 文本分块处理(不换模型时)
若坚持使用gpt-3.5-turbo基础版,需将大文本拆分为多个小块,分批处理后汇总结果:
- 将长文本按段落/固定长度拆分,每次发送一个文本块+用户问题,让模型逐步提取信息。
- 或先让模型总结每个文本块的关键信息,再合并所有总结结果,最后发送给模型回答最终问题。
示例思路(伪代码):
// 拆分大文本为多个小块 List<String> textChunks = splitLargeText(text, 3000); // 按3000字符拆分 StringBuilder summary = new StringBuilder(); // 分批总结每个文本块 for (String chunk : textChunks) { ChatGptRequest summaryRequest = new ChatGptRequest(); List<Message> summaryMessages = new ArrayList<>(); Message systemMsg = new Message(); systemMsg.setRole("system"); systemMsg.setContent("Summarize key information in this text, especially date-related content: " + chunk); summaryMessages.add(systemMsg); summaryRequest.setMessages(summaryMessages); String chunkSummary = ChatGptClient.chatGPT(summaryRequest); summary.append(chunkSummary).append("\n"); } // 用汇总信息回答原问题 ChatGptRequest finalRequest = new ChatGptRequest(); List<Message> finalMessages = new ArrayList<>(); Message systemMsg = new Message(); systemMsg.setRole("system"); systemMsg.setContent("Based on this summary: " + summary.toString()); finalMessages.add(systemMsg); Message userMsg = new Message(); userMsg.setRole("user"); userMsg.setContent("What is the start and end date?"); finalMessages.add(userMsg); finalRequest.setMessages(finalMessages); String finalResponse = ChatGptClient.chatGPT(finalRequest);
4. 提前校验token长度
在发送请求前计算总token数,超过模型限制时提前处理:
- 使用Java版tiktoken库(如
com.knuddels:tiktoken-java)计算消息的token数量。 - 若超过限制,直接提示用户或自动触发分块逻辑。
示例代码(依赖tiktoken-java):
import com.knuddels.jtokkit.Encodings; import com.knuddels.jtokkit.api.Encoding; import com.knuddels.jtokkit.api.EncodingRegistry; import com.knuddels.jtokkit.api.ModelType; // 计算消息总token数 public static int calculateTotalTokens(List<Message> messages) { EncodingRegistry registry = Encodings.newDefaultEncodingRegistry(); Encoding encoding = registry.getEncodingForModel(ModelType.GPT_3_5_TURBO); int totalTokens = 0; for (Message msg : messages) { // 每个消息的token数:角色字符数 + 内容字符数 + 固定分隔符token totalTokens += encoding.countTokens(msg.getRole()) + encoding.countTokens(msg.getContent()) + 4; } totalTokens += 2; // 系统额外token return totalTokens; } // 在sendData方法中添加校验 public Result sendData() { ChatGptRequest chatGptRequest = new ChatGptRequest(); List<Message> messages = new ArrayList<>(); Message userMessage = new Message(); userMessage.setRole("user"); userMessage.setContent("What is the start and end date?"); messages.add(userMessage); Message systemMessage = new Message(); systemMessage.setRole("system"); systemMessage.setContent(text); messages.add(systemMessage); // 校验token数 int totalTokens = calculateTotalTokens(messages); if (totalTokens > 4096) { // gpt-3.5-turbo基础版上限 return Result.error("Text too long, please reduce content length or use a larger model."); } chatGptRequest.setMessages(messages); String response = ChatGptClient.chatGPT(chatGptRequest); return Result.success(response); }
内容的提问来源于stack exchange,提问作者Shiva Rena
相关产品推荐
相关产品推荐

