export interface TestMessage{ role:string content:string } export class TestCompletion{ token:string = "r:60abef69e7cd8181b146ceaba1fdbf02" messageList:any = [] stream:boolean = true; constructor(messageList:any){ this.messageList = messageList || this.messageList } async sendMessage(messageList?:null|Array,onMessage?: (content: string) => void):Promise{ this.messageList = messageList || this.messageList let body = { "messages": this.messageList, "stream": this.stream, "model": "fmode-4.5-128k", "temperature": 0.5, "presence_penalty": 0, "frequency_penalty": 0, "token": "Bearer "+this.token } let response = await fetch("https://server.fmode.cn/api/apig/aigc/gpt/v1/chat/completions", { "headers": { }, "body": JSON.stringify(body), "method": "POST", "mode": "cors", "credentials": "omit" }); /** 单次响应 HTTP短连接请求 {"choices":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"您好!我是一个人工智能助手,旨在帮助您回答问题、提供信息和解决各种问题。我可以处理许多主题,包括科技、历史、文化、语言学习等。如果您有任何具体的问题或需要了解的内容,请随时告诉我!","refusal":null,"role":"assistant"}}],"created":1751509370,"id":"chatcmpl-Bp3t41MP4pb2NR38n1ylrJw922SBZ","model":"gpt-4o-mini-2024-07-18","object":"chat.completion","system_fingerprint":"fp_efad92c60b","usage":{"completion_tokens":55,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":15,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":70}} */ if(this.stream == false){ let data = await response.json() console.log(data) let lastContent = data?.choices?.[0]?.message?.content return lastContent } /** * 流式加载 HTTP Event Stream 模式 长连接获取 */ // Stream mode handling if (!response.body) { throw new Error("No response body in stream mode"); } const reader = response.body.getReader(); const decoder = new TextDecoder("utf-8"); let accumulatedContent = ""; try { while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); const lines = chunk.split('\n').filter(line => line.trim() !== ''); for (const line of lines) { if (line.startsWith('data:') && !line.includes('[DONE]')) { try { const jsonStr = line.substring(5).trim(); const data = JSON.parse(jsonStr); const content = data?.choices?.[0]?.delta?.content || ''; if (content) { accumulatedContent += content; if (onMessage) { onMessage(accumulatedContent); } } } catch (e) { console.error("Error parsing stream data:", e); } } } } } finally { reader.releaseLock(); } return accumulatedContent; } } /** * 使用AI生成符合指定结构的JSON数据 * @param prompt 任务要求的整体提示词 * @param jsonSchema 期望的JSON结构描述(用于提示词) * @param example 可选的JSON示例(帮助AI理解格式) * @param onMessage 实时生成内容回调 * @returns 解析后的JSON对象 */ export async function completionJSON( prompt:string, jsonSchema: string, example: object | null = null, onMessage?: (content: string) => void ): Promise { // 1. 构建提示词 const JsonResultParsePrompt = `请严格按照以下要求生成JSON数据: - 数据结构要求:${jsonSchema} - 只能返回一个完整的JSON对象 确保JSON格式正确 - 注意返回的JSON格式每个KEY都有""包裹和Value之间都有:`; // ${example ? `2. 参考示例格式:\n${JSON.stringify(example, null, 2)}` : ''} // 2. 初始化消息列表 const messages: TestMessage[] = [ { role: "user", content: prompt+JsonResultParsePrompt } ]; // 3. 创建TestCompletion实例 const completion = new TestCompletion(messages); // 4. 存储累积内容和JSON对象 let fullContent = ""; let jsonObject: any = null; // 5. 发送请求并处理流式响应 const result = await completion.sendMessage(null, (content) => { fullContent = content; }); console.log("fullContent",fullContent) // 6. 最终JSON提取(确保获取完整内容) try { // 再次尝试从完整内容中提取JSON jsonObject = extractJSON(fullContent); } catch (e) { console.error("JSON解析失败:", e); console.log("原始内容:", fullContent); throw new Error("生成的响应不符合JSON格式"); } return jsonObject; } function extractJSON(str:string){ let stack = 0; let startIndex = -1; let result = null; for (let i = 0; i < str.length; i++) { if (str[i] === '{') { if (stack === 0) startIndex = i; stack++; } else if (str[i] === '}') { stack--; if (stack === 0 && startIndex !== -1) { try { result = JSON.parse(str.slice(startIndex, i + 1)); break; } catch (e) { // 继续尝试下一个可能的 JSON startIndex = -1; } } } } return result; };