mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 21:13:50 +00:00
perf: openapi auth and lafgpt
This commit is contained in:
@@ -12,7 +12,7 @@ import { pushChatBill } from '@/service/events/pushBill';
|
||||
import { connectRedis } from '@/service/redis';
|
||||
import { VecModelDataPrefix } from '@/constants/redis';
|
||||
import { vectorToBuffer } from '@/utils/tools';
|
||||
import { openaiCreateEmbedding, getOpenApiKey, gpt35StreamResponse } from '@/service/utils/openai';
|
||||
import { openaiCreateEmbedding, gpt35StreamResponse } from '@/service/utils/openai';
|
||||
|
||||
/* 发送提示词 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -31,12 +31,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
});
|
||||
|
||||
try {
|
||||
const { prompt, modelId } = req.body as {
|
||||
const {
|
||||
prompt,
|
||||
modelId,
|
||||
isStream = true
|
||||
} = req.body as {
|
||||
prompt: ChatItemType;
|
||||
modelId: string;
|
||||
isStream: boolean;
|
||||
};
|
||||
|
||||
if (!prompt) {
|
||||
if (!prompt || !modelId) {
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
@@ -45,9 +50,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
let startTime = Date.now();
|
||||
|
||||
/* 凭证校验 */
|
||||
const userId = await authOpenApiKey(req);
|
||||
|
||||
const { userApiKey, systemKey } = await getOpenApiKey(userId);
|
||||
const { apiKey, userId } = await authOpenApiKey(req);
|
||||
|
||||
/* 查找数据库里的模型信息 */
|
||||
const model = await Model.findById(modelId);
|
||||
@@ -61,15 +64,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
if (!modelConstantsData) {
|
||||
throw new Error('模型已下架');
|
||||
}
|
||||
console.log('laf gpt start');
|
||||
|
||||
// 获取 chatAPI
|
||||
const chatAPI = getOpenAIApi(userApiKey || systemKey);
|
||||
const chatAPI = getOpenAIApi(apiKey);
|
||||
|
||||
// 请求一次 chatgpt 拆解需求
|
||||
const promptResponse = await chatAPI.createChatCompletion(
|
||||
{
|
||||
model: ChatModelNameMap[ChatModelNameEnum.GPT35],
|
||||
temperature: 0,
|
||||
frequency_penalty: 0.5, // 越大,重复内容越少
|
||||
presence_penalty: -0.5, // 越大,越容易出现新内容
|
||||
messages: [
|
||||
{
|
||||
role: 'system',
|
||||
@@ -104,7 +110,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
]
|
||||
},
|
||||
{
|
||||
timeout: 40000,
|
||||
timeout: 120000,
|
||||
httpsAgent
|
||||
}
|
||||
);
|
||||
@@ -114,13 +120,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
throw new Error('gpt 异常');
|
||||
}
|
||||
|
||||
prompt.value += `\n${promptResolve}`;
|
||||
prompt.value += ` ${promptResolve}`;
|
||||
console.log('prompt resolve success, time:', `${(Date.now() - startTime) / 1000}s`);
|
||||
|
||||
// 获取提示词的向量
|
||||
const { vector: promptVector } = await openaiCreateEmbedding({
|
||||
isPay: !userApiKey,
|
||||
apiKey: userApiKey || systemKey,
|
||||
isPay: true,
|
||||
apiKey: apiKey,
|
||||
userId,
|
||||
text: prompt.value
|
||||
});
|
||||
@@ -186,34 +192,44 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
const chatResponse = await chatAPI.createChatCompletion(
|
||||
{
|
||||
model: model.service.chatModel,
|
||||
temperature: temperature,
|
||||
// max_tokens: modelConstantsData.maxToken,
|
||||
temperature,
|
||||
messages: formatPrompts,
|
||||
frequency_penalty: 0.5, // 越大,重复内容越少
|
||||
presence_penalty: -0.5, // 越大,越容易出现新内容
|
||||
stream: true
|
||||
stream: isStream
|
||||
},
|
||||
{
|
||||
timeout: 40000,
|
||||
responseType: 'stream',
|
||||
timeout: 120000,
|
||||
responseType: isStream ? 'stream' : 'json',
|
||||
httpsAgent
|
||||
}
|
||||
);
|
||||
|
||||
console.log('api response. time:', `${(Date.now() - startTime) / 1000}s`);
|
||||
console.log('code response. time:', `${(Date.now() - startTime) / 1000}s`);
|
||||
|
||||
step = 1;
|
||||
const { responseContent } = await gpt35StreamResponse({
|
||||
res,
|
||||
stream,
|
||||
chatResponse
|
||||
});
|
||||
console.log('response done. time:', `${(Date.now() - startTime) / 1000}s`);
|
||||
let responseContent = '';
|
||||
|
||||
if (isStream) {
|
||||
const streamResponse = await gpt35StreamResponse({
|
||||
res,
|
||||
stream,
|
||||
chatResponse
|
||||
});
|
||||
responseContent = streamResponse.responseContent;
|
||||
} else {
|
||||
responseContent = chatResponse.data.choices?.[0]?.message?.content || '';
|
||||
jsonRes(res, {
|
||||
data: responseContent
|
||||
});
|
||||
}
|
||||
|
||||
console.log('laf gpt done. time:', `${(Date.now() - startTime) / 1000}s`);
|
||||
|
||||
const promptsContent = formatPrompts.map((item) => item.content).join('');
|
||||
// 只有使用平台的 key 才计费
|
||||
|
||||
pushChatBill({
|
||||
isPay: !userApiKey,
|
||||
isPay: true,
|
||||
modelName: model.service.modelName,
|
||||
userId,
|
||||
text: promptsContent + responseContent
|
||||
|
@@ -4,7 +4,8 @@ import jwt from 'jsonwebtoken';
|
||||
import tunnel from 'tunnel';
|
||||
import { ChatItemType } from '@/types/chat';
|
||||
import { encode } from 'gpt-token-utils';
|
||||
import { OpenApi } from '../mongo';
|
||||
import { OpenApi, User } from '../mongo';
|
||||
import { formatPrice } from '@/utils/user';
|
||||
|
||||
/* 密码加密 */
|
||||
export const hashPassword = (psw: string) => {
|
||||
@@ -44,27 +45,41 @@ export const authToken = (token?: string): Promise<string> => {
|
||||
};
|
||||
|
||||
/* 校验 open api key */
|
||||
export const authOpenApiKey = (req: NextApiRequest) => {
|
||||
return new Promise<string>(async (resolve, reject) => {
|
||||
const { apikey: apiKey } = req.headers;
|
||||
export const authOpenApiKey = async (req: NextApiRequest) => {
|
||||
const { apikey: apiKey } = req.headers;
|
||||
|
||||
if (!apiKey) {
|
||||
reject('api key is empty');
|
||||
return;
|
||||
if (!apiKey) {
|
||||
return Promise.reject('api key is empty');
|
||||
}
|
||||
|
||||
try {
|
||||
const openApi = await OpenApi.findOne({ apiKey });
|
||||
if (!openApi) {
|
||||
return Promise.reject('api key is error');
|
||||
}
|
||||
try {
|
||||
const openApi = await OpenApi.findOne({ apiKey });
|
||||
if (!openApi) {
|
||||
return reject('api key is error');
|
||||
}
|
||||
await OpenApi.findByIdAndUpdate(openApi._id, {
|
||||
lastUsedTime: new Date()
|
||||
});
|
||||
resolve(String(openApi.userId));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
const userId = String(openApi.userId);
|
||||
|
||||
// 余额校验
|
||||
const user = await User.findById(userId);
|
||||
if (!user) {
|
||||
return Promise.reject('user is empty');
|
||||
}
|
||||
});
|
||||
if (formatPrice(user.balance) <= 0) {
|
||||
return Promise.reject('Insufficient account balance');
|
||||
}
|
||||
|
||||
// 更新使用的时间
|
||||
await OpenApi.findByIdAndUpdate(openApi._id, {
|
||||
lastUsedTime: new Date()
|
||||
});
|
||||
|
||||
return {
|
||||
apiKey: process.env.OPENAIKEY as string,
|
||||
userId
|
||||
};
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
};
|
||||
|
||||
/* 代理 */
|
||||
|
Reference in New Issue
Block a user