Files
chatai/src/utils/models.js

203 lines
7.1 KiB
JavaScript
Raw Normal View History

2023-05-15 17:05:36 +08:00
import {dayjs} from "element-plus";
2023-05-17 18:16:53 +08:00
import {nanoid} from "nanoid";
2023-05-12 18:04:58 +08:00
import axios from "./axios";
2023-05-15 01:24:18 +08:00
import {AI_AVATAR, OPEN_AI_KEY} from "./env";
import {JSEncrypt} from "jsencrypt";
2023-05-12 15:53:39 +08:00
class BaseModel {
constructor(props) {
for (const k in props) {
this[k] = props[k];
}
2023-05-16 18:04:04 +08:00
this.headers = {
"Content-Type": "application/json", Accept: "application/json,text/event-stream",
2023-05-16 18:04:04 +08:00
}
}
setApiKey(key) {
this.apiKey = key
this.headers.Authorization = `Bearer ${key}`
}
2023-05-12 15:53:39 +08:00
}
2023-05-17 18:16:53 +08:00
/**
* ChatGPT gpt-3.5-turbo的api.
*/
2023-05-12 15:53:39 +08:00
export class ChatGPT extends BaseModel {
2023-05-12 18:12:21 +08:00
static base = "https://chatwithai.pages.dev"
static avatar = AI_AVATAR
static name = "ChatGPT"
static id = "gpt-3.5-turbo"
static desc = "ChatGPT-3.5所基于的模型"
2023-05-12 18:12:21 +08:00
constructor(params) {
const {avatar, name, desc, id} = ChatGPT
super({avatar, name, desc, id, ...params})
2023-05-15 23:45:11 +08:00
this.setApiKey(OPEN_AI_KEY)
2023-05-12 15:53:39 +08:00
}
2023-05-12 17:32:54 +08:00
2023-05-15 01:24:18 +08:00
async chat(history) {
const messages = history.map(e => ({role: e.role, content: e.msg}))
return await axios.post(ChatGPT.base + "/v1/chat/completions", JSON.stringify({messages, model: this.id}), {
headers: {
Authorization: 'Bearer ' + this.apiKey, "Content-Type": "application/json", Accept: "application/json",
},
}).then(res => res.json()).then(data => data?.choices?.[0]?.message?.content || "key无效或网络波动,请重新尝试");
2023-05-12 17:32:54 +08:00
}
2023-05-15 01:24:18 +08:00
async chatStream(history) {
const messages = history.map(e => ({role: e.role, content: e.msg}))
return await axios.post(ChatGPT.base + "/v1/chat/completions", JSON.stringify({messages, model: this.id, stream: true}), {
headers: {
Authorization: 'Bearer ' + this.apiKey, "Content-Type": "application/json", Accept: "application/json",
},
}).then(res => res?.body?.getReader());
}
2023-05-15 17:05:36 +08:00
async getAccount() {
const {headers} = this
const usages = await axios.get(ChatGPT.base + "/v1/dashboard/billing/subscription", {headers}).then(res => res.json());
const endDate = usages.access_until
if (endDate) {
const startDate = new Date(endDate - 90 * 24 * 60 * 60);
const formattedDate = time => dayjs(time).format("YYYY-MM-DD")
return await axios.get(`${ChatGPT.base}/v1/dashboard/billing/usage?start_date=${formattedDate(startDate * 1000)}&end_date=${formattedDate(endDate * 1000)}`, {headers}).then(res => res.json()).then(res => {
2023-05-15 17:05:36 +08:00
usages.total_usage = res.total_usage
const names = usages.account_name.split(" ")
return {
...usages, username: names.at(-1) + names[0], usage: (usages.total_usage / 100)?.toFixed(2), total: usages.hard_limit_usd?.toFixed(2)
2023-05-15 17:05:36 +08:00
}
});
} else return Promise.reject("没有权限或者网络异常,请重新尝试!")
}
2023-05-17 18:16:53 +08:00
streamOutput(reader, chat) {
return reader.read().then(({done, value}) => {
if (done) {
return;
}
if (!chat.reminder) {
chat.reminder = ""
}
let decode = new TextDecoder().decode(value)
decode = chat.reminder + decode
let decodedArray = decode.split("data: ");
let longstr = "";
decodedArray.forEach(decoded => {
decoded = decoded.trim();
try {
if (longstr != "") {
decoded = longstr + decoded;
longstr = "";
}
} catch (e) {
longstr = decoded;
decoded = "";
}
if (!!decoded && decoded !== "[DONE]") {
const choices = JSON.parse(decoded).choices
if (choices?.length > 0) {
const response = choices[0].delta.content || "";
chat.msg += response
}
}
})
return this.streamOutput(reader, chat)
})
}
2023-05-12 15:53:39 +08:00
}
2023-05-15 23:45:11 +08:00
/**
* ChatGLM 基于chatGLM-130B的api
*/
2023-05-12 15:53:39 +08:00
export class ChatGLM extends BaseModel {
2023-05-15 23:45:11 +08:00
static base = "https://maas.aminer.cn/api/paas"
2023-05-17 18:16:53 +08:00
"/model/v1/open/engines/chatGLM/chatGLM"
static avatar = "https://cdn.cunwuyun.cn/chat/chatglm.svg"
static name = "ChatGLM"
static id = "chatglm-130b"
static desc = "ChatGLM-130B所基于的模型"
2023-05-17 18:16:53 +08:00
static publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMZXxmDh2Rs1lh3Ymud1eVBjds/9SfjczHJFpNe9+0FsUffILVMTBcTqmdPZxjC6M1Ad2EHaHMWXZuc0fIc4Lh8CAwEAAQ=="
2023-05-12 18:12:21 +08:00
constructor(params) {
const {avatar, name, desc, id} = ChatGLM
2023-05-17 18:16:53 +08:00
super({avatar, name, desc, id, taskId: nanoid(), ...params})
2023-05-16 18:04:04 +08:00
this.getToken().then(e => this.setApiKey(e))
2023-05-15 23:45:11 +08:00
}
2023-05-17 18:16:53 +08:00
async getToken() {
if (this.apiKey) return await this.apiKey
const encrypted = ChatGLM.encrypt(ChatGLM.publicKey)
2023-05-17 18:16:53 +08:00
return await axios.post(ChatGLM.base + "/passApiToken/createApiToken", JSON.stringify({apiKey: "4e3ceff669c143dfa09e763663aa72cd", encrypted}), {
2023-05-15 23:45:11 +08:00
headers: this.headers,
}).then(res => res.json()).then(data => data?.data);
2023-05-12 15:53:39 +08:00
}
2023-05-12 18:12:21 +08:00
async chat(messages) {
const history = messages.map(e => e.msg)
history.pop()
const prompt = history.pop()
return await axios.post(ChatGLM.base + "/model/v1/open/engines/chatGLM/chatGLM", JSON.stringify({
history, prompt, temperature: 1, top_p: 0.6, requestTaskNo: this.taskId
}), {headers: this.headers}).then(res => res.json()).then(data => {
if (data?.data.taskStatus == 'PROCESSING') {
return this.getChatResult(data.data.taskOrderNo)
} else {
return data?.data?.outputText || "key无效或网络波动,请重新尝试"
}
});
}
async getChatResult(taskOrderNo) {
return await axios.get(ChatGLM.base + `/request-task/query-request-task-result/${taskOrderNo}`, {headers: this.headers}).then(res => res.json()).then(data => {
if (data?.data.taskStatus == 'PROCESSING') {
return this.getChatResult(data.data.taskOrderNo)
} else {
return data?.data?.outputText || "key无效或网络波动,请重新尝试"
}
})
2023-05-12 18:12:21 +08:00
}
2023-05-17 18:16:53 +08:00
async chatStream(messages) {
const history = messages.map(e => e.msg)
history.pop()
const prompt = history.pop()
const url = ChatGLM.base + "/model/v1/open/engines/sse/chatGLM/chatGLM"
return await axios.post(url, JSON.stringify({
2023-06-01 17:12:10 +08:00
history, prompt, temperature: 0.2, requestTaskNo: this.taskId
2023-05-17 18:16:53 +08:00
}), {
headers: this.headers,
}).then(res => res?.body?.getReader());
}
static encrypt(publicKey, timestamp) {
timestamp = Date.now().toFixed(0)
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey)
return encryptor.encrypt(timestamp);
2023-05-17 18:16:53 +08:00
}
async getAccount() {
const usages = await axios.get("https://open.bigmodel.ai/api/paas/account/query-customer-account-report", {headers: this.headers}).then(res => res.json());
2023-05-17 18:16:53 +08:00
if (usages.code == 200) {
const {data} = usages
return {
...data, username: "Kubbo", usage: data.totalSpendAmount?.toFixed(4), total: data.rechargeAmount?.toFixed(4)
2023-05-17 18:16:53 +08:00
}
} else return Promise.reject("没有权限或者网络异常,请重新尝试!")
}
streamOutput(reader, chat) {
return reader.read().then(({done, value}) => {
if (done) {
return;
}
const decode = new TextDecoder().decode(value)
2023-06-01 17:12:10 +08:00
const dialogue = decode.split("event:").at(-1)
const msg = dialogue.split("\n").filter(e => e.startsWith("data:"))?.map(e => e.replace("data:", '')).join("\n")
if (msg?.length > 0) chat.msg = msg
2023-05-17 18:16:53 +08:00
return this.streamOutput(reader, chat)
})
}
2023-05-12 15:53:39 +08:00
}