From 358c4716f98a68b91effa898762786c2a991569d Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Fri, 14 Jul 2023 10:05:29 +0800 Subject: [PATCH] feat: refresh max token --- client/src/api/app.ts | 4 +- client/src/constants/flow/ModuleTemplate.ts | 14 +++-- .../app/data/{tokenUsage.ts => totalUsage.ts} | 5 +- .../pages/api/openapi/v1/chat/completions.ts | 12 +++-- .../Charts/{TokenUsage.tsx => TotalUsage.tsx} | 13 ++--- .../pages/app/detail/components/Settings.tsx | 10 ++-- .../components/edit/components/NodeChat.tsx | 52 ++++++++++++++++++- 7 files changed, 83 insertions(+), 27 deletions(-) rename client/src/pages/api/app/data/{tokenUsage.ts => totalUsage.ts} (89%) rename client/src/pages/app/detail/components/Charts/{TokenUsage.tsx => TotalUsage.tsx} (91%) diff --git a/client/src/api/app.ts b/client/src/api/app.ts index deb4c7b2b..511a3fd26 100644 --- a/client/src/api/app.ts +++ b/client/src/api/app.ts @@ -45,8 +45,8 @@ export const triggerModelCollection = (appId: string) => POST(`/app/share/collection?appId=${appId}`); // ====================== data -export const getTokenUsage = (data: { appId: string }) => - POST<{ tokenLen: number; date: Date }[]>(`/app/data/tokenUsage`, { +export const getAppTotalUsage = (data: { appId: string }) => + POST<{ total: number; date: Date }[]>(`/app/data/totalUsage`, { ...data, start: addDays(new Date(), -7), end: new Date() diff --git a/client/src/constants/flow/ModuleTemplate.ts b/client/src/constants/flow/ModuleTemplate.ts index 5bf0bad98..91adde104 100644 --- a/client/src/constants/flow/ModuleTemplate.ts +++ b/client/src/constants/flow/ModuleTemplate.ts @@ -84,6 +84,7 @@ export const HistoryModule: AppModuleTemplateItemType = { ] }; +const defaultModel = chatModelList[0]; export const ChatModule: AppModuleTemplateItemType = { logo: '/imgs/module/AI.png', name: 'AI 对话', @@ -94,9 +95,9 @@ export const ChatModule: AppModuleTemplateItemType = { inputs: [ { key: 'model', - type: FlowInputItemTypeEnum.select, + type: FlowInputItemTypeEnum.custom, label: '对话模型', - value: chatModelList[0]?.model, + value: defaultModel?.model, list: chatModelList.map((item) => ({ label: item.name, value: item.model })) }, { @@ -116,13 +117,16 @@ export const ChatModule: AppModuleTemplateItemType = { key: 'maxToken', type: FlowInputItemTypeEnum.slider, label: '回复上限', - value: 3000, + value: defaultModel ? defaultModel.contextMaxToken / 2 : 2000, min: 0, - max: 4000, + max: defaultModel?.contextMaxToken || 4000, step: 50, markList: [ { label: '0', value: 0 }, - { label: '4000', value: 4000 } + { + label: `${defaultModel?.contextMaxToken || 4000}`, + value: defaultModel?.contextMaxToken || 4000 + } ] }, { diff --git a/client/src/pages/api/app/data/tokenUsage.ts b/client/src/pages/api/app/data/totalUsage.ts similarity index 89% rename from client/src/pages/api/app/data/tokenUsage.ts rename to client/src/pages/api/app/data/totalUsage.ts index 85c8a9576..b34cbe19c 100644 --- a/client/src/pages/api/app/data/tokenUsage.ts +++ b/client/src/pages/api/app/data/totalUsage.ts @@ -2,7 +2,6 @@ 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 { ChatHistoryItemType } from '@/types/chat'; import { Types } from 'mongoose'; /* get one app chat history content number. */ @@ -28,14 +27,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) month: { $month: '$time' }, day: { $dayOfMonth: '$time' } }, - tokenLen: { $sum: '$tokenLen' } // 对tokenLen的值求和 + total: { $sum: '$total' } } }, { $project: { _id: 0, date: { $dateFromParts: { year: '$_id.year', month: '$_id.month', day: '$_id.day' } }, - tokenLen: 1 + total: 1 } }, { $sort: { date: 1 } } diff --git a/client/src/pages/api/openapi/v1/chat/completions.ts b/client/src/pages/api/openapi/v1/chat/completions.ts index 838eb86bd..f3b22f10c 100644 --- a/client/src/pages/api/openapi/v1/chat/completions.ts +++ b/client/src/pages/api/openapi/v1/chat/completions.ts @@ -15,7 +15,7 @@ import { Types } from 'mongoose'; import { moduleFetch } from '@/service/api/request'; import { AppModuleItemType, RunningModuleItemType } from '@/types/app'; import { FlowInputItemTypeEnum } from '@/constants/flow'; -import { finishTaskBill, createTaskBill } from '@/service/events/pushBill'; +import { finishTaskBill, createTaskBill, delTaskBill } from '@/service/events/pushBill'; import { BillSourceEnum } from '@/constants/user'; export type MessageItemType = ChatCompletionRequestMessage & { _id?: string }; @@ -56,6 +56,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex variables = {} } = req.body as Props; + let billId = ''; + try { if (!messages) { throw new Error('Prams Error'); @@ -108,11 +110,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex res.setHeader('newHistoryId', String(newHistoryId)); } - const billId = await createTaskBill({ + billId = await createTaskBill({ userId, appName: app.name, appId, - source: BillSourceEnum.fastgpt + source: authType === 'apikey' ? BillSourceEnum.api : BillSourceEnum.fastgpt }); /* start process */ @@ -125,7 +127,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex userChatInput: prompt.value }, stream, - billId: '' + billId }); // save chat @@ -184,6 +186,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex billId }); } catch (err: any) { + delTaskBill(billId); + if (stream) { res.status(500); sseErrRes(res, err); diff --git a/client/src/pages/app/detail/components/Charts/TokenUsage.tsx b/client/src/pages/app/detail/components/Charts/TotalUsage.tsx similarity index 91% rename from client/src/pages/app/detail/components/Charts/TokenUsage.tsx rename to client/src/pages/app/detail/components/Charts/TotalUsage.tsx index 4b91eccd8..eee601074 100644 --- a/client/src/pages/app/detail/components/Charts/TokenUsage.tsx +++ b/client/src/pages/app/detail/components/Charts/TotalUsage.tsx @@ -1,9 +1,10 @@ import React, { useEffect, useMemo, useRef } from 'react'; import * as echarts from 'echarts'; import { useGlobalStore } from '@/store/global'; -import { getTokenUsage } from '@/api/app'; +import { getAppTotalUsage } from '@/api/app'; import { useQuery } from '@tanstack/react-query'; import dayjs from 'dayjs'; +import { formatPrice } from '@/utils/user'; const map = { blue: { @@ -98,7 +99,7 @@ const TokenUsage = ({ appId }: { appId: string }) => { const Dom = useRef(null); const myChart = useRef(); - const { data = [] } = useQuery(['init'], () => getTokenUsage({ appId })); + const { data = [] } = useQuery(['init'], () => getAppTotalUsage({ appId })); const option = useMemo( () => ({ @@ -110,7 +111,7 @@ const TokenUsage = ({ appId }: { appId: string }) => { }, yAxis: { type: 'value', - max: Math.max(...data.map((item) => item.tokenLen)), + max: Math.max(...data.map((item) => item.total)), min: 0 }, grid: { @@ -132,14 +133,14 @@ const TokenUsage = ({ appId }: { appId: string }) => { return `
${dayjs(data.axisValue).format('YYYY/MM/DD')}
-
${((e[0]?.value || 0) / 1000).toFixed(2)}k Tokens
+
${formatPrice(e[0]?.value || 0)}元
`; } }, series: [ { - data: data.map((item) => item.tokenLen), + data: data.map((item) => item.total), type: 'line', showSymbol: true, animationDuration: 300, @@ -170,7 +171,7 @@ const TokenUsage = ({ appId }: { appId: string }) => { if (!Dom.current || myChart?.current?.getOption()) return; myChart.current = echarts.init(Dom.current); myChart.current && myChart.current.setOption(option); - }, [Dom]); + }, []); // data changed, update useEffect(() => { diff --git a/client/src/pages/app/detail/components/Settings.tsx b/client/src/pages/app/detail/components/Settings.tsx index c4e32605d..8ce8ac6bf 100644 --- a/client/src/pages/app/detail/components/Settings.tsx +++ b/client/src/pages/app/detail/components/Settings.tsx @@ -14,8 +14,8 @@ import Avatar from '@/components/Avatar'; import MyIcon from '@/components/Icon'; const InfoModal = dynamic(() => import('./InfoModal')); -const TokenUsage = dynamic(() => import('./Charts/TokenUsage')); -const AppEdit = dynamic(() => import('./edit')); +const TotalUsage = dynamic(() => import('./Charts/TotalUsage'), { ssr: false }); +const AppEdit = dynamic(() => import('./edit'), { ssr: false }); import styles from '../../list/index.module.scss'; const Settings = ({ appId }: { appId: string }) => { @@ -143,10 +143,10 @@ const Settings = ({ appId }: { appId: string }) => { - 近 7 日 Tokens 消耗 + 近 7 日消费 - - + + diff --git a/client/src/pages/app/detail/components/edit/components/NodeChat.tsx b/client/src/pages/app/detail/components/edit/components/NodeChat.tsx index 50e758ff6..b30761dd4 100644 --- a/client/src/pages/app/detail/components/edit/components/NodeChat.tsx +++ b/client/src/pages/app/detail/components/edit/components/NodeChat.tsx @@ -7,6 +7,8 @@ import Container from './modules/Container'; import RenderInput from './render/RenderInput'; import RenderOutput from './render/RenderOutput'; import { FlowOutputItemTypeEnum } from '@/constants/flow'; +import MySelect from '@/components/Select'; +import { chatModelList } from '@/store/static'; const NodeChat = ({ data: { moduleId, inputs, outputs, onChangeNode, ...props } @@ -15,11 +17,57 @@ const NodeChat = ({ () => outputs.filter((item) => item.type !== FlowOutputItemTypeEnum.hidden).length, [outputs] ); + return ( - + - + ( + { + onChangeNode({ + moduleId, + key: inputItem.key, + value: e + }); + // update max tokens + const model = chatModelList.find((item) => item.model === e); + if (!model) return; + + onChangeNode({ + moduleId, + key: 'maxToken', + valueKey: 'markList', + value: [ + { label: '0', value: 0 }, + { label: `${model.contextMaxToken}`, value: model.contextMaxToken } + ] + }); + onChangeNode({ + moduleId, + key: 'maxToken', + valueKey: 'max', + value: model.contextMaxToken + }); + onChangeNode({ + moduleId, + key: 'maxToken', + valueKey: 'value', + value: model.contextMaxToken / 2 + }); + }} + /> + ) + }} + /> {outputsLen > 0 && ( <>