feat: app detail

This commit is contained in:
archer
2023-07-13 15:07:13 +08:00
parent 6c72c20317
commit b4d46ff34d
47 changed files with 1088 additions and 1091 deletions

View File

@@ -0,0 +1,53 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, Bill } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import type { ChatHistoryItemType } from '@/types/chat';
import { Types } from 'mongoose';
/* get one app chat history content number. */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { appId, start, end } = req.body as { appId: string; start: Date; end: Date };
const { userId } = await authUser({ req, authToken: true });
await connectToDatabase();
const result = await Bill.aggregate([
{
$match: {
appId: new Types.ObjectId(appId),
userId: new Types.ObjectId(userId),
time: { $gte: new Date(start) }
}
},
{
$group: {
_id: {
year: { $year: '$time' },
month: { $month: '$time' },
day: { $dayOfMonth: '$time' }
},
tokenLen: { $sum: '$tokenLen' } // 对tokenLen的值求和
}
},
{
$project: {
_id: 0,
date: { $dateFromParts: { year: '$_id.year', month: '$_id.month', day: '$_id.day' } },
tokenLen: 1
}
},
{ $sort: { date: 1 } }
]);
jsonRes(res, {
data: result
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -18,7 +18,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
await connectToDatabase();
// 验证是否是该用户的 model
// 验证是否是该用户的 app
await authApp({
appId,
userId

View File

@@ -6,22 +6,22 @@ import { Types } from 'mongoose';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { chatId, historyId } = req.query as {
chatId: string;
const { historyId, contentId } = req.query as {
historyId: string;
contentId: string;
};
await connectToDatabase();
const { userId } = await authUser({ req, authToken: true });
if (!chatId || !historyId) {
if (!historyId || !contentId) {
throw new Error('params is error');
}
const history = await Chat.aggregate([
{
$match: {
_id: new Types.ObjectId(chatId),
_id: new Types.ObjectId(historyId),
userId: new Types.ObjectId(userId)
}
},
@@ -30,7 +30,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
},
{
$match: {
'content._id': new Types.ObjectId(historyId)
'content._id': new Types.ObjectId(contentId)
}
},
{

View File

@@ -7,13 +7,13 @@ import { Types } from 'mongoose';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
let {
chatId,
historyId,
contentId,
quoteId,
sourceText = ''
} = req.query as {
chatId: string;
historyId: string;
contentId: string;
quoteId: string;
sourceText: string;
};
@@ -21,15 +21,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const { userId } = await authUser({ req, authToken: true });
if (!chatId || !historyId || !quoteId) {
if (!contentId || !historyId || !quoteId) {
throw new Error('params is error');
}
await Chat.updateOne(
{
_id: new Types.ObjectId(chatId),
_id: new Types.ObjectId(historyId),
userId: new Types.ObjectId(userId),
'content._id': new Types.ObjectId(historyId)
'content._id': new Types.ObjectId(contentId)
},
{
$set: {

View File

@@ -53,7 +53,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const { chat, history = [] }: { chat?: ChatSchema; history?: ChatItemType[] } =
await (async () => {
if (historyId) {
// auth chatId
// auth historyId
const chat = await Chat.findOne({
_id: historyId,
userId

View File

@@ -53,14 +53,14 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
throw new Error('params is error');
}
// auth model
// auth app
const { app } = await authApp({
appId,
userId
});
const result = await appKbSearch({
model: app,
app,
userId,
fixedQuote: [],
prompt: prompts[prompts.length - 1],
@@ -81,21 +81,21 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
});
export async function appKbSearch({
model,
app,
userId,
fixedQuote = [],
prompt,
similarity = 0.8,
limit = 5
}: {
model: AppSchema;
app: AppSchema;
userId: string;
fixedQuote?: QuoteItemType[];
prompt: ChatItemType;
similarity: number;
limit: number;
}): Promise<Response> {
const modelConstantsData = ChatModelMap[model.chat.chatModel];
const modelConstantsData = ChatModelMap[app.chat.chatModel];
// get vector
const promptVector = await openaiEmbedding({
@@ -107,7 +107,7 @@ export async function appKbSearch({
const res: any = await PgClient.query(
`BEGIN;
SET LOCAL ivfflat.probes = ${global.systemEnv.pgIvfflatProbe || 10};
select id,q,a,source from modelData where kb_id IN (${model.chat.relatedKbs
select id,q,a,source from modelData where kb_id IN (${app.chat.relatedKbs
.map((item) => `'${item}'`)
.join(',')}) AND vector <#> '[${promptVector[0]}]' < -${similarity} order by vector <#> '[${
promptVector[0]
@@ -133,32 +133,32 @@ export async function appKbSearch({
});
// 计算固定提示词的 token 数量
const userSystemPrompt = model.chat.systemPrompt // user system prompt
const userSystemPrompt = app.chat.systemPrompt // user system prompt
? [
{
obj: ChatRoleEnum.System,
value: model.chat.systemPrompt
value: app.chat.systemPrompt
}
]
: [];
const userLimitPrompt = [
{
obj: ChatRoleEnum.Human,
value: model.chat.limitPrompt
? model.chat.limitPrompt
: `知识库是关于 ${model.name} 的内容,参考知识库回答问题。与 "${model.name}" 无关内容,直接回复: "我不知道"。`
value: app.chat.limitPrompt
? app.chat.limitPrompt
: `知识库是关于 ${app.name} 的内容,参考知识库回答问题。与 "${app.name}" 无关内容,直接回复: "我不知道"。`
}
];
const fixedSystemTokens = modelToolMap.countTokens({
model: model.chat.chatModel,
model: app.chat.chatModel,
messages: [...userSystemPrompt, ...userLimitPrompt]
});
// filter part quote by maxToken
const sliceResult = modelToolMap
.tokenSlice({
model: model.chat.chatModel,
model: app.chat.chatModel,
maxToken: modelConstantsData.systemMaxToken - fixedSystemTokens,
messages: filterSearch.map((item, i) => ({
obj: ChatRoleEnum.System,

View File

@@ -61,7 +61,7 @@ export async function extract({ agents, history = [], userChatInput, description
agents.forEach((item) => {
properties[item.key] = {
type: 'string',
description: item.desc
description: item.value
};
});

View File

@@ -15,6 +15,8 @@ import { Types } from 'mongoose';
import { moduleFetch } from '@/service/api/request';
import { AppModuleItemType, RunningModuleItemType } from '@/types/app';
import { FlowInputItemTypeEnum } from '@/constants/flow';
import { pushChatBill } from '@/service/events/pushBill';
import { BillTypeEnum } from '@/constants/user';
export type MessageItemType = ChatCompletionRequestMessage & { _id?: string };
type FastGptWebChatProps = {
@@ -168,6 +170,16 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
]
});
}
pushChatBill({
isPay: true,
chatModel: 'gpt-3.5-turbo',
userId,
appId,
textLen: 1,
tokens: 100,
type: BillTypeEnum.chat
});
} catch (err: any) {
if (stream) {
res.status(500);

View File

@@ -31,7 +31,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
kbId: id
});
// delete related model
// delete related app
await App.updateMany(
{
userId