Files
Practical_Training_Assignment/web/src/services/chat_service.ts

92 lines
2.4 KiB
TypeScript

import type { AxiosRequestConfig } from "axios"
import type { IChatWithLLMRequest } from "@/interfaces"
import BaseClientService, { BaseUrl } from "./base_service.ts"
export class ChatService {
public static basePath = BaseUrl
/** Chat with LLM */
public static async ChatWithLLM(
accessToken: string,
request: IChatWithLLMRequest,
onProgress: (content: string) => void,
) {
let response
let buffer = ""
let accumulatedContent = ""
try {
response = await fetch("/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(request),
})
if (!response.ok) {
// eslint-disable-next-line unicorn/error-message
throw new Error()
}
const reader = response.body?.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader!.read()
if (done)
break
// 将二进制数据转为字符串并存入缓冲区
buffer += decoder.decode(value)
// 查找换行符分割数据
const lines = buffer.split("\n")
// 保留未处理完的部分
buffer = lines.pop() || ""
// 处理每一行
for (const line of lines) {
const trimmedLine = line.trim()
if (!trimmedLine)
continue
if (trimmedLine.startsWith("data: ")) {
const jsonStr = trimmedLine.slice(6)
// 处理结束标记
if (jsonStr === "[DONE]") {
onProgress(accumulatedContent) // 最终更新
return
}
try {
const data = JSON.parse(jsonStr)
if (data.choices?.[0]?.delta?.content) {
// 累积内容
accumulatedContent += data.choices[0].delta.content
// 触发回调
onProgress(accumulatedContent)
}
}
catch (err) {
console.error("JSON解析失败:", err)
}
}
}
}
}
catch (err) {
console.error("Error:", err)
}
}
// 获取模型列表
public static GetModelList(config?: AxiosRequestConfig<any>) {
return BaseClientService.get(`${this.basePath}/model/list`, config)
}
}