'use strict'; /** * Node-RED Function 节点脚本:处理大模型 HTTP 响应。 * 将响应解析为 mock 数据并写回 msg。 */ function processLlmResponse(msg, node) { const context = msg.llmContext || {}; if (!context.prompt || !context.operationCtx) { const err = 'LLM 上下文缺失,无法解析响应'; node.error(err, msg); msg.error = err; return msg; } if (msg.statusCode && (msg.statusCode < 200 || msg.statusCode >= 300)) { const err = `大模型接口返回状态码 ${msg.statusCode}`; node.error(err, msg); msg.error = err; return msg; } let raw = msg.payload; if (Buffer.isBuffer(raw)) { raw = raw.toString('utf8'); } if (typeof raw === 'string') { try { raw = JSON.parse(raw); } catch (error) { node.error(`无法解析大模型响应:${error.message}`, msg); msg.error = error.message; return msg; } } try { const parsed = parseModelResponse(raw); msg.llmRaw = raw; msg.mock = Object.assign({}, msg.mock, parsed.mock); msg.mockSource = context.provider || 'dashscope'; msg.mockPrompt = context.prompt; msg.mockCandidates = context.operationCtx.candidates; msg.mockAutoSelected = !!context.operationCtx.autoSelected; msg.payload = msg.mock; delete msg.llmContext; if (msg.headers && msg.headers.Authorization) { delete msg.headers.Authorization; } delete msg.error; return msg; } catch (error) { node.error(`大模型参数生成失败:${error.message}`, msg); msg.error = error.message; return msg; } } function parseModelResponse(response) { if (!response || typeof response !== 'object') { throw new Error('大模型响应为空或不是对象'); } if (response.mock && typeof response.mock === 'object') { return { mock: response.mock }; } const choices = Array.isArray(response.choices) ? response.choices : []; const firstChoice = choices[0]; const message = firstChoice && firstChoice.message ? firstChoice.message : null; const content = message && typeof message === 'object' ? message.content : null; if (!content) { throw new Error('响应中缺少 choices[0].message.content'); } let mockObject; if (typeof content === 'string') { try { mockObject = JSON.parse(content); } catch (err) { throw new Error(`无法解析模型返回的 JSON:${err.message},原始文本:${content}`); } } else if (Array.isArray(content)) { const jsonPart = content.find(part => part.type === 'output_text' || part.type === 'text' || part.type === 'json'); const text = jsonPart && jsonPart.text ? jsonPart.text : null; if (!text) { throw new Error('响应内容不是字符串,且未找到可解析的文本段'); } try { mockObject = JSON.parse(text); } catch (err) { throw new Error(`无法解析模型返回的 JSON:${err.message},原始文本:${text}`); } } else { throw new Error('模型返回的 message.content 既不是字符串也不是文本片段数组'); } if (!mockObject || typeof mockObject !== 'object') { throw new Error('模型返回的 JSON 不是对象'); } const normalisedMock = { pathParams: mockObject.pathParams || mockObject.path_parameters || {}, query: mockObject.query || mockObject.query_params || {}, headers: mockObject.headers || {}, cookies: mockObject.cookies || {}, body: mockObject.body || {}, notes: mockObject.notes || '', }; return { mock: normalisedMock }; } return processLlmResponse(msg, node);