This commit is contained in:
archer
2023-07-11 15:57:01 +08:00
parent cd77d81135
commit eb768d9c04
47 changed files with 1949 additions and 1280 deletions

View File

@@ -0,0 +1,77 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { connectToDatabase } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { sseErrRes } from '@/service/response';
import { sseResponseEventEnum } from '@/constants/chat';
import { sseResponse } from '@/service/utils/tools';
import { type ChatCompletionRequestMessage } from 'openai';
import { AppModuleItemType } from '@/types/app';
import { dispatchModules } from '../openapi/v1/chat/completions2';
export type MessageItemType = ChatCompletionRequestMessage & { _id?: string };
export type Props = {
history: MessageItemType[];
prompt: string;
modules: AppModuleItemType[];
variable: Record<string, any>;
};
export type ChatResponseType = {
newChatId: string;
quoteLen?: number;
};
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
res.on('close', () => {
res.end();
});
res.on('error', () => {
console.log('error: ', 'request error');
res.end();
});
let { modules = [], history = [], prompt, variable = {} } = req.body as Props;
try {
if (!history || !modules || !prompt) {
throw new Error('Prams Error');
}
if (!Array.isArray(modules)) {
throw new Error('history is not array');
}
await connectToDatabase();
/* user auth */
const { userId } = await authUser({ req });
/* start process */
const { responseData } = await dispatchModules({
res,
modules: modules,
variable,
params: {
history,
userChatInput: prompt
},
stream: true
});
sseResponse({
res,
event: sseResponseEventEnum.answer,
data: '[DONE]'
});
sseResponse({
res,
event: sseResponseEventEnum.appStreamResponse,
data: JSON.stringify(responseData)
});
res.end();
// bill
} catch (err: any) {
res.status(500);
sseErrRes(res, err);
res.end();
}
}

View File

