Express调用OpenAI API遇JSON解析错误:复杂System Prompt引发请求失败
问题排查:OpenAI API请求JSON解析失败
我用Express编写了代码,意图通过传入包含指令、用户档案、食材清单的system_prompt对象,调用gpt-3.5-turbo模型生成指定格式的一日饮食计划,但持续收到**"We could not parse the JSON body of your request"**错误。尝试将system prompt以字符串或JS对象传递均失败,但将system角色的content改为简单字符串(如"You are helping AI")时代码可正常运行,此前类似结构的项目未出现该问题,请求排查原因。
原代码
const express = require("express"); const https = require("https"); const cors = require("cors"); const app = express(); app.use(cors()); app.use(express.json()); const OPENAI_API_KEY = KEY; const system_prompt = { "instruction": "You are a multilingual AI assistant called Foodion. Please provide a 1-day diet plan based on the following grocery list. The diet plan should include breakfast, lunch, and dinner. Each meal should have at least two recipes. The diet plan must be returned as a JSON object in the following format: {diet: {breakfast: {recipe1: '', instructions1: '', recipe2: '', instructions2: ''}, lunch: {recipe3: '', instructions3: '', recipe4: '', instructions4: ''}, dinner: {recipe5: '', instructions5: '', recipe6: '', instructions6: ''}}}. The response must be a diet plan, and it must not exceed one day. If the user requests a diet plan for more than one day, respond with JSON object that says {'error_message': 'Max 1 günlük diet programı isteyebilirsiniz.'}", "user_profile": { "gender": "Male", "age": 18, "height": 180, "activity_level": "active sport life" }, "grocery_list": [ "3600 gram makarna", "4500 gram pirinc", "500 gram salca", "500 gram mantar", "500 gram zeytin", "500 gram turşu", "500 gram ekmek", "10 adet yumurta", "500 gram peynir", "1000 gram tost ekmeği", "1000 gram un", "500 gram tuz", "250 gram tereyağı", "200 gram salam dilimi", "200 gram sucuk dilimi", "300 gram pastırma dilimi", "500 gram sosis", "200 gram domates", "300 gram salatalık", "200 gram biber", "1000 gram yoğurt", "1000 gram sogan", "100 gram sarimsak" ] } app.post("/generate-text", async (req, res) => { const messageContent = req.body.message; const data = JSON.stringify({ model: "gpt-3.5-turbo", messages: [ { role: "system", content: system_prompt}, { role: "user", content: messageContent }, ], max_tokens: 2048, temperature: 0.5, top_p: 0.8, }); const options = { hostname: "api.openai.com", path: "/v1/chat/completions", method: "POST", headers: { Authorization: `Bearer ${OPENAI_API_KEY}`, "Content-Type": "application/json", "Content-Length": data.length, }, }; const request = https.request(options, (response) => { const chunks = []; response.on("data", (chunk) => { chunks.push(chunk); }); response.on("end", () => { const responseBody = Buffer.concat(chunks); res.send(responseBody); // Send the raw response body as is. }); }); request.on("error", (error) => { console.error("Error with OpenAI request:", error); res.status(500).send("Error with OpenAI request: " + error.message); }); request.write(data); request.end(); }); const PORT = process.env.PORT || portnumber; app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
问题原因及解决方案
1. 核心原因:OpenAI API的content字段仅支持字符串类型
OpenAI Chat Completions API明确要求,messages数组中每个消息对象的content属性必须是字符串,不能直接传入JS对象。你直接将system_prompt这个对象赋值给content,JSON序列化后会生成嵌套JSON结构,不符合API的参数格式要求,这是导致解析失败的根本原因。
2. 正确传递结构化提示的两种方式
需要将system_prompt的结构化内容转换为字符串格式,让模型能理解:
- 方式1:将对象序列化为JSON字符串
{ role: "system", content: JSON.stringify(system_prompt) }, - 方式2:用自然语言格式化输出(可读性更强)
{ role: "system", content: ` 你是多语言AI助手Foodion,请根据以下信息生成1日饮食计划: 指令:${system_prompt.instruction} 用户档案:性别${system_prompt.user_profile.gender},年龄${system_prompt.user_profile.age},身高${system_prompt.user_profile.height}cm,活动水平${system_prompt.user_profile.activity_level} 食材清单:${system_prompt.grocery_list.join(',')} ` },
3. 额外语法修复
原代码中system_prompt对象的grocery_list属性末尾多了一个尾逗号,虽然JS允许,但建议移除避免潜在的兼容问题。
4. 验证请求格式
发送请求前可以打印data变量,检查最终生成的JSON字符串是否符合API要求:
console.log(data);
内容的提问来源于stack exchange,提问作者Aldarion
相关产品推荐
相关产品推荐

