completion.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. export interface TestMessage{
  2. role:string
  3. content:string
  4. }
  5. export class TestCompletion{
  6. token:string = "r:60abef69e7cd8181b146ceaba1fdbf02"
  7. messageList:any = []
  8. stream:boolean = true;
  9. constructor(messageList:any){
  10. this.messageList = messageList || this.messageList
  11. }
  12. async sendMessage(messageList?:null|Array<TestMessage>,onMessage?: (content: string) => void):Promise<any>{
  13. this.messageList = messageList || this.messageList
  14. let body = {
  15. "messages": this.messageList,
  16. "stream": this.stream,
  17. "model": "fmode-4.5-128k",
  18. "temperature": 0.5,
  19. "presence_penalty": 0,
  20. "frequency_penalty": 0,
  21. "token": "Bearer "+this.token
  22. }
  23. let response = await fetch("https://server.fmode.cn/api/apig/aigc/gpt/v1/chat/completions", {
  24. "headers": {
  25. },
  26. "body": JSON.stringify(body),
  27. "method": "POST",
  28. "mode": "cors",
  29. "credentials": "omit"
  30. });
  31. /** 单次响应 HTTP短连接请求
  32. {"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}}
  33. */
  34. if(this.stream == false){
  35. let data = await response.json()
  36. console.log(data)
  37. let lastContent = data?.choices?.[0]?.message?.content
  38. return lastContent
  39. }
  40. /**
  41. * 流式加载 HTTP Event Stream 模式 长连接获取
  42. */
  43. // Stream mode handling
  44. if (!response.body) {
  45. throw new Error("No response body in stream mode");
  46. }
  47. const reader = response.body.getReader();
  48. const decoder = new TextDecoder("utf-8");
  49. let accumulatedContent = "";
  50. try {
  51. while (true) {
  52. const { done, value } = await reader.read();
  53. if (done) break;
  54. const chunk = decoder.decode(value, { stream: true });
  55. const lines = chunk.split('\n').filter(line => line.trim() !== '');
  56. for (const line of lines) {
  57. if (line.startsWith('data:') && !line.includes('[DONE]')) {
  58. try {
  59. const jsonStr = line.substring(5).trim();
  60. const data = JSON.parse(jsonStr);
  61. const content = data?.choices?.[0]?.delta?.content || '';
  62. if (content) {
  63. accumulatedContent += content;
  64. if (onMessage) {
  65. onMessage(accumulatedContent);
  66. }
  67. }
  68. } catch (e) {
  69. console.error("Error parsing stream data:", e);
  70. }
  71. }
  72. }
  73. }
  74. } finally {
  75. reader.releaseLock();
  76. }
  77. return accumulatedContent;
  78. }
  79. }
  80. /**
  81. * 使用AI生成符合指定结构的JSON数据
  82. * @param prompt 任务要求的整体提示词
  83. * @param jsonSchema 期望的JSON结构描述(用于提示词)
  84. * @param example 可选的JSON示例(帮助AI理解格式)
  85. * @param onMessage 实时生成内容回调
  86. * @returns 解析后的JSON对象
  87. */
  88. export async function completionJSON(
  89. prompt:string,
  90. jsonSchema: string,
  91. example: object | null = null,
  92. onMessage?: (content: string) => void
  93. ): Promise<any> {
  94. // 1. 构建提示词
  95. const JsonResultParsePrompt = `请严格按照以下要求生成JSON数据:
  96. - 数据结构要求:${jsonSchema}
  97. - 只能返回一个完整的JSON对象 确保JSON格式正确
  98. - 注意返回的JSON格式每个KEY都有""包裹和Value之间都有:`;
  99. // ${example ? `2. 参考示例格式:\n${JSON.stringify(example, null, 2)}` : ''}
  100. // 2. 初始化消息列表
  101. const messages: TestMessage[] = [
  102. {
  103. role: "user",
  104. content: prompt+JsonResultParsePrompt
  105. }
  106. ];
  107. // 3. 创建TestCompletion实例
  108. const completion = new TestCompletion(messages);
  109. // 4. 存储累积内容和JSON对象
  110. let fullContent = "";
  111. let jsonObject: any = null;
  112. // 5. 发送请求并处理流式响应
  113. const result = await completion.sendMessage(null, (content) => {
  114. fullContent = content;
  115. });
  116. console.log("fullContent",fullContent)
  117. // 6. 最终JSON提取(确保获取完整内容)
  118. try {
  119. // 再次尝试从完整内容中提取JSON
  120. jsonObject = extractJSON(fullContent);
  121. } catch (e) {
  122. console.error("JSON解析失败:", e);
  123. console.log("原始内容:", fullContent);
  124. throw new Error("生成的响应不符合JSON格式");
  125. }
  126. return jsonObject;
  127. }
  128. function extractJSON(str:string){
  129. let stack = 0;
  130. let startIndex = -1;
  131. let result = null;
  132. for (let i = 0; i < str.length; i++) {
  133. if (str[i] === '{') {
  134. if (stack === 0) startIndex = i;
  135. stack++;
  136. } else if (str[i] === '}') {
  137. stack--;
  138. if (stack === 0 && startIndex !== -1) {
  139. try {
  140. result = JSON.parse(str.slice(startIndex, i + 1));
  141. break;
  142. } catch (e) {
  143. // 继续尝试下一个可能的 JSON
  144. startIndex = -1;
  145. }
  146. }
  147. }
  148. }
  149. return result;
  150. };