class-rxjs-chat-completion.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { Observable, from, of } from 'rxjs';
  2. import { switchMap, map, catchError, finalize } from 'rxjs/operators';
  3. export interface TestRxjsChatMessage {
  4. role: string;
  5. content: string;
  6. }
  7. export class TestRxjsChatCompletion {
  8. messageList: Array<TestRxjsChatMessage>;
  9. constructor(messageList: Array<TestRxjsChatMessage>) {
  10. this.messageList = messageList;
  11. }
  12. createCompletionByStream(options?:{
  13. model?:string
  14. }): Observable<{ content: string, cumulativeContent: string, done: boolean }> {
  15. const token = localStorage.getItem("token");
  16. const bodyJson = {
  17. "token": `Bearer ${token}`,
  18. "messages": this.messageList,
  19. "model": options?.model || "fmode-3.6-16k",
  20. "temperature": 0.5,
  21. "presence_penalty": 0,
  22. "frequency_penalty": 0,
  23. "top_p": 1,
  24. "stream": true
  25. };
  26. return from(fetch("https://test.fmode.cn/api/apig/aigc/gpt/v1/chat/completions", {
  27. "headers": {
  28. "accept": "text/event-stream",
  29. "sec-fetch-dest": "empty",
  30. "sec-fetch-mode": "cors",
  31. "sec-fetch-site": "same-site"
  32. },
  33. "referrer": "https://ai.fmode.cn/",
  34. "referrerPolicy": "strict-origin-when-cross-origin",
  35. "body": JSON.stringify(bodyJson),
  36. "method": "POST",
  37. "mode": "cors",
  38. "credentials": "omit"
  39. })).pipe(
  40. switchMap(response => {
  41. const reader = response.body?.getReader();
  42. if (!reader) {
  43. throw new Error("Failed to get the response reader.");
  44. }
  45. const decoder = new TextDecoder();
  46. let buffer = "";
  47. let messageAiReply = "";
  48. let messageIndex = this.messageList.length;
  49. return new Observable<{ content: string, cumulativeContent: string, done: boolean }>(observer => {
  50. const read = () => {
  51. reader.read().then(({ done, value }) => {
  52. if (done) {
  53. observer.complete();
  54. return;
  55. }
  56. buffer += decoder.decode(value);
  57. let messages = buffer.split("\n");
  58. for (let i = 0; i < messages.length - 1; i++) {
  59. let message = messages[i];
  60. let dataText = message.replace("data: ", "");
  61. if (dataText.startsWith("{")) {
  62. try {
  63. let dataJson = JSON.parse(dataText);
  64. let content = dataJson?.choices?.[0]?.delta?.content || "";
  65. messageAiReply += content;
  66. this.messageList[messageIndex] = {
  67. role: "assistant",
  68. content: messageAiReply
  69. };
  70. observer.next({ content, cumulativeContent: messageAiReply, done: false });
  71. } catch (err) { }
  72. }
  73. if (dataText.startsWith("[")) {
  74. this.messageList[messageIndex] = {
  75. role: "assistant",
  76. content: messageAiReply
  77. };
  78. observer.next({ content: "", cumulativeContent: messageAiReply, done: true });
  79. messageAiReply = "";
  80. }
  81. buffer = buffer.slice(message.length + 1);
  82. }
  83. read();
  84. }).catch(err => observer.error(err));
  85. };
  86. read();
  87. });
  88. }),
  89. catchError(err => {
  90. console.error(err);
  91. return of({ content: "", cumulativeContent: "", done: true });
  92. }),
  93. finalize(() => {
  94. console.log("Stream completed");
  95. })
  96. );
  97. }
  98. }