@@ -3,33 +3,36 @@ import { jsonRes } from '@/service/response';
import { connectToDatabase, ShareChat } from '@/service/mongo';
import { authApp, authUser } from '@/service/utils/auth';
import type { ShareChatEditType } from '@/types/app';
import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
/* create a shareChat */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { modelId, name, maxContext, password } = req.body as ShareChatEditType & {
modelId: string;
const { appId, name, maxContext } = req.body as ShareChatEditType & {
appId: string;
};
await connectToDatabase();
const { userId } = await authUser({ req, authToken: true });
await authApp({
appId: modelId,
appId,
userId,
authOwner: false
});
const { _id } = await ShareChat.create({
const shareId = nanoid();
await ShareChat.create({
shareId,
userId,
modelId,
appId,
name,
password,
maxContext
});
jsonRes(res, {
data: _id
data: shareId
});
} catch (err) {
jsonRes(res, {

View File

@@ -5,13 +5,14 @@ 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';
/* 初始化我的聊天框,需要身份验证 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
let { shareId, password = '' } = req.query as {
let { shareId } = req.query as {
shareId: string;
password: string;
};
if (!shareId) {
@@ -21,22 +22,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
await connectToDatabase();
// get shareChat
const shareChat = await ShareChat.findById(shareId);
const shareChat = await ShareChat.findOne({ shareId });
if (!shareChat) {
throw new Error('分享链接已失效');
}
if (shareChat.password !== hashPassword(password)) {
return jsonRes(res, {
code: 501,
message: '密码不正确'
error: '分享链接已失效'
});
}
// 校验使用权限
const { app } = await authApp({
appId: shareChat.modelId,
appId: shareChat.appId,
userId: String(shareChat.userId),
authOwner: false
});
@@ -45,15 +42,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
jsonRes<InitShareChatResponse>(res, {
data: {
appId: shareChat.modelId,
maxContext: shareChat.maxContext,
userAvatar: user?.avatar || HUMAN_ICON,
model: {
maxContext:
app.modules
?.find((item) => item.flowType === FlowModuleTypeEnum.historyNode)
?.inputs?.find((item) => item.key === 'maxContext')?.value || 0,
app: {
variableModules: app.modules
.find((item) => item.flowType === FlowModuleTypeEnum.userGuide)
?.inputs?.find((item) => item.key === SystemInputEnum.variables)?.value,
welcomeText: app.modules
.find((item) => item.flowType === FlowModuleTypeEnum.userGuide)
?.inputs?.find((item) => item.key === SystemInputEnum.welcomeText)?.value,
name: app.name,
avatar: app.avatar,
intro: app.intro
},
chatModel: app.chat.chatModel
}
}
});
} catch (err) {

View File

@@ -4,11 +4,11 @@ import { connectToDatabase, ShareChat } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { hashPassword } from '@/service/utils/tools';
/* get shareChat list by modelId */
/* get shareChat list by appId */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { modelId } = req.query as {
modelId: string;
const { appId } = req.query as {
appId: string;
};
await connectToDatabase();
@@ -16,19 +16,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const { userId } = await authUser({ req, authToken: true });
const data = await ShareChat.find({
modelId,
appId,
userId
}).sort({
_id: -1
});
const blankPassword = hashPassword('');
jsonRes(res, {
data: data.map((item) => ({
_id: item._id,
shareId: item.shareId,
name: item.name,
password: item.password === blankPassword ? '' : '1',
tokens: item.tokens,
maxContext: item.maxContext,
lastTime: item.lastTime

View File

@@ -131,6 +131,7 @@ export async function chatCompletion({
const adaptMessages = adaptChatItem_openAI({ messages: filterMessages, reserveId: false });
const chatAPI = getOpenAIApi();
console.log(adaptMessages);
/* count response max token */
const promptsToken = modelToolMap.countTokens({

View File

@@ -23,7 +23,6 @@ type FastGptWebChatProps = {
appId?: string;
};
type FastGptShareChatProps = {
password?: string;
shareId?: string;
};
export type Props = CreateChatCompletionRequest &
@@ -31,6 +30,7 @@ export type Props = CreateChatCompletionRequest &
FastGptShareChatProps & {
messages: MessageItemType[];
stream?: boolean;
variables: Record<string, any>;
};
export type ChatResponseType = {
newChatId: string;
@@ -46,7 +46,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
res.end();
});
let { chatId, appId, shareId, password = '', stream = false, messages = [] } = req.body as Props;
let { chatId, appId, shareId, stream = false, messages = [], variables = {} } = req.body as Props;
try {
if (!messages) {
@@ -66,8 +66,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
authType
} = await (shareId
? authShareChat({
shareId,
password
shareId
})
: authUser({ req }));
@@ -105,6 +104,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
const { responseData, answerText } = await dispatchModules({
res,
modules: app.modules,
variables,
params: {
history: prompts,
userChatInput: prompt.value
@@ -175,18 +175,20 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
}
});
async function dispatchModules({
export async function dispatchModules({
res,
modules,
params = {},
variables = {},
stream = false
}: {
res: NextApiResponse;
modules: AppModuleItemType[];
params?: Record<string, any>;
variables?: Record<string, any>;
stream?: boolean;
}) {
const runningModules = loadModules(modules);
const runningModules = loadModules(modules, variables);
let storeData: Record<string, any> = {};
let responseData: Record<string, any> = {};
let answerText = '';
@@ -333,7 +335,10 @@ async function dispatchModules({
};
}
function loadModules(modules: AppModuleItemType[]): RunningModuleItemType[] {
function loadModules(
modules: AppModuleItemType[],
variables: Record<string, any>
): RunningModuleItemType[] {
return modules.map((module) => {
return {
moduleId: module.moduleId,
@@ -341,10 +346,25 @@ function loadModules(modules: AppModuleItemType[]): RunningModuleItemType[] {
url: module.url,
inputs: module.inputs
.filter((item) => item.type !== FlowInputItemTypeEnum.target || item.connected) // filter unconnected target input
.map((item) => ({
key: item.key,
value: item.value
})),
.map((item) => {
if (typeof item.value !== 'string') {
return {
key: item.key,
value: item.value
};
}
// variables replace
const replacedVal = item.value.replace(
/{{(.*?)}}/g,
(match, key) => variables[key.trim()] || match
);
return {
key: item.key,
value: replacedVal
};
}),
outputs: module.outputs.map((item) => ({
key: item.key,
answer: item.key === SpecificInputEnum.answerText,