diff --git a/src/api/user.ts b/src/api/user.ts index 5971260c2..72fedb196 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -2,10 +2,9 @@ import { GET, POST, PUT } from './request'; import { createHashPassword, Obj2Query } from '@/utils/tools'; import { ResLogin, PromotionRecordType } from './response/user'; import { UserAuthTypeEnum } from '@/constants/common'; -import { UserType, UserUpdateParams } from '@/types/user'; +import { UserBillType, UserType, UserUpdateParams } from '@/types/user'; import type { PagingData, RequestPaging } from '@/types'; -import { BillSchema, PaySchema } from '@/types/mongoSchema'; -import { adaptBill } from '@/utils/adapt'; +import { PaySchema } from '@/types/mongoSchema'; export const sendAuthCode = ({ username, @@ -69,10 +68,7 @@ export const loginOut = () => GET('/user/loginout'); export const putUserInfo = (data: UserUpdateParams) => PUT('/user/update', data); export const getUserBills = (data: RequestPaging) => - GET>(`/user/getBill?${Obj2Query(data)}`).then((res) => ({ - ...res, - data: res.data.map((bill) => adaptBill(bill)) - })); + GET>(`/user/getBill?${Obj2Query(data)}`); export const getPayOrders = () => GET(`/user/getPayOrders`); diff --git a/src/constants/user.ts b/src/constants/user.ts index 67660938f..a1fd5289d 100644 --- a/src/constants/user.ts +++ b/src/constants/user.ts @@ -1,8 +1,7 @@ export enum BillTypeEnum { chat = 'chat', - splitData = 'splitData', + openapiChat = 'openapiChat', QA = 'QA', - abstract = 'abstract', vector = 'vector', return = 'return' } @@ -14,9 +13,8 @@ export enum PageTypeEnum { export const BillTypeMap: Record<`${BillTypeEnum}`, string> = { [BillTypeEnum.chat]: '对话', - [BillTypeEnum.splitData]: 'QA拆分', + [BillTypeEnum.openapiChat]: 'api 对话', [BillTypeEnum.QA]: 'QA拆分', - [BillTypeEnum.abstract]: '摘要总结', [BillTypeEnum.vector]: '索引生成', [BillTypeEnum.return]: '退款' }; diff --git a/src/hooks/useTabs.tsx b/src/hooks/useTabs.tsx deleted file mode 100644 index 89414f201..000000000 --- a/src/hooks/useTabs.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React, { useState, useCallback, useRef } from 'react'; - -export const useTabs = ({ - tabs = [] -}: { - tabs: { - id: string; - label: string; - }[]; -}) => { - const [activeTab, setActiveTab] = useState(tabs[0].id); - - return { - tabs, - activeTab, - setActiveTab - }; -}; diff --git a/src/pages/api/chat/chat.ts b/src/pages/api/chat/chat.ts index d472dcde5..5de8cfce2 100644 --- a/src/pages/api/chat/chat.ts +++ b/src/pages/api/chat/chat.ts @@ -9,6 +9,7 @@ import { pushChatBill } from '@/service/events/pushBill'; import { resStreamResponse } from '@/service/utils/chat'; import { searchKb } from '@/service/plugins/searchKb'; import { ChatRoleEnum } from '@/constants/chat'; +import { BillTypeEnum } from '@/constants/user'; /* 发送提示词 */ export default async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -108,7 +109,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) userId, chatId, textLen: finishMessages.map((item) => item.value).join('').length, - tokens: totalTokens + tokens: totalTokens, + type: BillTypeEnum.chat }); } catch (err: any) { if (step === 1) { diff --git a/src/pages/api/chat/shareChat/chat.ts b/src/pages/api/chat/shareChat/chat.ts index 4ce4403f0..17676897d 100644 --- a/src/pages/api/chat/shareChat/chat.ts +++ b/src/pages/api/chat/shareChat/chat.ts @@ -9,6 +9,7 @@ import { pushChatBill, updateShareChatBill } from '@/service/events/pushBill'; import { resStreamResponse } from '@/service/utils/chat'; import { searchKb } from '@/service/plugins/searchKb'; import { ChatRoleEnum } from '@/constants/chat'; +import { BillTypeEnum } from '@/constants/user'; /* 发送提示词 */ export default async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -98,7 +99,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) chatModel: model.chat.chatModel, userId, textLen: finishMessages.map((item) => item.value).join('').length, - tokens: totalTokens + tokens: totalTokens, + type: BillTypeEnum.chat }); updateShareChatBill({ shareId, diff --git a/src/pages/api/openapi/chat/chat.ts b/src/pages/api/openapi/chat/chat.ts index 9e10def36..64881fad4 100644 --- a/src/pages/api/openapi/chat/chat.ts +++ b/src/pages/api/openapi/chat/chat.ts @@ -9,6 +9,7 @@ import { pushChatBill } from '@/service/events/pushBill'; import { searchKb } from '@/service/plugins/searchKb'; import { ChatRoleEnum } from '@/constants/chat'; import { withNextCors } from '@/service/utils/tools'; +import { BillTypeEnum } from '@/constants/user'; /* 发送提示词 */ export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -45,7 +46,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex let startTime = Date.now(); /* 凭证校验 */ - const { userId } = await authUser({ req, authOpenApi: true }); + const { userId } = await authUser({ req }); const { model } = await authModel({ userId, @@ -74,7 +75,9 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex // search result is empty if (code === 201) { - return res.send(searchPrompts[0]?.value); + return isStream + ? res.send(searchPrompts[0]?.value) + : jsonRes(res, { data: searchPrompts[0]?.value }); } prompts.splice(prompts.length - 3, 0, ...searchPrompts); } else { @@ -129,7 +132,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex chatModel: model.chat.chatModel, userId, textLen, - tokens + tokens, + type: BillTypeEnum.openapiChat }); } catch (err: any) { if (step === 1) { diff --git a/src/pages/api/openapi/kb/delDataById.ts b/src/pages/api/openapi/kb/delDataById.ts index fcb7d086a..7cad054ab 100644 --- a/src/pages/api/openapi/kb/delDataById.ts +++ b/src/pages/api/openapi/kb/delDataById.ts @@ -15,7 +15,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex } // 凭证校验 - const { userId } = await authUser({ req, authToken: true }); + const { userId } = await authUser({ req }); await PgClient.delete('modelData', { where: [['user_id', userId], 'AND', ['id', dataId]] diff --git a/src/pages/api/openapi/kb/updateData.ts b/src/pages/api/openapi/kb/updateData.ts index 96860c36b..07db9f4a0 100644 --- a/src/pages/api/openapi/kb/updateData.ts +++ b/src/pages/api/openapi/kb/updateData.ts @@ -15,7 +15,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex } // 凭证校验 - const { userId } = await authUser({ req, authToken: true }); + const { userId } = await authUser({ req }); // 更新 pg 内容.仅修改a,不需要更新向量。 await PgClient.update('modelData', { diff --git a/src/pages/api/openapi/text/splitText.ts b/src/pages/api/openapi/text/splitText.ts index 15b3ecddc..8767bf440 100644 --- a/src/pages/api/openapi/text/splitText.ts +++ b/src/pages/api/openapi/text/splitText.ts @@ -22,7 +22,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex } await connectToDatabase(); - const { userId } = await authUser({ req, authToken: true }); + const { userId } = await authUser({ req }); // 验证是否是该用户的 model await authKb({ diff --git a/src/pages/api/user/getBill.ts b/src/pages/api/user/getBill.ts index b782b315d..8412af4f1 100644 --- a/src/pages/api/user/getBill.ts +++ b/src/pages/api/user/getBill.ts @@ -3,7 +3,7 @@ import type { NextApiRequest, NextApiResponse } from 'next'; import { jsonRes } from '@/service/response'; import { connectToDatabase, Bill } from '@/service/mongo'; import { authUser } from '@/service/utils/auth'; -import type { BillSchema } from '@/types/mongoSchema'; +import { adaptBill } from '@/utils/adapt'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { @@ -17,7 +17,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) await connectToDatabase(); // 根据 id 获取用户账单 - const bills = await Bill.find({ + const bills = await Bill.find({ userId }) .sort({ _id: -1 }) // 按照创建时间倒序排列 @@ -33,7 +33,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) data: { pageNum, pageSize, - data: bills, + data: bills.map(adaptBill), total } }); diff --git a/src/pages/number/components/BillTable.tsx b/src/pages/number/components/BillTable.tsx index cd0a2e499..d7bdc9b33 100644 --- a/src/pages/number/components/BillTable.tsx +++ b/src/pages/number/components/BillTable.tsx @@ -5,6 +5,7 @@ import { getUserBills } from '@/api/user'; import type { UserBillType } from '@/types/user'; import { usePagination } from '@/hooks/usePagination'; import { useLoading } from '@/hooks/useLoading'; +import dayjs from 'dayjs'; const BillTable = () => { const { Loading } = useLoading(); @@ -28,6 +29,7 @@ const BillTable = () => { 时间 类型 + 底层模型 内容长度 Tokens 长度 金额 @@ -36,8 +38,9 @@ const BillTable = () => { {bills.map((item) => ( - {item.time} - {BillTypeMap[item.type]} + {dayjs(item.time).format('YYYY/MM/DD HH:mm:ss')} + {BillTypeMap[item.type] || '-'} + {item.modelName} {item.textLen} {item.tokenLen} {item.price}元 diff --git a/src/service/events/generateQA.ts b/src/service/events/generateQA.ts index 1a8d80a1e..f59b2bea0 100644 --- a/src/service/events/generateQA.ts +++ b/src/service/events/generateQA.ts @@ -9,6 +9,7 @@ import { SplitDataSchema } from '@/types/mongoSchema'; import { modelServiceToolMap } from '../utils/chat'; import { ChatRoleEnum } from '@/constants/chat'; import { getErrText } from '@/utils/tools'; +import { BillTypeEnum } from '@/constants/user'; export async function generateQA(next = false): Promise { if (process.env.queueTask !== '1') { @@ -98,7 +99,7 @@ A2: pushSplitDataBill({ isPay: !userOpenAiKey && result.length > 0, userId: dataItem.userId, - type: 'QA', + type: BillTypeEnum.QA, textLen: responseMessages.map((item) => item.value).join('').length, totalTokens }); diff --git a/src/service/events/pushBill.ts b/src/service/events/pushBill.ts index 6dff3aa09..b63fbb589 100644 --- a/src/service/events/pushBill.ts +++ b/src/service/events/pushBill.ts @@ -8,7 +8,8 @@ export const pushChatBill = async ({ userId, chatId, textLen, - tokens + tokens, + type }: { isPay: boolean; chatModel: ChatModelType; @@ -16,6 +17,7 @@ export const pushChatBill = async ({ chatId?: '' | string; textLen: number; tokens: number; + type: BillTypeEnum.chat | BillTypeEnum.openapiChat; }) => { console.log(`chat generate success. text len: ${textLen}. token len: ${tokens}. pay:${isPay}`); if (!isPay) return; @@ -33,7 +35,7 @@ export const pushChatBill = async ({ // 插入 Bill 记录 const res = await Bill.create({ userId, - type: 'chat', + type, modelName: chatModel, chatId: chatId ? chatId : undefined, textLen, @@ -83,7 +85,7 @@ export const pushSplitDataBill = async ({ userId: string; totalTokens: number; textLen: number; - type: `${BillTypeEnum}`; + type: BillTypeEnum.QA; }) => { console.log( `splitData generate success. text len: ${textLen}. token len: ${totalTokens}. pay:${isPay}` diff --git a/src/service/models/bill.ts b/src/service/models/bill.ts index 2cb601f65..241e9addc 100644 --- a/src/service/models/bill.ts +++ b/src/service/models/bill.ts @@ -1,5 +1,5 @@ import { Schema, model, models, Model } from 'mongoose'; -import { ChatModelMap } from '@/constants/model'; +import { ChatModelMap, embeddingModel } from '@/constants/model'; import { BillSchema as BillType } from '@/types/mongoSchema'; import { BillTypeMap } from '@/constants/user'; @@ -16,7 +16,7 @@ const BillSchema = new Schema({ }, modelName: { type: String, - enum: [...Object.keys(ChatModelMap), 'text-embedding-ada-002'], + enum: [...Object.keys(ChatModelMap), embeddingModel], required: true }, chatId: { diff --git a/src/service/plugins/useSearch.ts b/src/service/plugins/useSearch.ts index baab72b9e..e00a0f520 100644 --- a/src/service/plugins/useSearch.ts +++ b/src/service/plugins/useSearch.ts @@ -1,35 +1,34 @@ import axios from 'axios'; -{/*Bing 搜索*/} +{ + /*Bing 搜索*/ +} const BingSearch = async (wait_val: string) => { - const response = await axios.post("newbing中转服务器", { - prompt: wait_val, + const response = await axios.post('newbing中转服务器', { + prompt: wait_val }); const result = response.data.result; return result; }; - -{/*google 搜索*/} +{ + /*google 搜索*/ +} const GoogleSearch = async (wait_val: string) => { - const response = await axios.get('https://www.googleapis.com/customsearch/v1', { params: { - key: google_api, + key: process.env.GOOGLE_KEY, q: wait_val, - cx: searchEngineId, + cx: process.env.searchEngineId, start: 1, num: 3, - dateRestrict: 'm[1]', //搜索结果限定为一个月内 - }, + dateRestrict: 'm[1]' //搜索结果限定为一个月内 + } }); const results = response.data.items; if (results !== null) { const result = results.map((item: { snippet: string }) => item.snippet).join('\n'); return result; } - } -export { - BingSearch, - GoogleSearch }; +export { BingSearch, GoogleSearch }; diff --git a/src/service/utils/auth.ts b/src/service/utils/auth.ts index 59faa3938..0c6d7d7d6 100644 --- a/src/service/utils/auth.ts +++ b/src/service/utils/auth.ts @@ -14,13 +14,11 @@ import { hashPassword } from '@/service/utils/tools'; /* uniform auth user */ export const authUser = async ({ req, - userId = '', authToken = false, authOpenApi = false, authRoot = false }: { req: NextApiRequest; - userId?: string; authToken?: boolean; authOpenApi?: boolean; authRoot?: boolean; @@ -68,17 +66,18 @@ export const authUser = async ({ return Promise.reject(error); } }; - const parseRootKey = async (rootKey?: string) => { - if (!rootKey || !process.env.ROOT_KEY || rootKey !== process.env.ROOT_KEY) { + const parseRootKey = async (rootKey?: string, userId?: string) => { + if (!rootKey || !userId || !process.env.ROOT_KEY || rootKey !== process.env.ROOT_KEY) { return Promise.reject(ERROR_ENUM.unAuthorization); } return userId; }; - const { cookie, apikey, rootkey } = (req.headers || {}) as { + const { cookie, apikey, rootkey, userid } = (req.headers || {}) as { cookie?: string; apikey?: string; rootkey?: string; + userid?: string; }; let uid = ''; @@ -88,13 +87,13 @@ export const authUser = async ({ } else if (authOpenApi) { uid = await parseOpenApiKey(apikey); } else if (authRoot) { - uid = await parseRootKey(rootkey); + uid = await parseRootKey(rootkey, userid); } else if (cookie) { uid = await parseCookie(cookie); } else if (apikey) { uid = await parseOpenApiKey(apikey); } else if (rootkey) { - uid = await parseRootKey(rootkey); + uid = await parseRootKey(rootkey, userid); } else { return Promise.reject(ERROR_ENUM.unAuthorization); } diff --git a/src/types/mongoSchema.d.ts b/src/types/mongoSchema.d.ts index a2f8de210..19623215b 100644 --- a/src/types/mongoSchema.d.ts +++ b/src/types/mongoSchema.d.ts @@ -3,9 +3,11 @@ import { ModelStatusEnum, ModelNameEnum, ModelVectorSearchModeEnum, - ChatModelType + ChatModelType, + EmbeddingModelType } from '@/constants/model'; import type { DataType } from './data'; +import { BillTypeEnum } from '@/constants/user'; export interface UserModelSchema { _id: string; @@ -89,7 +91,8 @@ export interface ChatPopulate extends ChatSchema { export interface BillSchema { _id: string; userId: string; - type: 'chat' | 'splitData' | 'return'; + type: `${BillTypeEnum}`; + modelName: ChatModelType | EmbeddingModelType; chatId: string; time: Date; textLen: number; diff --git a/src/types/user.d.ts b/src/types/user.d.ts index 5dbf74c4a..d36c618bf 100644 --- a/src/types/user.d.ts +++ b/src/types/user.d.ts @@ -1,3 +1,4 @@ +import type { BillSchema } from './mongoSchema'; export interface UserType { _id: string; username: string; @@ -17,11 +18,10 @@ export interface UserUpdateParams { export interface UserBillType { id: string; - time: string; - type: 'chat' | 'splitData' | 'return'; + time: Date; + modelName: BillSchema['modelName']; + type: BillSchema['type']; textLen: number; tokenLen: number; - userId: string; - chatId: string; price: number; } diff --git a/src/utils/adapt.ts b/src/utils/adapt.ts index 2f9c00b3f..1764ff787 100644 --- a/src/utils/adapt.ts +++ b/src/utils/adapt.ts @@ -7,9 +7,8 @@ export const adaptBill = (bill: BillSchema): UserBillType => { return { id: bill._id, type: bill.type, - userId: bill.userId, - chatId: bill.chatId, - time: dayjs(bill.time).format('YYYY/MM/DD HH:mm:ss'), + modelName: bill.modelName, + time: bill.time, textLen: bill.textLen, tokenLen: bill.tokenLen, price: formatPrice(bill.price)