diff --git a/src/pages/api/chat/chatGpt.ts b/src/pages/api/chat/chatGpt.ts index dc15dfb77..4063ee220 100644 --- a/src/pages/api/chat/chatGpt.ts +++ b/src/pages/api/chat/chatGpt.ts @@ -148,13 +148,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const promptsContent = formatPrompts.map((item) => item.content).join(''); // 只有使用平台的 key 才计费 - !userApiKey && - pushChatBill({ - modelName: model.service.modelName, - userId, - chatId, - text: promptsContent + responseContent - }); + pushChatBill({ + isPay: !userApiKey, + modelName: model.service.modelName, + userId, + chatId, + text: promptsContent + responseContent + }); } catch (err: any) { if (step === 1) { // 直接结束流 diff --git a/src/pages/api/chat/gpt3.ts b/src/pages/api/chat/gpt3.ts index 611f372c2..2bcbdc588 100644 --- a/src/pages/api/chat/gpt3.ts +++ b/src/pages/api/chat/gpt3.ts @@ -149,13 +149,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) stream.destroy(); // 只有使用平台的 key 才计费 - !userApiKey && - pushChatBill({ - modelName: model.service.modelName, - userId, - chatId, - text: promptText + responseContent - }); + pushChatBill({ + isPay: !userApiKey, + modelName: model.service.modelName, + userId, + chatId, + text: promptText + responseContent + }); } catch (err: any) { // console.log(err?.response); if (step === 1) { diff --git a/src/service/events/generateAbstract.ts b/src/service/events/generateAbstract.ts index 3f2fb8dc2..677947719 100644 --- a/src/service/events/generateAbstract.ts +++ b/src/service/events/generateAbstract.ts @@ -12,7 +12,7 @@ export async function generateAbstract(next = false): Promise { const systemPrompt: ChatCompletionRequestMessage = { role: 'system', - content: `总结助手,我会向你发送一段长文本,请从文本中归纳总结5至15条信息,请直接输出总结内容,并按以下格式输出: 'A1:'\n'A2:'\n'A3:'\n` + content: `总结助手,我会向你发送一段长文本,请从文本中归纳总结5至15条信息,如果是英文,请增加一条中文的总结,并按以下格式输出: A1:\nA2:\nA3:\n` }; let dataItem: DataItemSchema | null = null; @@ -80,36 +80,36 @@ export async function generateAbstract(next = false): Promise { const rawContent: string = abstractResponse?.data.choices[0].message?.content || ''; // 从 content 中提取摘要内容 const splitContents = splitText(rawContent); - console.log(rawContent); + // console.log(rawContent); // 生成词向量 - const vectorResponse = await Promise.allSettled( - splitContents.map((item) => - chatAPI.createEmbedding( - { - model: 'text-embedding-ada-002', - input: item.abstract - }, - { - timeout: 120000, - httpsAgent - } - ) - ) - ); + // const vectorResponse = await Promise.allSettled( + // splitContents.map((item) => + // chatAPI.createEmbedding( + // { + // model: 'text-embedding-ada-002', + // input: item.abstract + // }, + // { + // timeout: 120000, + // httpsAgent + // } + // ) + // ) + // ); // 筛选成功的向量请求 - const vectorSuccessResponse = vectorResponse - .map((item: any, i) => { - if (item.status !== 'fulfilled') { - // 没有词向量的【摘要】不要 - console.log('获取词向量错误: ', item); - return ''; - } - return { - abstract: splitContents[i].abstract, - abstractVector: item?.value?.data?.data?.[0]?.embedding - }; - }) - .filter((item) => item); + // const vectorSuccessResponse = vectorResponse + // .map((item: any, i) => { + // if (item.status !== 'fulfilled') { + // // 没有词向量的【摘要】不要 + // console.log('获取词向量错误: ', item); + // return ''; + // } + // return { + // abstract: splitContents[i].abstract, + // abstractVector: item?.value?.data?.data?.[0]?.embedding + // }; + // }) + // .filter((item) => item); // 插入数据库,并修改状态 await DataItem.findByIdAndUpdate(dataItem._id, { @@ -117,28 +117,22 @@ export async function generateAbstract(next = false): Promise { $push: { rawResponse: rawContent, result: { - $each: vectorSuccessResponse + $each: splitContents } } }); - // 计费 - !userApiKey && - vectorSuccessResponse.length > 0 && - pushSplitDataBill({ - userId: dataItem.userId, - type: 'abstract', - text: - systemPrompt.content + - dataItem.text + - rawContent + - rawContent.substring(0, Math.floor(dataItem.text.length / 10)) // 向量价格是 gpt35 的1/10 - }); console.log( `生成摘要成功,time: ${(Date.now() - startTime) / 1000}s`, - `摘要匹配数量: ${splitContents.length}`, - `有向量摘要数量:${vectorSuccessResponse.length}` + `摘要匹配数量: ${splitContents.length}` ); + // 计费 + pushSplitDataBill({ + isPay: !userApiKey && splitContents.length > 0, + userId: dataItem.userId, + type: 'abstract', + text: systemPrompt.content + dataItem.text + rawContent + }); } catch (error: any) { console.log('error: 生成摘要错误', dataItem?._id); console.log('response:', error); diff --git a/src/service/events/generateQA.ts b/src/service/events/generateQA.ts index 387348cc9..d6b3d7555 100644 --- a/src/service/events/generateQA.ts +++ b/src/service/events/generateQA.ts @@ -12,7 +12,7 @@ export async function generateQA(next = false): Promise { const systemPrompt: ChatCompletionRequestMessage = { role: 'system', - content: `总结助手。我会向你发送一段长文本,请从中总结出5至15个问题和答案,答案请尽量详细,请按以下格式返回: "Q1:"\n"A1:"\n"Q2:"\n"A2:"\n` + content: `总结助手。我会向你发送一段长文本,请从中总结出5至15个问题和答案,答案请尽量详细,请按以下格式返回: Q1:\nA1:\nQ2:\nA2:\n` }; let dataItem: DataItemSchema | null = null; @@ -58,61 +58,68 @@ export async function generateQA(next = false): Promise { const chatAPI = getOpenAIApi(userApiKey || systemKey); // 请求 chatgpt 获取回答 const response = await Promise.allSettled( - [0, 0.5, 0.8].map((temperature) => - chatAPI.createChatCompletion( - { - model: ChatModelNameEnum.GPT35, - temperature: temperature, - n: 1, - messages: [ - systemPrompt, + [0.2, 0.8].map( + (temperature) => + chatAPI + .createChatCompletion( { - role: 'user', - content: dataItem?.text || '' + model: ChatModelNameEnum.GPT35, + temperature: temperature, + n: 1, + messages: [ + systemPrompt, + { + role: 'user', + content: dataItem?.text || '' + } + ] + }, + { + timeout: 120000, + httpsAgent } - ] - }, - { - timeout: 120000, - httpsAgent - } - ) + ) + .then((res) => ({ + rawContent: res?.data.choices[0].message?.content || '', + result: splitText(res?.data.choices[0].message?.content || '') + })) // 从 content 中提取 QA ) ); // 过滤出成功的响应 - const successResponse = response.filter((item) => item.status === 'fulfilled'); - // 提取响应内容 - const rawContents: string[] = successResponse.map( - (item: any) => item?.value?.data.choices[0].message?.content || '' - ); - // 从 content 中提取 QA - const splitResponses = rawContents.map((content) => splitText(content)).flat(); + const successResponse: { + rawContent: string; + result: { q: string; a: string }[]; + }[] = response.filter((item) => item.status === 'fulfilled').map((item: any) => item.value); + + const rawContents = successResponse.map((item) => item.rawContent); + const results = successResponse.map((item) => item.result).flat(); + // 插入数据库,并修改状态 await DataItem.findByIdAndUpdate(dataItem._id, { status: 0, $push: { rawResponse: { - $each: rawContents + $each: successResponse.map((item) => item.rawContent) }, result: { - $each: splitResponses + $each: results } } }); - // 计费 - !userApiKey && - splitResponses.length > 0 && - pushSplitDataBill({ - userId: dataItem.userId, - type: 'QA', - text: systemPrompt.content + dataItem.text + rawContents.join('') - }); console.log( '生成QA成功,time:', `${(Date.now() - startTime) / 1000}s`, 'QA数量:', - splitResponses.length + results.length ); + + // 计费 + pushSplitDataBill({ + isPay: !userApiKey && results.length > 0, + userId: dataItem.userId, + type: 'QA', + text: systemPrompt.content + dataItem.text + rawContents.join('') + }); } catch (error: any) { console.log('error: 生成QA错误', dataItem?._id); console.log('response:', error?.response); diff --git a/src/service/events/pushBill.ts b/src/service/events/pushBill.ts index 99c1c938d..456bbaa2f 100644 --- a/src/service/events/pushBill.ts +++ b/src/service/events/pushBill.ts @@ -5,55 +5,58 @@ import { formatPrice } from '@/utils/user'; import type { DataType } from '@/types/data'; export const pushChatBill = async ({ + isPay, modelName, userId, chatId, text }: { + isPay: boolean; modelName: string; userId: string; chatId: string; text: string; }) => { - await connectToDatabase(); - let billId; try { - // 获取模型单价格 - const modelItem = modelList.find((item) => item.model === modelName); - const unitPrice = modelItem?.price || 5; - // 计算 token 数量 const tokens = encode(text); - // 计算价格 - const price = unitPrice * tokens.length; - console.log('chat bill'); - console.log('token len:', tokens.length); console.log('text len: ', text.length); - console.log('price: ', `${formatPrice(price)}元`); + console.log('token len:', tokens.length); - try { - // 插入 Bill 记录 - const res = await Bill.create({ - userId, - type: 'chat', - modelName, - chatId, - textLen: text.length, - tokenLen: tokens.length, - price - }); - billId = res._id; + if (isPay) { + await connectToDatabase(); - // 账号扣费 - await User.findByIdAndUpdate(userId, { - $inc: { balance: -price } - }); - } catch (error) { - console.log('创建账单失败:', error); - billId && Bill.findByIdAndDelete(billId); + // 获取模型单价格 + const modelItem = modelList.find((item) => item.model === modelName); + // 计算价格 + const unitPrice = modelItem?.price || 5; + const price = unitPrice * tokens.length; + console.log(`chat bill, price: ${formatPrice(price)}元`); + + try { + // 插入 Bill 记录 + const res = await Bill.create({ + userId, + type: 'chat', + modelName, + chatId, + textLen: text.length, + tokenLen: tokens.length, + price + }); + billId = res._id; + + // 账号扣费 + await User.findByIdAndUpdate(userId, { + $inc: { balance: -price } + }); + } catch (error) { + console.log('创建账单失败:', error); + billId && Bill.findByIdAndDelete(billId); + } } } catch (error) { console.log(error); @@ -61,10 +64,12 @@ export const pushChatBill = async ({ }; export const pushSplitDataBill = async ({ + isPay, userId, text, type }: { + isPay: boolean; userId: string; text: string; type: DataType; @@ -74,39 +79,41 @@ export const pushSplitDataBill = async ({ let billId; try { - // 获取模型单价格, 都是用 gpt35 拆分 - const modelItem = modelList.find((item) => item.model === ChatModelNameEnum.GPT35); - const unitPrice = modelItem?.price || 5; - // 计算 token 数量 const tokens = encode(text); - // 计算价格 - const price = unitPrice * tokens.length; - console.log('splitData bill'); - console.log('token len:', tokens.length); console.log('text len: ', text.length); - console.log('price: ', `${formatPrice(price)}元`); + console.log('token len:', tokens.length); - try { - // 插入 Bill 记录 - const res = await Bill.create({ - userId, - type, - modelName: ChatModelNameEnum.GPT35, - textLen: text.length, - tokenLen: tokens.length, - price - }); - billId = res._id; + if (isPay) { + try { + // 获取模型单价格, 都是用 gpt35 拆分 + const modelItem = modelList.find((item) => item.model === ChatModelNameEnum.GPT35); + const unitPrice = modelItem?.price || 5; + // 计算价格 + const price = unitPrice * tokens.length; - // 账号扣费 - await User.findByIdAndUpdate(userId, { - $inc: { balance: -price } - }); - } catch (error) { - console.log('创建账单失败:', error); - billId && Bill.findByIdAndDelete(billId); + console.log(`splitData bill, price: ${formatPrice(price)}元`); + + // 插入 Bill 记录 + const res = await Bill.create({ + userId, + type, + modelName: ChatModelNameEnum.GPT35, + textLen: text.length, + tokenLen: tokens.length, + price + }); + billId = res._id; + + // 账号扣费 + await User.findByIdAndUpdate(userId, { + $inc: { balance: -price } + }); + } catch (error) { + console.log('创建账单失败:', error); + billId && Bill.findByIdAndDelete(billId); + } } } catch (error) { console.log(error); diff --git a/src/service/response.ts b/src/service/response.ts index edaab5af4..e1e92b74e 100644 --- a/src/service/response.ts +++ b/src/service/response.ts @@ -28,10 +28,10 @@ export const jsonRes = ( } else if (openaiError[error?.response?.statusText]) { msg = openaiError[error.response.statusText]; } - error?.response && console.log('chat err:', error?.response); console.log('error->'); console.log('code:', error.code); console.log('statusText:', error?.response?.statusText); + console.log('data len:', error?.response?.config?.data.length); console.log('msg:', msg); }