优化: token分项显示(in/cache/out/reasoning)+ 详情面板 + base前置
token分项(各计费不同,不显 total):df-ai 解析 provider cache/reasoning(openai_compat prompt_cache_hit/miss/reasoning_tokens + anthropic cache_read/creation)+ TokenUsage 加字段(全构造点)+ AiMessage/AiCompleted/DB V39(ai_messages 加 cache_hit/miss/reasoning 列)+ message_repo 映射(持久化)+ 前端 MessageList 显 in·cache·out·reason(in=cache_miss 全价,reasoning 有才显)+ 点击 token 弹详情面板(完整 usage+缓存命中率+model)+ df-miniapp 同步 base前置(提升 prompt cache 命中率):chat.rs aug 拼 base 后(4处)+ knowledge_inject 知识拼 base 后(固定 base 前缀,cache 命中) 附修:replace_conversation 原 13 列 INSERT 丢消息级 token → 改 18 列
This commit is contained in:
@@ -152,9 +152,20 @@ export async function switchConversation(id: string) {
|
||||
// (V38 迁移后 push_assistant_message 落库的本轮 token),映射回 tokenUsage 供
|
||||
// MessageList.vue 渲染 in/out 计数。压缩/切会话后历史 assistant 消息 token 不丢。
|
||||
// 老消息 NULL → m.prompt_tokens==null → tokenUsage 不设(对齐 useAiEvents 实时态语义)。
|
||||
// 分项 token(2026-08-02):cache/reasoning 透传(V39 列),老消息无则 undefined 前端 fallback。
|
||||
tokenUsage: m.role === 'assistant' && m.prompt_tokens != null
|
||||
? { prompt: m.prompt_tokens, completion: m.completion_tokens ?? 0 }
|
||||
? {
|
||||
prompt: m.prompt_tokens,
|
||||
completion: m.completion_tokens ?? 0,
|
||||
cache_hit: m.prompt_cache_hit_tokens,
|
||||
cache_miss: m.prompt_cache_miss_tokens,
|
||||
reasoning: m.reasoning_tokens,
|
||||
}
|
||||
: undefined,
|
||||
// 分项 token 消息级字段(详情面板直接读 msg.xxx,与实时态 useAiEvents 写入一致)
|
||||
prompt_cache_hit_tokens: m.prompt_cache_hit_tokens,
|
||||
prompt_cache_miss_tokens: m.prompt_cache_miss_tokens,
|
||||
reasoning_tokens: m.reasoning_tokens,
|
||||
// F-260614-05 Phase 2b: 透传 parts(多模态 Image 片)。后端序列化的 ContentPart[]
|
||||
// 含 type:'text'|'image' discriminator + url/base64/media_type/alt 字段,
|
||||
// 此处原样透传供 AiChat.vue 用户气泡渲染 <img>(base64 模式持久化层已替换占位 Text 片,
|
||||
|
||||
@@ -693,11 +693,15 @@ function handleLifecycleEvent(event: AiChatEvent): boolean {
|
||||
}
|
||||
void loadConversations()
|
||||
// token 用量记录(开关开时):lastTokenUsage 供当前回复展示,convTokenTotal 累加对话总量
|
||||
// 分项 token(2026-08-02):cache_hit/cache_miss/reasoning 透传,前端 in=cache_miss 分计费展示
|
||||
if (isShowTokenUsage()) {
|
||||
state.lastTokenUsage = {
|
||||
prompt: event.prompt_tokens,
|
||||
completion: event.completion_tokens,
|
||||
total: event.total_tokens,
|
||||
cache_hit: event.prompt_cache_hit_tokens,
|
||||
cache_miss: event.prompt_cache_miss_tokens,
|
||||
reasoning: event.reasoning_tokens,
|
||||
}
|
||||
if (state.convTokenTotal) {
|
||||
state.convTokenTotal.prompt += event.prompt_tokens
|
||||
@@ -707,10 +711,20 @@ function handleLifecycleEvent(event: AiChatEvent): boolean {
|
||||
state.convTokenTotal = { prompt: event.prompt_tokens, completion: event.completion_tokens, total: event.total_tokens }
|
||||
}
|
||||
// 每轮 token 写入对应 assistant 消息(最后一条 AI 消息),供 MessageList 逐条显示。
|
||||
// 同时写消息级 cache/reasoning 字段(详情面板 + 分项显示用)。
|
||||
for (let i = state.messages.length - 1; i >= 0; i--) {
|
||||
const m = state.messages[i]
|
||||
if (m.role === 'assistant' && !m.isError) {
|
||||
m.tokenUsage = { prompt: event.prompt_tokens, completion: event.completion_tokens }
|
||||
m.tokenUsage = {
|
||||
prompt: event.prompt_tokens,
|
||||
completion: event.completion_tokens,
|
||||
cache_hit: event.prompt_cache_hit_tokens,
|
||||
cache_miss: event.prompt_cache_miss_tokens,
|
||||
reasoning: event.reasoning_tokens,
|
||||
}
|
||||
m.prompt_cache_hit_tokens = event.prompt_cache_hit_tokens
|
||||
m.prompt_cache_miss_tokens = event.prompt_cache_miss_tokens
|
||||
m.reasoning_tokens = event.reasoning_tokens
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user