perf: 生成对话框时机

This commit is contained in:
archer
2023-04-23 14:07:17 +08:00
parent 9682c82713
commit c2c73ed23c
25 changed files with 299 additions and 327 deletions

View File

@@ -1,11 +1,10 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { connectToDatabase } from '@/service/mongo';
import { getOpenAIApi, authChat } from '@/service/utils/chat';
import { getOpenAIApi, authChat } from '@/service/utils/auth';
import { httpsAgent, openaiChatFilter } from '@/service/utils/tools';
import { ChatCompletionRequestMessage, ChatCompletionRequestMessageRoleEnum } from 'openai';
import { ChatItemType } from '@/types/chat';
import { jsonRes } from '@/service/response';
import type { ModelSchema } from '@/types/mongoSchema';
import { PassThrough } from 'stream';
import { modelList } from '@/constants/model';
import { pushChatBill } from '@/service/events/pushBill';
@@ -28,29 +27,33 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
});
try {
const { chatId, prompt } = req.body as {
const { chatId, prompt, modelId } = req.body as {
prompt: ChatItemType;
chatId: string;
modelId: string;
chatId: '' | string;
};
const { authorization } = req.headers;
if (!chatId || !prompt) {
if (!modelId || !prompt) {
throw new Error('缺少参数');
}
await connectToDatabase();
let startTime = Date.now();
const { chat, userApiKey, systemKey, userId } = await authChat(chatId, authorization);
const { model, content, userApiKey, systemKey, userId } = await authChat({
modelId,
chatId,
authorization
});
const model: ModelSchema = chat.modelId;
const modelConstantsData = modelList.find((item) => item.model === model.service.modelName);
if (!modelConstantsData) {
throw new Error('模型加载异常');
}
// 读取对话内容
const prompts = [...chat.content, prompt];
const prompts = [...content, prompt];
// 如果有系统提示词,自动插入
if (model.systemPrompt) {

View File

@@ -1,54 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, Model, Chat } from '@/service/mongo';
import { authToken } from '@/service/utils/tools';
import type { ModelSchema } from '@/types/mongoSchema';
/* 获取我的模型 */
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const { modelId } = req.query as {
modelId: string;
};
const { authorization } = req.headers;
if (!authorization) {
throw new Error('无权生成对话');
}
if (!modelId) {
throw new Error('缺少参数');
}
// 凭证校验
const userId = await authToken(authorization);
await connectToDatabase();
// 校验是否为用户的模型
const model = await Model.findOne<ModelSchema>({
_id: modelId,
userId
});
if (!model) {
throw new Error('无权使用该模型');
}
// 创建 chat 数据
const response = await Chat.create({
userId,
modelId,
content: []
});
jsonRes(res, {
data: response._id // 即聊天框的 ID
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -1,9 +1,10 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, Chat } from '@/service/mongo';
import type { ChatPopulate } from '@/types/mongoSchema';
import { connectToDatabase, Chat, Model } from '@/service/mongo';
import type { InitChatResponse } from '@/api/response/chat';
import { authToken } from '@/service/utils/tools';
import { ChatItemType } from '@/types/chat';
import { authModel } from '@/service/utils/auth';
/* 初始化我的聊天框,需要身份验证 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
@@ -11,43 +12,46 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const { authorization } = req.headers;
const userId = await authToken(authorization);
const { chatId } = req.query as { chatId: string };
const { modelId, chatId } = req.query as { modelId: string; chatId: '' | string };
if (!chatId) {
if (!modelId) {
throw new Error('缺少参数');
}
await connectToDatabase();
// 获取 chat 数据
const chat = await Chat.findOne<ChatPopulate>({
_id: chatId,
userId
}).populate({
path: 'modelId',
options: {
strictPopulate: false
}
});
// 获取 model 数据
const { model } = await authModel(modelId, userId);
if (!chat) {
throw new Error('聊天框不存在');
// 历史记录
let history: ChatItemType[] = [];
if (chatId) {
// 获取 chat 数据
const chat = await Chat.findOne({
_id: chatId,
userId,
modelId
});
if (!chat) {
throw new Error('聊天框不存在');
}
// filter 被 deleted 的内容
history = chat.content.filter((item) => item.deleted !== true);
}
// filter 掉被 deleted 的内容
chat.content = chat.content.filter((item) => item.deleted !== true);
const model = chat.modelId;
jsonRes<InitChatResponse>(res, {
data: {
chatId: chat._id,
modelId: model._id,
chatId: chatId || '',
modelId: modelId,
name: model.name,
avatar: model.avatar,
intro: model.intro,
modelName: model.service.modelName,
chatModel: model.service.chatModel,
history: chat.content
history
}
});
} catch (err) {

View File

@@ -2,34 +2,53 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { ChatItemType } from '@/types/chat';
import { connectToDatabase, Chat } from '@/service/mongo';
import { authModel } from '@/service/utils/auth';
import { authToken } from '@/service/utils/tools';
/* 聊天内容存存储 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { chatId, prompts } = req.body as {
chatId: string;
const { chatId, modelId, prompts } = req.body as {
chatId: '' | string;
modelId: string;
prompts: ChatItemType[];
};
if (!chatId || !prompts) {
if (!prompts) {
throw new Error('缺少参数');
}
const userId = await authToken(req.headers.authorization);
await connectToDatabase();
// 存入库
await Chat.findByIdAndUpdate(chatId, {
$push: {
content: {
$each: prompts.map((item) => ({
obj: item.obj,
value: item.value
}))
}
},
updateTime: new Date()
});
const content = prompts.map((item) => ({
obj: item.obj,
value: item.value
}));
// 没有 chatId, 创建一个对话
if (!chatId) {
await authModel(modelId, userId);
const { _id } = await Chat.create({
userId,
modelId,
content
});
return jsonRes(res, {
data: _id
});
} else {
// 已经有记录,追加入库
await Chat.findByIdAndUpdate(chatId, {
$push: {
content: {
$each: content
}
},
updateTime: new Date()
});
}
jsonRes(res);
} catch (err) {
jsonRes(res, {

View File

@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { connectToDatabase } from '@/service/mongo';
import { authChat } from '@/service/utils/chat';
import { authChat } from '@/service/utils/auth';
import { httpsAgent, systemPromptFilter, openaiChatFilter } from '@/service/utils/tools';
import { ChatCompletionRequestMessage, ChatCompletionRequestMessageRoleEnum } from 'openai';
import { ChatItemType } from '@/types/chat';
@@ -35,29 +35,33 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
});
try {
const { chatId, prompt } = req.body as {
const { modelId, chatId, prompt } = req.body as {
modelId: string;
chatId: '' | string;
prompt: ChatItemType;
chatId: string;
};
const { authorization } = req.headers;
if (!chatId || !prompt) {
if (!modelId || !prompt) {
throw new Error('缺少参数');
}
await connectToDatabase();
let startTime = Date.now();
const { chat, userApiKey, systemKey, userId } = await authChat(chatId, authorization);
const { model, content, userApiKey, systemKey, userId } = await authChat({
modelId,
chatId,
authorization
});
const model: ModelSchema = chat.modelId;
const modelConstantsData = modelList.find((item) => item.model === model.service.modelName);
if (!modelConstantsData) {
throw new Error('模型加载异常');
}
// 读取对话内容
const prompts = [...chat.content, prompt];
const prompts = [...content, prompt];
// 获取提示词的向量
const { vector: promptVector, chatAPI } = await openaiCreateEmbedding({

View File

@@ -47,7 +47,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
userId,
status: ModelStatusEnum.running,
service: {
company: modelItem.serviceCompany,
trainId: '',
chatModel: ChatModelNameMap[modelItem.model], // 聊天时用的模型
modelName: modelItem.model // 最底层的模型,不会变,用于计费等核心操作

View File

@@ -36,14 +36,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const textList: string[] = [];
let splitText = '';
/* 取 3k ~ 4K tokens 内容 */
/* 取 2.5k ~ 3.5K tokens 内容 */
chunks.forEach((chunk) => {
const tokens = encode(splitText + chunk).length;
if (tokens >= 4000) {
// 超过 4000不要这块内容
if (tokens >= 3500) {
// 超过 3500不要这块内容
splitText && textList.push(splitText);
splitText = chunk;
} else if (tokens >= 3000) {
} else if (tokens >= 2500) {
// 超过 3000取内容
splitText && textList.push(splitText + chunk);
splitText = '';

View File

@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { connectToDatabase, Model } from '@/service/mongo';
import { getOpenAIApi } from '@/service/utils/chat';
import { getOpenAIApi } from '@/service/utils/auth';
import { httpsAgent, openaiChatFilter, authOpenApiKey } from '@/service/utils/tools';
import { ChatCompletionRequestMessage, ChatCompletionRequestMessageRoleEnum } from 'openai';
import { ChatItemType } from '@/types/chat';

View File

@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { connectToDatabase, Model } from '@/service/mongo';
import { getOpenAIApi } from '@/service/utils/chat';
import { getOpenAIApi } from '@/service/utils/auth';
import { authOpenApiKey } from '@/service/utils/tools';
import { httpsAgent, openaiChatFilter, systemPromptFilter } from '@/service/utils/tools';
import { ChatCompletionRequestMessage, ChatCompletionRequestMessageRoleEnum } from 'openai';