diff --git a/src/pages/api/openapi/chat/lafGpt.ts b/src/pages/api/openapi/chat/lafGpt.ts index 3b480d17e..ad0e1e841 100644 --- a/src/pages/api/openapi/chat/lafGpt.ts +++ b/src/pages/api/openapi/chat/lafGpt.ts @@ -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 diff --git a/src/service/utils/tools.ts b/src/service/utils/tools.ts index 5c0420138..1bb8a9709 100644 --- a/src/service/utils/tools.ts +++ b/src/service/utils/tools.ts @@ -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 => { }; /* 校验 open api key */ -export const authOpenApiKey = (req: NextApiRequest) => { - return new Promise(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); + } }; /* 代理 */