feat(llm): 用量落库 + 只读汇总端点 + 面板用量小卡(契约 v0.64)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- model 层新增可选 UsageSink(nil ⇒ 逐字不变,既有用例零改动)
- 组合根注入 UsageWriter:有界队列 1024 + 单写者 + 批量事务(128/批、2s 兜底),
  队列满丢弃 + 限流 WARN,绝不阻塞模型调用;sink 挂 RuntimeLLM(热重载不断)
- 迁移 0017:表 llm_usage(13 列,session_id 可空)+ idx_created_at + idx_session_id
- 新端点 GET /api/v1/admin/llm/usage(owner|admin 读;缺省近 24h、上限 90 天、
  超限 400 不静默裁剪;hitRate = cacheHit/(cacheHit+cacheMiss),分母 0 ⇒ 0;
  绝不含凭据与正文;未接线/查库失败 ⇒ 500 usage_unavailable)
- LLM_USAGE_RETENTION(默认 720h,≤0 = 关闭清理):启动清一次 + 每小时
- 面板 LLM 页「用量(近 24h)」小卡 + Docs 两份同步 v0.64
- 已知缺口(如实登记):session_id 恒 NULL,需 loop 侧在请求上打标,留列后接
This commit is contained in:
AskaEth committed 2026-10-04 22:16:26 +08:00
1 parent 18381f65fd
commit be38651ba4
32 files changed
+2233 -44

No files matched your search

+15
View File
@@ -246,3 +246,18 @@ type RagStore interface {
// 不存在该文档时返回 knowledge.ErrDocumentNotFound。
DeleteDocument(ctx context.Context, id string) error
}
// LlmUsageStore 是 LLM 用量汇总的**只读**出口(切片 U1,
// GET /api/v1/admin/llm/usage)。*runtime/model.UsageReader 是生产
// 实现:它在一块时间窗内聚合 `llm_usage` 表的 token 计数与缓存两档,
// 按用途与模型分解。
//
// 汇总里**没有任何凭据、也没有消息正文** —— 那些东西根本没进
// `llm_usage` 表(写入侧 model.UsageWriter 的样本里就没有这些字段)。
// 为 nil 时端点诚实作答 500 usage_unavailable,绝不回一份全 0
// 的假汇总。
type LlmUsageStore interface {
// Summary 聚合 q 描述的时间窗与用途过滤。q 的时间窗由
// handler 校验并补齐(缺省近 24h、上限 90 天)。
Summary(ctx context.Context, q model.UsageQuery) (model.UsageSummary, error)
}