perf: bill

This commit is contained in:
archer
2023-07-13 22:53:44 +08:00
parent 726de0396b
commit f3715731c4
67 changed files with 915 additions and 1254 deletions

View File

@@ -1,13 +1,8 @@
import { ChatItemType } from '@/types/chat';
import { modelToolMap } from '@/utils/plugin';
import type { ChatModelType } from '@/constants/model';
import { ChatRoleEnum, sseResponseEventEnum } from '@/constants/chat';
import { sseResponse } from '../tools';
import { ChatRoleEnum } from '@/constants/chat';
import { OpenAiChatEnum } from '@/constants/model';
import { chatResponse, openAiStreamResponse } from './openai';
import type { NextApiResponse } from 'next';
import { textAdaptGptResponse } from '@/utils/adapt';
import { parseStreamChunk } from '@/utils/adapt';
export type ChatCompletionType = {
apiKey: string;
@@ -36,11 +31,6 @@ export type StreamResponseReturnType = {
finishMessages: ChatItemType[];
};
export const modelServiceToolMap = {
chatCompletion: chatResponse,
streamResponse: openAiStreamResponse
};
/* delete invalid symbol */
const simplifyStr = (str = '') =>
str
@@ -54,7 +44,7 @@ export const ChatContextFilter = ({
prompts,
maxTokens
}: {
model: ChatModelType;
model: string;
prompts: ChatItemType[];
maxTokens: number;
}) => {
@@ -111,126 +101,3 @@ export const ChatContextFilter = ({
return [...systemPrompts, ...chats];
};
/* stream response */
export const resStreamResponse = async ({
model,
res,
chatResponse,
prompts
}: StreamResponseType & {
model: ChatModelType;
}) => {
// 创建响应流
res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('X-Accel-Buffering', 'no');
res.setHeader('Cache-Control', 'no-cache, no-transform');
const { responseContent, totalTokens, finishMessages } = await modelServiceToolMap.streamResponse(
{
chatResponse,
prompts,
res,
model
}
);
return { responseContent, totalTokens, finishMessages };
};
/* stream response */
export const V2_StreamResponse = async ({
model,
res,
chatResponse,
prompts
}: StreamResponseType & {
model: ChatModelType;
}) => {
let responseContent = '';
let error: any = null;
let truncateData = '';
const clientRes = async (data: string) => {
//部分代理会导致流式传输时的数据被截断不为json格式这里做一个兼容
const { content = '' } = (() => {
try {
if (truncateData) {
try {
//判断是否为json如果是的话直接跳过后续拼装操作注意极端情况下可能出现截断成3截以上情况也可以兼容
JSON.parse(data);
} catch (e) {
data = truncateData + data;
}
truncateData = '';
}
const json = JSON.parse(data);
const content: string = json?.choices?.[0].delta.content || '';
error = json.error;
responseContent += content;
return { content };
} catch (error) {
truncateData = data;
return {};
}
})();
if (res.closed || error) return;
if (data === '[DONE]') {
sseResponse({
res,
event: sseResponseEventEnum.answer,
data: textAdaptGptResponse({
text: null,
finish_reason: 'stop'
})
});
sseResponse({
res,
event: sseResponseEventEnum.answer,
data: '[DONE]'
});
} else {
sseResponse({
res,
event: sseResponseEventEnum.answer,
data: textAdaptGptResponse({
text: content
})
});
}
};
try {
for await (const chunk of chatResponse.data as any) {
if (res.closed) break;
const parse = parseStreamChunk(chunk);
parse.forEach((item) => clientRes(item.data));
}
} catch (error) {
console.log('pipe error', error);
}
if (error) {
console.log(error);
return Promise.reject(error);
}
// count tokens
const finishMessages = prompts.concat({
obj: ChatRoleEnum.AI,
value: responseContent
});
const totalTokens = modelToolMap.countTokens({
model,
messages: finishMessages
});
return {
responseContent,
totalTokens,
finishMessages
};
};