Skip to content

Commit 337e965

Browse files
author
Marvin Zhang
committed
feat: enhance token usage display in ChatMessage component
- Added computed properties to display token usage details, including prompt, completion, and total tokens. - Implemented formatting for token counts with comma separators for better readability. - Updated internationalization files to include new labels for token usage. - Refactored styles in ChatMessage to accommodate token usage display, improving user experience.
1 parent 252afff commit 337e965

File tree

6 files changed

+93
-8
lines changed

6 files changed

+93
-8
lines changed

src/components/core/ai/AssistantConsole.vue

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
<script setup lang="ts">
2-
import { computed, onBeforeMount, reactive, ref, watch } from 'vue';
2+
import { onBeforeMount, ref, watch } from 'vue';
33
import { useI18n } from 'vue-i18n';
44
import { ClChatInput } from '@/components';
5-
import useRequest from '@/services/request';
6-
import { getRequestBaseUrl } from '@/utils';
75
import { debounce } from 'lodash';
8-
import { ElMessage } from 'element-plus';
9-
import { AxiosError } from 'axios';
106
import { useRouter } from 'vue-router';
117
import useAssistantConsole from './useAssistantConsole';
128
@@ -19,12 +15,10 @@ const emit = defineEmits<{
1915
}>();
2016
2117
const { t } = useI18n();
22-
const { get } = useRequest();
2318
2419
const router = useRouter();
2520
2621
const {
27-
currentConversation,
2822
currentConversationId,
2923
conversations,
3024
chatHistory,

src/components/ui/chat/ChatMessage.vue

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { useI18n } from 'vue-i18n';
33
import markdownit from 'markdown-it';
44
import hljs from 'highlight.js';
5-
import { computed, ref, watch, onUnmounted } from 'vue';
5+
import { computed, ref, watch } from 'vue';
66
import 'highlight.js/styles/github.css';
77
88
const { t } = useI18n();
@@ -66,6 +66,20 @@ const filteredContents = computed<ChatMessageContent[]>(() => {
6666
return message.contents?.filter(content => !content.hidden) || [];
6767
});
6868
69+
// Compute token usage display
70+
const hasTokenUsage = computed(() => {
71+
const { message } = props;
72+
return message.usage &&
73+
(message.usage.total_tokens ||
74+
message.usage.prompt_tokens ||
75+
message.usage.completion_tokens);
76+
});
77+
78+
// Format token count with comma separators
79+
const formatTokenCount = (count?: number): string => {
80+
return count ? count.toLocaleString() : '0';
81+
};
82+
6983
defineOptions({ name: 'ClChatMessage' });
7084
</script>
7185

@@ -102,6 +116,35 @@ defineOptions({ name: 'ClChatMessage' });
102116
</div>
103117

104118
<div class="message-footer">
119+
<!-- Token usage display -->
120+
<el-popover
121+
v-if="hasTokenUsage && !message.isStreaming && message.role === 'assistant'"
122+
placement="top"
123+
trigger="hover"
124+
:width="220"
125+
popper-class="token-usage-popover"
126+
>
127+
<template #reference>
128+
<span class="token-usage">
129+
{{ formatTokenCount(message.usage?.total_tokens) }} {{ t('components.ai.chatbot.tokens') }}
130+
</span>
131+
</template>
132+
<div class="token-usage-details">
133+
<div class="token-usage-row">
134+
<span>{{ t('components.ai.chatbot.promptTokens') }}:</span>
135+
<span>{{ formatTokenCount(message.usage?.prompt_tokens) }}</span>
136+
</div>
137+
<div class="token-usage-row">
138+
<span>{{ t('components.ai.chatbot.completionTokens') }}:</span>
139+
<span>{{ formatTokenCount(message.usage?.completion_tokens) }}</span>
140+
</div>
141+
<div class="token-usage-row total">
142+
<span>{{ t('components.ai.chatbot.totalTokens') }}:</span>
143+
<span>{{ formatTokenCount(message.usage?.total_tokens) }}</span>
144+
</div>
145+
</div>
146+
</el-popover>
147+
105148
<!-- Show 'Generating...' for streaming messages -->
106149
<template v-if="message.isStreaming">
107150
<cl-loading-text
@@ -328,6 +371,9 @@ defineOptions({ name: 'ClChatMessage' });
328371
font-size: 10px;
329372
opacity: 0.7;
330373
margin-top: 6px;
374+
display: flex;
375+
justify-content: space-between;
376+
align-items: center;
331377
}
332378
333379
.message-container.user .message-content {
@@ -357,6 +403,31 @@ defineOptions({ name: 'ClChatMessage' });
357403
color: var(--el-color-primary);
358404
}
359405
406+
/* Token usage styles */
407+
.token-usage {
408+
font-size: 10px;
409+
cursor: pointer;
410+
color: var(--el-color-info);
411+
margin-right: 8px;
412+
}
413+
414+
.token-usage-details {
415+
font-size: 12px;
416+
}
417+
418+
.token-usage-row {
419+
display: flex;
420+
justify-content: space-between;
421+
margin-bottom: 4px;
422+
}
423+
424+
.token-usage-row.total {
425+
margin-top: 4px;
426+
border-top: 1px solid var(--el-border-color-lighter);
427+
padding-top: 4px;
428+
font-weight: bold;
429+
}
430+
360431
@keyframes loadingDots {
361432
to {
362433
width: 1.25em;

src/i18n/lang/en/components/ai.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ const ai: LangAi = {
3131
tooltip:
3232
"You haven't configured any models yet. Add a model to get started.",
3333
},
34+
tokens: 'Tokens',
35+
promptTokens: 'Prompt Tokens',
36+
completionTokens: 'Completion Tokens',
37+
totalTokens: 'Total Tokens',
3438
},
3539
};
3640

src/i18n/lang/zh/components/ai.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ const ai: LangAi = {
3030
label: '添加模型',
3131
tooltip: '您还没有配置任何模型。添加一个模型开始聊天',
3232
},
33+
tokens: '词元数',
34+
promptTokens: '输入词元数',
35+
completionTokens: '输出词元数',
36+
totalTokens: '总词元数',
3337
},
3438
};
3539

src/interfaces/i18n/components/ai.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ export declare global {
3131
label: string;
3232
tooltip: string;
3333
};
34+
tokens: string;
35+
promptTokens: string;
36+
completionTokens: string;
37+
totalTokens: string;
3438
};
3539
}
3640
}

src/interfaces/models/llm.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export declare global {
4444
metadata?: Record<string, any>;
4545
status: ChatMessageStatus;
4646
error?: string;
47+
usage?: ChatMessageUsage;
4748

4849
// Frontend UI-specific properties
4950
timestamp?: Date;
@@ -61,11 +62,18 @@ export declare global {
6162
action?: string;
6263
action_status?: ChatMessageActionStatus;
6364
hidden?: boolean;
65+
usage?: ChatMessageUsage;
6466

6567
// Frontend UI-specific properties
6668
isStreaming?: boolean;
6769
}
6870

71+
interface ChatMessageUsage {
72+
prompt_tokens?: number;
73+
completion_tokens?: number;
74+
total_tokens?: number;
75+
}
76+
6977
type ChatConversationStatus = 'active' | 'archived' | 'deleted';
7078

7179
interface ChatConversation extends BaseModel {

0 commit comments

Comments
 (0)