+ {header}
+ {usage.error ? (
+ 刷新失败,下方仍是上次成功读取的用量:{usage.error}
+ ) : null}
+
+
+
+ 0
+ ? `命中 ${formatTokens(totals.cacheHit)} / 未命中 ${formatTokens(totals.cacheMiss)} token`
+ : "本窗口没有输入侧缓存明细(不是 0% 命中)"
+ }
+ />
+
+
+ 窗口 {formatWindow(window.since, window.until)}
+ {window.purpose ? ` · 用途过滤 ${window.purpose}` : ""}
+ {usage.data.byModel.length > 0
+ ? ` · 模型 ${usage.data.byModel.map((m) => `${m.model} ${m.calls} 次`).join(",")}`
+ : ""}
+
+
+ 每次成功模型调用都会把一条**非敏感**用量样本(token 计数 / 缓存两档 / 模型名 / 用途 / 耗时)异步落进本机
+ `llm_usage` 表:写入走有界队列 + 单写者批量事务,队列满即丢弃并告警,**绝不阻塞模型调用**;**凭据与消息正文绝不入库、绝不进日志**。
+ 命中率口径 = 命中 /(命中 + 未命中),分母为 0 时按 0 处理。
+
+
+ );
+}
diff --git a/frontend/web/src/lib/api.ts b/frontend/web/src/lib/api.ts
index ce41d7e..56dfe7b 100644
--- a/frontend/web/src/lib/api.ts
+++ b/frontend/web/src/lib/api.ts
@@ -75,6 +75,7 @@ export {
adminListRag,
adminListSessions,
adminListUsers,
+ adminLlmUsage,
adminMemorySearch,
adminPluginInstall,
adminPluginUninstall,
diff --git a/frontend/web/src/lib/api/admin.ts b/frontend/web/src/lib/api/admin.ts
index 6f17371..26fbda7 100644
--- a/frontend/web/src/lib/api/admin.ts
+++ b/frontend/web/src/lib/api/admin.ts
@@ -6,6 +6,7 @@ import type {
AdminLlmConfig,
AdminLlmProvider,
AdminLlmResetResult,
+ AdminLlmUsage,
AdminPluginRecord,
AdminRagHit,
AdminRagResponse,
@@ -100,6 +101,20 @@ export function adminGetLlmCatalog(opts: { refresh?: boolean } = {}): Promise