perf: keys

This commit is contained in:
archer
2023-06-23 17:12:52 +08:00
parent ae1f7a888e
commit 41ada6ecda
18 changed files with 49 additions and 93 deletions

View File

@@ -26,7 +26,8 @@ MONGODB_NAME=fastgpt
ADMIN_USER=username ADMIN_USER=username
ADMIN_PASS=password ADMIN_PASS=password
ADMIN_SECRET=any ADMIN_SECRET=any
VITE_PUBLIC_SERVER_URL=http://localhost:3001 # 和server.js一致 PARENT_URL=http://localhost:3000
PARENT_ROOT_KEY=rootkey
``` ```
## sealos 部署 ## sealos 部署

View File

@@ -86,18 +86,6 @@ const modelSchema = new mongoose.Schema({
}); });
const SystemSchema = new mongoose.Schema({ const SystemSchema = new mongoose.Schema({
openAIKeys: {
type: String,
default: ''
},
openAITrainingKeys: {
type: String,
default: ''
},
gpt4Key: {
type: String,
default: ''
},
vectorMaxProcess: { vectorMaxProcess: {
type: Number, type: Number,
default: 10 default: 10

View File

@@ -45,9 +45,6 @@ export const ModelFields = [
]; ];
export const SystemFields = [ export const SystemFields = [
createTextField('openAIKeys', { label: 'openAIKeys逗号隔开' }),
createTextField('openAITrainingKeys', { label: 'openAITrainingKeys' }),
createTextField('gpt4Key', { label: 'gpt4Key' }),
createTextField('vectorMaxProcess', { label: '向量最大进程' }), createTextField('vectorMaxProcess', { label: '向量最大进程' }),
createTextField('qaMaxProcess', { label: 'qa最大进程' }), createTextField('qaMaxProcess', { label: 'qa最大进程' }),
createTextField('pgIvfflatProbe', { label: 'pg 探针数量' }), createTextField('pgIvfflatProbe', { label: 'pg 探针数量' }),

View File

@@ -21,8 +21,6 @@ ROOT_KEY=fdafasd
# OPENAI_BASE_URL=http://ai.openai.com/v1 # OPENAI_BASE_URL=http://ai.openai.com/v1
# OPENAI_BASE_URL_AUTH=可选安全凭证,会放到 header.auth 里 # OPENAI_BASE_URL_AUTH=可选安全凭证,会放到 header.auth 里
OPENAIKEY=sk-xxx OPENAIKEY=sk-xxx
OPENAI_TRAINING_KEY=sk-xxx
GPT4KEY=sk-xxx
# db # db
MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
MONGODB_NAME=fastgpt MONGODB_NAME=fastgpt

View File

@@ -96,8 +96,7 @@ export async function appKbSearch({
// get vector // get vector
const promptVector = await openaiEmbedding({ const promptVector = await openaiEmbedding({
userId, userId,
input: [prompt.value], input: [prompt.value]
type: 'chat'
}); });
// search kb // search kb

View File

@@ -29,8 +29,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
const vector = await openaiEmbedding({ const vector = await openaiEmbedding({
userId, userId,
input: [text], input: [text]
type: 'training'
}); });
const response: any = await PgClient.query( const response: any = await PgClient.query(

View File

@@ -21,8 +21,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
if (q) { if (q) {
return openaiEmbedding({ return openaiEmbedding({
userId, userId,
input: [q], input: [q]
type: 'chat'
}); });
} }
return []; return [];

View File

@@ -6,26 +6,24 @@ import { getOpenAIApi } from '@/service/utils/chat/openai';
import { embeddingModel } from '@/constants/model'; import { embeddingModel } from '@/constants/model';
import { axiosConfig } from '@/service/utils/tools'; import { axiosConfig } from '@/service/utils/tools';
import { pushGenerateVectorBill } from '@/service/events/pushBill'; import { pushGenerateVectorBill } from '@/service/events/pushBill';
import { ApiKeyType } from '@/service/utils/auth';
import { OpenAiChatEnum } from '@/constants/model'; import { OpenAiChatEnum } from '@/constants/model';
type Props = { type Props = {
input: string[]; input: string[];
type?: ApiKeyType;
}; };
type Response = number[][]; type Response = number[][];
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) { export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try { try {
const { userId } = await authUser({ req }); const { userId } = await authUser({ req });
let { input, type } = req.query as Props; let { input } = req.query as Props;
if (!Array.isArray(input)) { if (!Array.isArray(input)) {
throw new Error('缺少参数'); throw new Error('缺少参数');
} }
jsonRes<Response>(res, { jsonRes<Response>(res, {
data: await openaiEmbedding({ userId, input, type, mustPay: true }) data: await openaiEmbedding({ userId, input, mustPay: true })
}); });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
@@ -39,14 +37,12 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
export async function openaiEmbedding({ export async function openaiEmbedding({
userId, userId,
input, input,
mustPay = false, mustPay = false
type = 'chat'
}: { userId: string; mustPay?: boolean } & Props) { }: { userId: string; mustPay?: boolean } & Props) {
const { userOpenAiKey, systemAuthKey } = await getApiKey({ const { userOpenAiKey, systemAuthKey } = await getApiKey({
model: OpenAiChatEnum.GPT35, model: OpenAiChatEnum.GPT35,
userId, userId,
mustPay, mustPay
type
}); });
// 获取 chatAPI // 获取 chatAPI

View File

@@ -33,7 +33,7 @@ export async function sensitiveCheck({ input }: Props) {
} }
const response = await axios({ const response = await axios({
...axiosConfig(getSystemOpenAiKey('chat')), ...axiosConfig(getSystemOpenAiKey()),
method: 'POST', method: 'POST',
url: `/moderations`, url: `/moderations`,
data: { data: {

View File

@@ -7,11 +7,9 @@ import { ChatModelMap, OpenAiChatEnum } from '@/constants/model';
export default async function handler(req: NextApiRequest, res: NextApiResponse) { export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const chatModelList: ChatModelItemType[] = []; const chatModelList: ChatModelItemType[] = [];
if (global.systemEnv.openAIKeys) { if (process.env.OPENAIKEY) {
chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT3516k]); chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT3516k]);
chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT35]); chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT35]);
}
if (global.systemEnv.gpt4Key) {
chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT4]); chatModelList.push(ChatModelMap[OpenAiChatEnum.GPT4]);
} }

View File

@@ -256,7 +256,7 @@ const SelectFileModal = ({
)} )}
{/* chunk size */} {/* chunk size */}
{mode === TrainingModeEnum.index && ( {mode === TrainingModeEnum.index && (
<Flex w={'100%'} px={5} alignItems={'center'} mt={4}> <Flex mt={5}>
<Box w={['70px']} flexShrink={0}> <Box w={['70px']} flexShrink={0}>
</Box> </Box>

View File

@@ -55,7 +55,6 @@ export async function generateQA(): Promise<any> {
const { systemAuthKey } = await getApiKey({ const { systemAuthKey } = await getApiKey({
model: OpenAiChatEnum.GPT35, model: OpenAiChatEnum.GPT35,
userId, userId,
type: 'training',
mustPay: true mustPay: true
}); });

View File

@@ -58,7 +58,6 @@ export async function generateVector(): Promise<any> {
const vectors = await openaiEmbedding({ const vectors = await openaiEmbedding({
input: dataItems.map((item) => item.q), input: dataItems.map((item) => item.q),
userId, userId,
type: 'training',
mustPay: true mustPay: true
}); });

View File

@@ -1,18 +1,6 @@
import { Schema, model, models } from 'mongoose'; import { Schema, model, models } from 'mongoose';
const SystemSchema = new Schema({ const SystemSchema = new Schema({
openAIKeys: {
type: String,
default: ''
},
openAITrainingKeys: {
type: String,
default: ''
},
gpt4Key: {
type: String,
default: ''
},
vectorMaxProcess: { vectorMaxProcess: {
type: Number, type: Number,
default: 10 default: 10

View File

@@ -15,9 +15,6 @@ export async function connectToDatabase(): Promise<void> {
global.qaQueueLen = 0; global.qaQueueLen = 0;
global.vectorQueueLen = 0; global.vectorQueueLen = 0;
global.systemEnv = { global.systemEnv = {
openAIKeys: process.env.OPENAIKEY || '',
openAITrainingKeys: process.env.OPENAI_TRAINING_KEY || '',
gpt4Key: process.env.GPT4KEY || '',
vectorMaxProcess: 10, vectorMaxProcess: 10,
qaMaxProcess: 10, qaMaxProcess: 10,
pgIvfflatProbe: 10, pgIvfflatProbe: 10,

View File

@@ -11,7 +11,6 @@ import { ERROR_ENUM } from '../errorCode';
import { ChatModelType, OpenAiChatEnum } from '@/constants/model'; import { ChatModelType, OpenAiChatEnum } from '@/constants/model';
import { hashPassword } from '@/service/utils/tools'; import { hashPassword } from '@/service/utils/tools';
export type ApiKeyType = 'training' | 'chat';
export type AuthType = 'token' | 'root' | 'apikey'; export type AuthType = 'token' | 'root' | 'apikey';
export const parseCookie = (cookie?: string): Promise<string> => { export const parseCookie = (cookie?: string): Promise<string> => {
@@ -163,37 +162,19 @@ export const authUser = async ({
}; };
/* random get openai api key */ /* random get openai api key */
export const getSystemOpenAiKey = (type: ApiKeyType) => { export const getSystemOpenAiKey = () => {
const keys = (() => { return process.env.OPENAIKEY || '';
if (type === 'training') {
return global.systemEnv.openAITrainingKeys?.split(',') || [];
}
return global.systemEnv.openAIKeys?.split(',') || [];
})();
// 纯字符串类型
const i = Math.floor(Math.random() * keys.length);
return keys[i] || (global.systemEnv.openAIKeys as string);
};
export const getGpt4Key = () => {
const keys = global.systemEnv.gpt4Key?.split(',') || [];
// 纯字符串类型
const i = Math.floor(Math.random() * keys.length);
return keys[i] || (global.systemEnv.openAIKeys as string);
}; };
/* 获取 api 请求的 key */ /* 获取 api 请求的 key */
export const getApiKey = async ({ export const getApiKey = async ({
model, model,
userId, userId,
mustPay = false, mustPay = false
type = 'chat'
}: { }: {
model: ChatModelType; model: ChatModelType;
userId: string; userId: string;
mustPay?: boolean; mustPay?: boolean;
type?: ApiKeyType;
}) => { }) => {
const user = await User.findById(userId); const user = await User.findById(userId);
if (!user) { if (!user) {
@@ -203,19 +184,19 @@ export const getApiKey = async ({
const keyMap = { const keyMap = {
[OpenAiChatEnum.GPT35]: { [OpenAiChatEnum.GPT35]: {
userOpenAiKey: user.openaiKey || '', userOpenAiKey: user.openaiKey || '',
systemAuthKey: getSystemOpenAiKey(type) as string systemAuthKey: getSystemOpenAiKey()
}, },
[OpenAiChatEnum.GPT3516k]: { [OpenAiChatEnum.GPT3516k]: {
userOpenAiKey: user.openaiKey || '', userOpenAiKey: user.openaiKey || '',
systemAuthKey: getSystemOpenAiKey(type) as string systemAuthKey: getSystemOpenAiKey()
}, },
[OpenAiChatEnum.GPT4]: { [OpenAiChatEnum.GPT4]: {
userOpenAiKey: user.openaiKey || '', userOpenAiKey: user.openaiKey || '',
systemAuthKey: getGpt4Key() as string systemAuthKey: getSystemOpenAiKey()
}, },
[OpenAiChatEnum.GPT432k]: { [OpenAiChatEnum.GPT432k]: {
userOpenAiKey: user.openaiKey || '', userOpenAiKey: user.openaiKey || '',
systemAuthKey: getGpt4Key() as string systemAuthKey: getSystemOpenAiKey()
} }
}; };

View File

@@ -23,9 +23,6 @@ declare global {
var vectorQueueLen: number; var vectorQueueLen: number;
var OpenAiEncMap: Record<string, Tiktoken>; var OpenAiEncMap: Record<string, Tiktoken>;
var systemEnv: { var systemEnv: {
openAIKeys: string;
openAITrainingKeys: string;
gpt4Key: string;
vectorMaxProcess: number; vectorMaxProcess: number;
qaMaxProcess: number; qaMaxProcess: number;
pgIvfflatProbe: number; pgIvfflatProbe: number;

View File

@@ -1,3 +1,4 @@
# host 版本。
version: '3.3' version: '3.3'
services: services:
pg: pg:
@@ -31,10 +32,9 @@ services:
- /root/fastgpt/mongo/data:/data/db - /root/fastgpt/mongo/data:/data/db
- /root/fastgpt/mongo/logs:/var/log/mongodb - /root/fastgpt/mongo/logs:/var/log/mongodb
fastgpt: fastgpt:
# image: ghcr.io/c121914yu/fastgpt:latest # github
# image: c121914yu/fast-gpt:latest # docker hub # image: c121914yu/fast-gpt:latest # docker hub
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云 image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
network_mode: host # network_mode: host #
restart: always restart: always
container_name: fastgpt container_name: fastgpt
environment: # 可选的变量,不需要的话需要去掉 environment: # 可选的变量,不需要的话需要去掉
@@ -55,9 +55,9 @@ services:
- CLIENT_GOOGLE_VER_TOKEN=xxx - CLIENT_GOOGLE_VER_TOKEN=xxx
- SERVICE_GOOGLE_VER_TOKEN=xx - SERVICE_GOOGLE_VER_TOKEN=xx
# token加密凭证随便填作为登录凭证 # token加密凭证随便填作为登录凭证
- TOKEN_KEY=xxxx - TOKEN_KEY=any
# root key, 最高权限,可以内部接口互相调用 # root key, 最高权限,可以内部接口互相调用
- ROOT_KEY=xxx - ROOT_KEY=root_key
# 和上方mongo镜像的username,password对应 # 和上方mongo镜像的username,password对应
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin - MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
- MONGODB_NAME=fastgpt - MONGODB_NAME=fastgpt
@@ -68,14 +68,34 @@ services:
- PG_PASSWORD=1234 - PG_PASSWORD=1234
- PG_DB_NAME=fastgpt - PG_DB_NAME=fastgpt
# openai # openai
# 对话用的key多个key逗号分开 - OPENAIKEY=sk-xxxxx
- OPENAIKEY=sk-xxxxx,sk-xxx
# 训练用的key
- OPENAI_TRAINING_KEY=sk-xxx,sk-xxxx
- GPT4KEY=sk-xxx
- OPENAI_BASE_URL=https://api.openai.com/v1 - OPENAI_BASE_URL=https://api.openai.com/v1
- OPENAI_BASE_URL_AUTH=可选的安全凭证 - OPENAI_BASE_URL_AUTH=可选的安全凭证
nginx: fastgpt-admin:
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-admin:latest
container_name: fastgpt-admin
restart: always
ports:
- 3001:3001
environment:
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
- MONGODB_NAME=fastgpt
- ADMIN_USER=username
- ADMIN_PASS=password
- ADMIN_SECRET=any
- PARENT_URL=http://0.0.0.0:3000
- PARENT_ROOT_KEY=root_key
key-admin:
container_name: key-admin
image: justsong/one-api
restart: always
ports:
- 3002:3000
environment:
- TZ=Asia/Shanghai
volumes:
- /home/ubuntu/data/one-api:/data
nginx: # 宝塔不需要额外装 nginx
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/nginx:alpine3.17 image: registry.cn-hangzhou.aliyuncs.com/fastgpt/nginx:alpine3.17
# image: nginx:alpine3.17 # image: nginx:alpine3.17
container_name: nginx container_name: nginx