feat: openapi v2 chat

This commit is contained in:
archer
2023-06-18 19:59:37 +08:00
parent 2b93ae2d00
commit ee9afa310a
27 changed files with 790 additions and 585 deletions

View File

@@ -3,15 +3,16 @@ import jwt from 'jsonwebtoken';
import Cookie from 'cookie';
import { Chat, Model, OpenApi, User, ShareChat, KB } from '../mongo';
import type { ModelSchema } from '@/types/mongoSchema';
import type { ChatItemSimpleType } from '@/types/chat';
import type { ChatItemType } from '@/types/chat';
import mongoose from 'mongoose';
import { ClaudeEnum, defaultModel, embeddingModel, EmbeddingModelType } from '@/constants/model';
import { defaultModel } from '@/constants/model';
import { formatPrice } from '@/utils/user';
import { ERROR_ENUM } from '../errorCode';
import { ChatModelType, OpenAiChatEnum } from '@/constants/model';
import { hashPassword } from '@/service/utils/tools';
export type ApiKeyType = 'training' | 'chat';
export type AuthType = 'token' | 'root' | 'apikey';
export const parseCookie = (cookie?: string): Promise<string> => {
return new Promise((resolve, reject) => {
@@ -39,13 +40,11 @@ export const parseCookie = (cookie?: string): Promise<string> => {
export const authUser = async ({
req,
authToken = false,
authOpenApi = false,
authRoot = false,
authBalance = false
}: {
req: NextApiRequest;
authToken?: boolean;
authOpenApi?: boolean;
authRoot?: boolean;
authBalance?: boolean;
}) => {
@@ -71,6 +70,36 @@ export const authUser = async ({
return Promise.reject(error);
}
};
const parseAuthorization = async (authorization?: string) => {
if (!authorization) {
return Promise.reject(ERROR_ENUM.unAuthorization);
}
// Bearer fastgpt-xxxx-appId
const auth = authorization.split(' ')[1];
if (!auth) {
return Promise.reject(ERROR_ENUM.unAuthorization);
}
const { apiKey, appId } = await (async () => {
const arr = auth.split('-');
if (arr.length !== 3) {
return Promise.reject(ERROR_ENUM.unAuthorization);
}
return {
apiKey: `${arr[0]}-${arr[1]}`,
appId: arr[2]
};
})();
// auth apiKey
const uid = await parseOpenApiKey(apiKey);
return {
uid,
appId
};
};
const parseRootKey = async (rootKey?: string, userId = '') => {
if (!rootKey || !process.env.ROOT_KEY || rootKey !== process.env.ROOT_KEY) {
return Promise.reject(ERROR_ENUM.unAuthorization);
@@ -78,31 +107,43 @@ export const authUser = async ({
return userId;
};
const { cookie, apikey, rootkey, userid } = (req.headers || {}) as {
const { cookie, apikey, rootkey, userid, authorization } = (req.headers || {}) as {
cookie?: string;
apikey?: string;
rootkey?: string;
userid?: string;
authorization?: string;
};
let uid = '';
let appId = '';
let authType: AuthType = 'token';
if (authToken) {
uid = await parseCookie(cookie);
} else if (authOpenApi) {
uid = await parseOpenApiKey(apikey);
authType = 'token';
} else if (authRoot) {
uid = await parseRootKey(rootkey, userid);
authType = 'root';
} else if (cookie) {
uid = await parseCookie(cookie);
authType = 'token';
} else if (apikey) {
uid = await parseOpenApiKey(apikey);
authType = 'apikey';
} else if (authorization) {
const authResponse = await parseAuthorization(authorization);
uid = authResponse.uid;
appId = authResponse.appId;
authType = 'apikey';
} else if (rootkey) {
uid = await parseRootKey(rootkey, userid);
authType = 'root';
} else {
return Promise.reject(ERROR_ENUM.unAuthorization);
}
// balance check
if (authBalance) {
const user = await User.findById(uid);
if (!user) {
@@ -115,7 +156,9 @@ export const authUser = async ({
}
return {
userId: uid
userId: uid,
appId,
authType
};
};
@@ -173,15 +216,15 @@ export const getApiKey = async ({
[OpenAiChatEnum.GPT432k]: {
userOpenAiKey: user.openaiKey || '',
systemAuthKey: getGpt4Key() as string
},
[ClaudeEnum.Claude]: {
userOpenAiKey: '',
systemAuthKey: process.env.CLAUDE_KEY as string
}
};
if (!keyMap[model]) {
return Promise.reject('App model is exists');
}
// 有自己的key
if (!mustPay && keyMap[model]?.userOpenAiKey) {
if (!mustPay && keyMap[model].userOpenAiKey) {
return {
user,
userOpenAiKey: keyMap[model].userOpenAiKey,
@@ -240,7 +283,7 @@ export const authModel = async ({
return {
model,
showModelDetail: model.share.isShareDetail || userId === String(model.userId)
showModelDetail: userId === String(model.userId)
};
};
@@ -277,7 +320,7 @@ export const authChat = async ({
});
// 聊天内容
let content: ChatItemSimpleType[] = [];
let content: ChatItemType[] = [];
if (chatId) {
// 获取 chat 数据
@@ -336,28 +379,9 @@ export const authShareChat = async ({
});
}
const modelId = String(shareChat.modelId);
const userId = String(shareChat.userId);
// 获取 model 数据
const { model, showModelDetail } = await authModel({
modelId,
userId,
authOwner: false,
reserveDetail: true
});
// 获取 user 的 apiKey
const { userOpenAiKey, systemAuthKey } = await getApiKey({
model: model.chat.chatModel,
userId
});
return {
userOpenAiKey,
systemAuthKey,
userId,
model,
showModelDetail
userId: String(shareChat.userId),
appId: String(shareChat.modelId),
authType: 'token' as AuthType
};
};