perf: code and inform

This commit is contained in:
archer
2023-07-04 21:24:32 +08:00
parent 8635de866f
commit 2a45fe520b
20 changed files with 97 additions and 163 deletions

View File

@@ -31,7 +31,7 @@ export const ChatModelMap = {
contextMaxToken: 4000,
systemMaxToken: 2400,
maxTemperature: 1.2,
price: 2.5
price: 1.5
},
[OpenAiChatEnum.GPT3516k]: {
chatModel: OpenAiChatEnum.GPT3516k,

View File

@@ -129,7 +129,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
// 发出请求
const { streamResponse, responseMessages, responseText, totalTokens } =
await modelServiceToolMap[model.chat.chatModel].chatCompletion({
await modelServiceToolMap.chatCompletion({
model: model.chat.chatModel,
apiKey,
temperature: +temperature,
messages: completePrompts,

View File

@@ -150,13 +150,15 @@ export async function appKbSearch({
}
];
const fixedSystemTokens = modelToolMap[model.chat.chatModel].countTokens({
const fixedSystemTokens = modelToolMap.countTokens({
model: model.chat.chatModel,
messages: [...userSystemPrompt, ...userLimitPrompt]
});
// filter part quote by maxToken
const sliceResult = modelToolMap[model.chat.chatModel]
const sliceResult = modelToolMap
.tokenSlice({
model: model.chat.chatModel,
maxToken: modelConstantsData.systemMaxToken - fixedSystemTokens,
messages: filterSearch.map((item, i) => ({
obj: ChatRoleEnum.System,

View File

@@ -78,7 +78,8 @@ export async function pushDataToKb({
if (mode === TrainingModeEnum.qa) {
// count token
const token = modelToolMap[OpenAiChatEnum.GPT3516k].countTokens({
const token = modelToolMap.countTokens({
model: OpenAiChatEnum.GPT3516k,
messages: [{ obj: 'System', value: item.q }]
});
if (token > modeMaxToken[TrainingModeEnum.qa]) {

View File

@@ -196,7 +196,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
// start model api. responseText and totalTokens: valid only if stream = false
const { streamResponse, responseMessages, responseText, totalTokens } =
await modelServiceToolMap[model.chat.chatModel].chatCompletion({
await modelServiceToolMap.chatCompletion({
model: model.chat.chatModel,
apiKey: userOpenAiKey || apiKey,
temperature: +temperature,
maxToken: model.chat.maxToken,

View File

@@ -9,6 +9,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT3516k]);
chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT35]);
chatModelList.push(ChatModelMap[OpenAiChatEnum.textada001]);
chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT4]);
jsonRes(res, {

View File

@@ -4,6 +4,7 @@ import { jsonRes } from '@/service/response';
import { connectToDatabase, Inform, User } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { InformTypeEnum } from '@/constants/user';
import { startSendInform } from '@/service/events/sendInform';
export type Props = {
type: `${InformTypeEnum}`;
@@ -37,25 +38,26 @@ export async function sendInform({ type, title, content, userId }: Props) {
try {
if (userId) {
// skip it if have same inform within 5 minutes
const inform = await Inform.findOne({
type,
title,
content,
userId,
read: false,
time: { $lte: new Date(Date.now() + 5 * 60 * 1000) }
global.sendInformQueue.push(async () => {
// skip it if have same inform within 5 minutes
const inform = await Inform.findOne({
type,
title,
content,
userId,
time: { $gte: new Date(Date.now() - 5 * 60 * 1000) }
});
if (inform) return;
await Inform.create({
type,
title,
content,
userId
});
});
if (inform) return;
await Inform.create({
type,
title,
content,
userId
});
startSendInform();
return;
}

View File

@@ -114,7 +114,7 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
| 计费项 | 价格: 元/ 1K tokens(包含上下文)|
| --- | --- |
| 知识库 - 索引 | 0.001 |
| chatgpt - 对话 | 0.025 |
| chatgpt - 对话 | 0.015 |
| chatgpt16K - 对话 | 0.025 |
| gpt4 - 对话 | 0.45 |
| 文件拆分 | 0.025 |`}

View File

@@ -63,8 +63,9 @@ export async function generateQA(): Promise<any> {
// 请求 chatgpt 获取回答
const response = await Promise.all(
[data.q].map((text) =>
modelServiceToolMap[OpenAiChatEnum.GPT3516k]
modelServiceToolMap
.chatCompletion({
model: OpenAiChatEnum.GPT3516k,
apiKey: systemAuthKey,
temperature: 0.8,
messages: [

View File

@@ -0,0 +1,16 @@
export const startSendInform = async () => {
if (global.sendInformQueue.length === 0 || global.sendInformQueueLen > 0) return;
global.sendInformQueueLen++;
try {
const fn = global.sendInformQueue[global.sendInformQueue.length - 1];
await fn();
global.sendInformQueue.pop();
global.sendInformQueueLen--;
startSendInform();
} catch (error) {
global.sendInformQueueLen--;
startSendInform();
}
};

View File

@@ -20,6 +20,8 @@ export async function connectToDatabase(): Promise<void> {
pgIvfflatProbe: 10,
sensitiveCheck: false
};
global.sendInformQueue = [];
global.sendInformQueueLen = 0;
// proxy obj
if (process.env.AXIOS_PROXY_HOST && process.env.AXIOS_PROXY_PORT) {
global.httpsAgent = tunnel.httpsOverHttp({

View File

@@ -181,33 +181,13 @@ export const getApiKey = async ({
return Promise.reject(ERROR_ENUM.unAuthorization);
}
const keyMap = {
[OpenAiChatEnum.GPT35]: {
userOpenAiKey: user.openaiKey || '',
systemAuthKey: getSystemOpenAiKey()
},
[OpenAiChatEnum.GPT3516k]: {
userOpenAiKey: user.openaiKey || '',
systemAuthKey: getSystemOpenAiKey()
},
[OpenAiChatEnum.GPT4]: {
userOpenAiKey: user.openaiKey || '',
systemAuthKey: getSystemOpenAiKey()
},
[OpenAiChatEnum.GPT432k]: {
userOpenAiKey: user.openaiKey || '',
systemAuthKey: getSystemOpenAiKey()
}
};
if (!keyMap[model]) {
return Promise.reject('App model is exists');
}
const userOpenAiKey = user.openaiKey || '';
const systemAuthKey = getSystemOpenAiKey();
// 有自己的key
if (!mustPay && keyMap[model].userOpenAiKey) {
if (!mustPay && userOpenAiKey) {
return {
userOpenAiKey: keyMap[model].userOpenAiKey,
userOpenAiKey,
systemAuthKey: ''
};
}
@@ -219,7 +199,7 @@ export const getApiKey = async ({
return {
userOpenAiKey: '',
systemAuthKey: keyMap[model].systemAuthKey
systemAuthKey
};
};

View File

@@ -27,6 +27,7 @@ export type StreamResponseType = {
chatResponse: any;
prompts: ChatItemType[];
res: NextApiResponse;
model: `${OpenAiChatEnum}`;
[key: string]: any;
};
export type StreamResponseReturnType = {
@@ -35,49 +36,9 @@ export type StreamResponseReturnType = {
finishMessages: ChatItemType[];
};
export const modelServiceToolMap: Record<
ChatModelType,
{
chatCompletion: (data: ChatCompletionType) => Promise<ChatCompletionResponseType>;
streamResponse: (data: StreamResponseType) => Promise<StreamResponseReturnType>;
}
> = {
[OpenAiChatEnum.GPT35]: {
chatCompletion: (data: ChatCompletionType) =>
chatResponse({ model: OpenAiChatEnum.GPT35, ...data }),
streamResponse: (data: StreamResponseType) =>
openAiStreamResponse({
model: OpenAiChatEnum.GPT35,
...data
})
},
[OpenAiChatEnum.GPT3516k]: {
chatCompletion: (data: ChatCompletionType) =>
chatResponse({ model: OpenAiChatEnum.GPT3516k, ...data }),
streamResponse: (data: StreamResponseType) =>
openAiStreamResponse({
model: OpenAiChatEnum.GPT3516k,
...data
})
},
[OpenAiChatEnum.GPT4]: {
chatCompletion: (data: ChatCompletionType) =>
chatResponse({ model: OpenAiChatEnum.GPT4, ...data }),
streamResponse: (data: StreamResponseType) =>
openAiStreamResponse({
model: OpenAiChatEnum.GPT4,
...data
})
},
[OpenAiChatEnum.GPT432k]: {
chatCompletion: (data: ChatCompletionType) =>
chatResponse({ model: OpenAiChatEnum.GPT432k, ...data }),
streamResponse: (data: StreamResponseType) =>
openAiStreamResponse({
model: OpenAiChatEnum.GPT432k,
...data
})
}
export const modelServiceToolMap = {
chatCompletion: chatResponse,
streamResponse: openAiStreamResponse
};
/* delete invalid symbol */
@@ -124,7 +85,8 @@ export const ChatContextFilter = ({
}
// 去掉 system 的 token
maxTokens -= modelToolMap[model].countTokens({
maxTokens -= modelToolMap.countTokens({
model,
messages: systemPrompts
});
@@ -135,7 +97,8 @@ export const ChatContextFilter = ({
for (let i = chatPrompts.length - 1; i >= 0; i--) {
chats.unshift(chatPrompts[i]);
const tokens = modelToolMap[model].countTokens({
const tokens = modelToolMap.countTokens({
model,
messages: chats
});
@@ -164,13 +127,14 @@ export const resStreamResponse = async ({
res.setHeader('X-Accel-Buffering', 'no');
res.setHeader('Cache-Control', 'no-cache, no-transform');
const { responseContent, totalTokens, finishMessages } = await modelServiceToolMap[
model
].streamResponse({
chatResponse,
prompts,
res
});
const { responseContent, totalTokens, finishMessages } = await modelServiceToolMap.streamResponse(
{
chatResponse,
prompts,
res,
model
}
);
return { responseContent, totalTokens, finishMessages };
};
@@ -259,7 +223,8 @@ export const V2_StreamResponse = async ({
value: responseContent
});
const totalTokens = modelToolMap[model].countTokens({
const totalTokens = modelToolMap.countTokens({
model,
messages: finishMessages
});

View File

@@ -35,7 +35,8 @@ export const chatResponse = async ({
const adaptMessages = adaptChatItem_openAI({ messages: filterMessages, reserveId: false });
const chatAPI = getOpenAIApi(apiKey);
const promptsToken = modelToolMap[model].countTokens({
const promptsToken = modelToolMap.countTokens({
model,
messages: filterMessages
});
@@ -116,7 +117,8 @@ export const openAiStreamResponse = async ({
value: responseContent
});
const totalTokens = modelToolMap[model].countTokens({
const totalTokens = modelToolMap.countTokens({
model,
messages: finishMessages
});

View File

@@ -21,7 +21,9 @@ declare global {
var QRCode: any;
var qaQueueLen: number;
var vectorQueueLen: number;
var OpenAiEncMap: Record<string, Tiktoken>;
var OpenAiEncMap: Tiktoken;
var sendInformQueue: (() => Promise<void>)[];
var sendInformQueueLen: number;
var systemEnv: {
vectorMaxProcess: number;
qaMaxProcess: number;

View File

@@ -152,7 +152,7 @@ export const splitText_token = ({ text, maxLen }: { text: string; maxLen: number
const slideLen = Math.floor(maxLen * 0.3);
try {
const enc = getOpenAiEncMap()[OpenAiChatEnum.GPT35];
const enc = getOpenAiEncMap();
// filter empty text. encode sentence
const encodeText = enc.encode(text);

View File

@@ -4,32 +4,8 @@ import type { ChatItemType } from '@/types/chat';
import { countOpenAIToken, openAiSliceTextByToken } from './openai';
import { gpt_chatItemTokenSlice } from '@/pages/api/openapi/text/gptMessagesSlice';
export const modelToolMap: Record<
ChatModelType,
{
countTokens: (data: { messages: ChatItemType[] }) => number;
sliceText: (data: { text: string; length: number }) => string;
tokenSlice: (data: { messages: ChatItemType[]; maxToken: number }) => ChatItemType[];
}
> = {
[OpenAiChatEnum.GPT35]: {
countTokens: ({ messages }) => countOpenAIToken({ model: OpenAiChatEnum.GPT35, messages }),
sliceText: (data) => openAiSliceTextByToken({ model: OpenAiChatEnum.GPT35, ...data }),
tokenSlice: (data) => gpt_chatItemTokenSlice({ model: OpenAiChatEnum.GPT35, ...data })
},
[OpenAiChatEnum.GPT3516k]: {
countTokens: ({ messages }) => countOpenAIToken({ model: OpenAiChatEnum.GPT3516k, messages }),
sliceText: (data) => openAiSliceTextByToken({ model: OpenAiChatEnum.GPT3516k, ...data }),
tokenSlice: (data) => gpt_chatItemTokenSlice({ model: OpenAiChatEnum.GPT3516k, ...data })
},
[OpenAiChatEnum.GPT4]: {
countTokens: ({ messages }) => countOpenAIToken({ model: OpenAiChatEnum.GPT4, messages }),
sliceText: (data) => openAiSliceTextByToken({ model: OpenAiChatEnum.GPT4, ...data }),
tokenSlice: (data) => gpt_chatItemTokenSlice({ model: OpenAiChatEnum.GPT4, ...data })
},
[OpenAiChatEnum.GPT432k]: {
countTokens: ({ messages }) => countOpenAIToken({ model: OpenAiChatEnum.GPT432k, messages }),
sliceText: (data) => openAiSliceTextByToken({ model: OpenAiChatEnum.GPT432k, ...data }),
tokenSlice: (data) => gpt_chatItemTokenSlice({ model: OpenAiChatEnum.GPT432k, ...data })
}
export const modelToolMap = {
countTokens: countOpenAIToken,
sliceText: openAiSliceTextByToken,
tokenSlice: gpt_chatItemTokenSlice
};

View File

@@ -4,7 +4,6 @@ import { ChatRoleEnum } from '@/constants/chat';
import { ChatCompletionRequestMessageRoleEnum } from 'openai';
import { OpenAiChatEnum } from '@/constants/model';
import axios from 'axios';
import dayjs from 'dayjs';
import type { MessageItemType } from '@/pages/api/openapi/v1/chat/completions';
export const getOpenAiEncMap = () => {
@@ -14,28 +13,11 @@ export const getOpenAiEncMap = () => {
if (typeof global !== 'undefined' && global.OpenAiEncMap) {
return global.OpenAiEncMap;
}
const enc = {
[OpenAiChatEnum.GPT35]: encoding_for_model('gpt-3.5-turbo', {
'<|im_start|>': 100264,
'<|im_end|>': 100265,
'<|im_sep|>': 100266
}),
[OpenAiChatEnum.GPT3516k]: encoding_for_model('gpt-3.5-turbo', {
'<|im_start|>': 100264,
'<|im_end|>': 100265,
'<|im_sep|>': 100266
}),
[OpenAiChatEnum.GPT4]: encoding_for_model('gpt-4', {
'<|im_start|>': 100264,
'<|im_end|>': 100265,
'<|im_sep|>': 100266
}),
[OpenAiChatEnum.GPT432k]: encoding_for_model('gpt-4-32k', {
'<|im_start|>': 100264,
'<|im_end|>': 100265,
'<|im_sep|>': 100266
})
};
const enc = encoding_for_model('gpt-3.5-turbo', {
'<|im_start|>': 100264,
'<|im_end|>': 100265,
'<|im_sep|>': 100266
});
if (typeof window !== 'undefined') {
window.OpenAiEncMap = enc;
@@ -78,7 +60,7 @@ export function countOpenAIToken({
const adaptMessages = adaptChatItem_openAI({ messages, reserveId: true });
const token = adaptMessages.reduce((sum, item) => {
const text = `${item.role}\n${item.content}`;
const enc = getOpenAiEncMap()[model];
const enc = getOpenAiEncMap();
const encodeText = enc.encode(text);
const tokens = encodeText.length + diffVal;
return sum + tokens;
@@ -96,7 +78,7 @@ export const openAiSliceTextByToken = ({
text: string;
length: number;
}) => {
const enc = getOpenAiEncMap()[model];
const enc = getOpenAiEncMap();
const encodeText = enc.encode(text);
const decoder = new TextDecoder();
return decoder.decode(enc.decode(encodeText.slice(0, length)));