perf: completion chatId

This commit is contained in:
archer
2023-07-23 20:07:35 +08:00
parent b7d18e38d1
commit 67e10d6f2c
35 changed files with 447 additions and 385 deletions

View File

@@ -16,7 +16,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// 凭证校验
const { userId } = await authUser({ req, authToken: true });
const chatRecord = await Chat.findById(chatId);
const chatRecord = await Chat.findOne({ chatId });
if (!chatRecord) {
throw new Error('找不到对话');

View File

@@ -17,14 +17,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
userId,
...(appId && { appId })
},
'_id title top customTitle appId updateTime'
'chatId title top customTitle appId updateTime'
)
.sort({ top: -1, updateTime: -1 })
.limit(20);
jsonRes<ChatHistoryItemType[]>(res, {
data: data.map((item) => ({
_id: item._id,
chatId: item.chatId,
updateTime: item.updateTime,
appId: item.appId,
customTitle: item.customTitle,

View File

@@ -3,7 +3,6 @@ import { jsonRes } from '@/service/response';
import { connectToDatabase, Chat } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { Types } from 'mongoose';
import { rawSearchKey } from '@/constants/chat';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -36,13 +35,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
},
{
$project: {
[rawSearchKey]: `$content.${rawSearchKey}`
// [rawSearchKey]: `$content.${rawSearchKey}`
}
}
]);
jsonRes(res, {
data: history[0]?.[rawSearchKey] || []
// data: history[0]?.[rawSearchKey] || []
});
} catch (err) {
jsonRes(res, {

View File

@@ -20,7 +20,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
await Chat.findOneAndUpdate(
{
_id: chatId,
chatId,
userId
},
{

View File

@@ -27,7 +27,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
await Chat.updateOne(
{
_id: new Types.ObjectId(chatId),
chatId,
userId: new Types.ObjectId(userId),
'content._id': new Types.ObjectId(contentId)
},

View File

@@ -6,8 +6,7 @@ import { authUser } from '@/service/utils/auth';
import { ChatItemType } from '@/types/chat';
import { authApp } from '@/service/utils/auth';
import mongoose from 'mongoose';
import type { AppSchema, ChatSchema } from '@/types/mongoSchema';
import { quoteLenKey, rawSearchKey } from '@/constants/chat';
import type { ChatSchema } from '@/types/mongoSchema';
import { getSpecialModule } from '@/components/ChatBox';
/* 初始化我的聊天框,需要身份验证 */
@@ -20,72 +19,62 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
chatId: '' | string;
};
if (!appId) {
return jsonRes(res, {
code: 501,
message: "You don't have an app yet"
});
}
await connectToDatabase();
// 没有 appId 时直接获取用户的第一个id
const app = await (async () => {
if (!appId) {
const myModel = await App.findOne({ userId });
if (!myModel) {
const { _id } = await App.create({
name: '应用1',
userId
});
return (await App.findById(_id)) as AppSchema;
} else {
return myModel;
}
} else {
// 校验使用权限
const authRes = await authApp({
appId,
userId,
authUser: false,
authOwner: false
});
return authRes.app;
}
})();
appId = appId || app._id;
// 校验使用权限
const app = (
await authApp({
appId,
userId,
authUser: false,
authOwner: false
})
).app;
// 历史记录
const { chat, history = [] }: { chat?: ChatSchema; history?: ChatItemType[] } =
await (async () => {
if (chatId) {
// auth chatId
const chat = await Chat.findOne({
_id: chatId,
userId
});
const [chat, history] = await Promise.all([
Chat.findOne({
chatId,
userId
}),
Chat.aggregate([
{
$match: {
chatId,
userId: new mongoose.Types.ObjectId(userId)
}
},
{
$project: {
content: {
$slice: ['$content', -50] // 返回 content 数组的最后50个元素
}
}
},
{ $unwind: '$content' },
{
$project: {
_id: '$content._id',
obj: '$content.obj',
value: '$content.value'
}
}
])
]);
if (!chat) {
throw new Error('聊天框不存在');
}
// 获取 chat.content 数据
const history = await Chat.aggregate([
{
$match: {
_id: new mongoose.Types.ObjectId(chatId),
userId: new mongoose.Types.ObjectId(userId)
}
},
{
$project: {
content: {
$slice: ['$content', -50] // 返回 content 数组的最后50个元素
}
}
},
{ $unwind: '$content' },
{
$project: {
_id: '$content._id',
obj: '$content.obj',
value: '$content.value',
[quoteLenKey]: { $size: { $ifNull: [`$content.${rawSearchKey}`, []] } }
}
}
]);
return { history, chat };
}
return {};

View File

@@ -6,13 +6,13 @@ import { authUser } from '@/service/utils/auth';
/* 获取历史记录 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { id } = req.query;
const { chatId } = req.query;
const { userId } = await authUser({ req, authToken: true });
await connectToDatabase();
await Chat.findOneAndRemove({
_id: id,
chatId,
userId
});

View File

@@ -1,104 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { ChatItemType } from '@/types/chat';
import { connectToDatabase, Chat, App } from '@/service/mongo';
import { authApp } from '@/service/utils/auth';
import { authUser } from '@/service/utils/auth';
import { Types } from 'mongoose';
type Props = {
chatId?: string;
appId: string;
variables?: Record<string, any>;
prompts: [ChatItemType, ChatItemType];
};
/* 聊天内容存存储 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { chatId, appId, prompts } = req.body as Props;
if (!prompts) {
throw new Error('缺少参数');
}
const { userId } = await authUser({ req, authToken: true });
const response = await saveChat({
chatId,
appId,
prompts,
userId
});
jsonRes(res, {
data: response
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}
export async function saveChat({
newChatId,
chatId,
appId,
prompts,
variables,
userId
}: Props & { newChatId?: Types.ObjectId; userId: string }): Promise<{ newChatId: string }> {
await connectToDatabase();
const { app } = await authApp({ appId, userId, authOwner: false });
if (String(app.userId) === userId) {
await App.findByIdAndUpdate(appId, {
updateTime: new Date()
});
}
const [response] = await Promise.all([
...(chatId
? [
Chat.findByIdAndUpdate(chatId, {
$push: {
content: {
$each: prompts
}
},
variables,
title: prompts[0].value.slice(0, 20),
updateTime: new Date()
}).then(() => ({
newChatId: ''
}))
]
: [
Chat.create({
_id: newChatId,
userId,
appId,
variables,
content: prompts,
title: prompts[0].value.slice(0, 20)
}).then((res) => ({
newChatId: String(res._id)
}))
]),
// update app
...(String(app.userId) === userId
? [
App.findByIdAndUpdate(appId, {
updateTime: new Date()
})
]
: [])
]);
return {
// @ts-ignore
newChatId: response?.newChatId || ''
};
}

View File

@@ -9,7 +9,7 @@ const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
/* create a shareChat */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { appId, name, maxContext } = req.body as ShareChatEditType & {
const { appId, name } = req.body as ShareChatEditType & {
appId: string;
};
@@ -27,8 +27,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
shareId,
userId,
appId,
name,
maxContext
name
});
jsonRes(res, {

View File

@@ -3,10 +3,7 @@ import { jsonRes } from '@/service/response';
import { connectToDatabase, ShareChat, User } from '@/service/mongo';
import type { InitShareChatResponse } from '@/api/response/chat';
import { authApp } from '@/service/utils/auth';
import { hashPassword } from '@/service/utils/tools';
import { HUMAN_ICON } from '@/constants/chat';
import { FlowModuleTypeEnum } from '@/constants/flow';
import { SystemInputEnum } from '@/constants/app';
import { getSpecialModule } from '@/components/ChatBox';
/* 初始化我的聊天框,需要身份验证 */
@@ -33,21 +30,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}
// 校验使用权限
const { app } = await authApp({
appId: shareChat.appId,
userId: String(shareChat.userId),
authOwner: false
});
const user = await User.findById(shareChat.userId, 'avatar');
const [{ app }, user] = await Promise.all([
authApp({
appId: shareChat.appId,
userId: String(shareChat.userId),
authOwner: false
}),
User.findById(shareChat.userId, 'avatar')
]);
jsonRes<InitShareChatResponse>(res, {
data: {
userAvatar: user?.avatar || HUMAN_ICON,
maxContext:
app.modules
?.find((item) => item.flowType === FlowModuleTypeEnum.historyNode)
?.inputs?.find((item) => item.key === 'maxContext')?.value || 0,
app: {
...getSpecialModule(app.modules),
name: app.name,

View File

@@ -28,7 +28,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
shareId: item.shareId,
name: item.name,
total: item.total,
maxContext: item.maxContext,
lastTime: item.lastTime
}))
});