feat: logs cache field (#2920)

* feat: logs cache field

* feat: logs cache field

* feat: logs cache field
This commit is contained in:
Seefs
2026-02-11 21:50:39 +08:00
committed by GitHub
parent c7804fef69
commit 48ec1faffe
7 changed files with 115 additions and 8 deletions

View File

@@ -286,6 +286,44 @@ function renderModelName(record, copyText, t) {
}
}
function toTokenNumber(value) {
const parsed = Number(value);
if (!Number.isFinite(parsed) || parsed <= 0) {
return 0;
}
return parsed;
}
function formatTokenCount(value) {
return toTokenNumber(value).toLocaleString();
}
function getPromptCacheSummary(other) {
if (!other || typeof other !== 'object') {
return null;
}
const cacheReadTokens = toTokenNumber(other.cache_tokens);
const cacheCreationTokens = toTokenNumber(other.cache_creation_tokens);
const cacheCreationTokens5m = toTokenNumber(other.cache_creation_tokens_5m);
const cacheCreationTokens1h = toTokenNumber(other.cache_creation_tokens_1h);
const hasSplitCacheCreation =
cacheCreationTokens5m > 0 || cacheCreationTokens1h > 0;
const cacheWriteTokens = hasSplitCacheCreation
? cacheCreationTokens5m + cacheCreationTokens1h
: cacheCreationTokens;
if (cacheReadTokens <= 0 && cacheWriteTokens <= 0) {
return null;
}
return {
cacheReadTokens,
cacheWriteTokens,
};
}
export const getLogsColumns = ({
t,
COLUMN_KEYS,
@@ -524,11 +562,56 @@ export const getLogsColumns = ({
},
{
key: COLUMN_KEYS.PROMPT,
title: t('输入'),
title: (
<div className='flex items-center gap-1'>
{t('输入')}
<Tooltip
content={t(
'根据 Anthropic 协定,/v1/messages 的输入 tokens 仅统计非缓存输入,不包含缓存读取与缓存写入 tokens。',
)}
>
<IconHelpCircle className='text-gray-400 cursor-help' />
</Tooltip>
</div>
),
dataIndex: 'prompt_tokens',
render: (text, record, index) => {
const other = getLogOther(record.other);
const cacheSummary = getPromptCacheSummary(other);
const hasCacheRead = (cacheSummary?.cacheReadTokens || 0) > 0;
const hasCacheWrite = (cacheSummary?.cacheWriteTokens || 0) > 0;
let cacheText = '';
if (hasCacheRead && hasCacheWrite) {
cacheText = `${t('缓存读')} ${formatTokenCount(cacheSummary.cacheReadTokens)} · ${t('写')} ${formatTokenCount(cacheSummary.cacheWriteTokens)}`;
} else if (hasCacheRead) {
cacheText = `${t('缓存读')} ${formatTokenCount(cacheSummary.cacheReadTokens)}`;
} else if (hasCacheWrite) {
cacheText = `${t('缓存写')} ${formatTokenCount(cacheSummary.cacheWriteTokens)}`;
}
return record.type === 0 || record.type === 2 || record.type === 5 ? (
<>{<span> {text} </span>}</>
<div
style={{
display: 'inline-flex',
flexDirection: 'column',
alignItems: 'flex-start',
lineHeight: 1.2,
}}
>
<span>{text}</span>
{cacheText ? (
<span
style={{
marginTop: 2,
fontSize: 11,
color: 'var(--semi-color-text-2)',
whiteSpace: 'nowrap',
}}
>
{cacheText}
</span>
) : null}
</div>
) : (
<></>
);