mirror of
https://github.com/langgenius/dify.git
synced 2026-04-05 20:22:39 +08:00
feat: dashboard add tps chart (#706)
Co-authored-by: John Wang <takatost@gmail.com>
This commit is contained in:
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import useSWR from 'swr'
|
||||
import { fetchAppDetail } from '@/service/apps'
|
||||
import type { PeriodParams } from '@/app/components/app/overview/appChart'
|
||||
import { AvgResponseTime, AvgSessionInteractions, ConversationsChart, CostChart, EndUsersChart, UserSatisfactionRate } from '@/app/components/app/overview/appChart'
|
||||
import { AvgResponseTime, AvgSessionInteractions, ConversationsChart, CostChart, EndUsersChart, TokenPerSecond, UserSatisfactionRate } from '@/app/components/app/overview/appChart'
|
||||
import type { Item } from '@/app/components/base/select'
|
||||
import { SimpleSelect } from '@/app/components/base/select'
|
||||
import { TIME_PERIOD_LIST } from '@/app/components/app/log/filter'
|
||||
@@ -65,10 +65,17 @@ export default function ChartView({ appId }: IChartViewProps) {
|
||||
)}
|
||||
</div>
|
||||
<div className='flex-1 ml-3'>
|
||||
<UserSatisfactionRate period={period} id={appId} />
|
||||
<TokenPerSecond period={period} id={appId} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex flex-row w-full mb-6'>
|
||||
<div className='flex-1 ml-3'>
|
||||
<UserSatisfactionRate period={period} id={appId} />
|
||||
</div>
|
||||
<div className='flex-1 ml-3'>
|
||||
<CostChart period={period} id={appId} />
|
||||
</div>
|
||||
</div>
|
||||
<CostChart period={period} id={appId} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
} from '@heroicons/react/24/outline'
|
||||
import Tooltip from '../base/tooltip'
|
||||
import AppIcon from '../base/app-icon'
|
||||
|
||||
const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'
|
||||
|
||||
export function randomString(length: number) {
|
||||
@@ -21,6 +20,7 @@ export type IAppBasicProps = {
|
||||
type: string | React.ReactNode
|
||||
hoverTip?: string
|
||||
textStyle?: { main?: string; extra?: string }
|
||||
isExtraInLine?: boolean
|
||||
}
|
||||
|
||||
const ApiSvg = <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@@ -61,7 +61,7 @@ const ICON_MAP = {
|
||||
notion: <AppIcon innerIcon={NotionSvg} className='!border-[0.5px] !border-indigo-100 !bg-white' />,
|
||||
}
|
||||
|
||||
export default function AppBasic({ icon, icon_background, name, type, hoverTip, textStyle, iconType = 'app' }: IAppBasicProps) {
|
||||
export default function AppBasic({ icon, icon_background, name, type, hoverTip, textStyle, iconType = 'app', isExtraInLine }: IAppBasicProps) {
|
||||
return (
|
||||
<div className="flex items-start">
|
||||
{icon && icon_background && iconType === 'app' && (
|
||||
|
||||
@@ -231,6 +231,7 @@ const Chart: React.FC<IChartProps> = ({
|
||||
</div>
|
||||
<div className='mb-4'>
|
||||
<Basic
|
||||
isExtraInLine={CHART_TYPE_CONFIG[chartType].showTokens}
|
||||
name={chartType !== 'costs' ? (sumData.toLocaleString() + unit) : `${sumData < 1000 ? sumData : (`${formatNumber(Math.round(sumData / 1000))}k`)}`}
|
||||
type={!CHART_TYPE_CONFIG[chartType].showTokens
|
||||
? ''
|
||||
@@ -316,6 +317,23 @@ export const AvgResponseTime: FC<IBizChartProps> = ({ id, period }) => {
|
||||
/>
|
||||
}
|
||||
|
||||
export const TokenPerSecond: FC<IBizChartProps> = ({ id, period }) => {
|
||||
const { t } = useTranslation()
|
||||
const { data: response } = useSWR({ url: `/apps/${id}/statistics/tokens-per-second`, params: period.query }, getAppStatistics)
|
||||
if (!response)
|
||||
return <Loading />
|
||||
const noDataFlag = !response.data || response.data.length === 0
|
||||
return <Chart
|
||||
basicInfo={{ title: t('appOverview.analysis.tps.title'), explanation: t('appOverview.analysis.tps.explanation'), timePeriod: period.name }}
|
||||
chartData={!noDataFlag ? response : { data: getDefaultChartData({ ...(period.query ?? defaultPeriod), key: 'tps' }) } as any}
|
||||
valueKey='tps'
|
||||
chartType='conversations'
|
||||
isAvg
|
||||
unit={t('appOverview.analysis.tokenPS') as string}
|
||||
{...(noDataFlag && { yMax: 100 })}
|
||||
/>
|
||||
}
|
||||
|
||||
export const UserSatisfactionRate: FC<IBizChartProps> = ({ id, period }) => {
|
||||
const { t } = useTranslation()
|
||||
const { data: response } = useSWR({ url: `/apps/${id}/statistics/user-satisfaction-rate`, params: period.query }, getAppStatistics)
|
||||
|
||||
@@ -81,6 +81,7 @@ const translation = {
|
||||
analysis: {
|
||||
title: 'Analysis',
|
||||
ms: 'ms',
|
||||
tokenPS: 'Token/s',
|
||||
totalMessages: {
|
||||
title: 'Total Messages',
|
||||
explanation: 'Daily AI interactions count; prompt engineering/debugging excluded.',
|
||||
@@ -106,6 +107,10 @@ const translation = {
|
||||
title: 'Avg. Response Time',
|
||||
explanation: 'Time (ms) for AI to process/respond; for text-based apps.',
|
||||
},
|
||||
tps: {
|
||||
title: 'Token Output Speed',
|
||||
explanation: 'Measure the performance of the LLM. Count the Tokens output speed of LLM from the beginning of the request to the completion of the output.',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ const translation = {
|
||||
analysis: {
|
||||
title: '分析',
|
||||
ms: '毫秒',
|
||||
tokenPS: 'Token/秒',
|
||||
totalMessages: {
|
||||
title: '全部消息数',
|
||||
explanation: '反映 AI 每天的互动总次数,每回答用户一个问题算一条 Message。提示词编排和调试的消息不计入。',
|
||||
@@ -106,6 +107,10 @@ const translation = {
|
||||
title: '平均响应时间',
|
||||
explanation: '衡量 AI 应用处理和回复用户请求所花费的平均时间,单位为毫秒,反映性能和用户体验。仅在文本型应用提供。',
|
||||
},
|
||||
tps: {
|
||||
title: 'Token 输出速度',
|
||||
explanation: '衡量 LLM 的性能。统计 LLM 从请求开始到输出完毕这段期间的 Tokens 输出速度。',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user