mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-09-20 00:48:00 +00:00
feat: record cache hit/miss per request in audit trail and WebUI
- Req: add CacheHit and CacheMiss fields (carrying upstream cache accounting from either prompt_tokens_details.cached_tokens or legacy prompt_cache_hit_tokens) - recordChatUsage (non-streaming): copy cache fields from resp.TokenUsage - pumpStream (streaming): write lastUsage cache fields back onto rec at stream end, so streaming requests carry cache data too - CSV export: add first_byte_ms, cache_hit_tokens, cache_miss_tokens columns alongside the existing latency/prompt/completion - WebUI request-records table: add a Cache column showing hit% per row (green/amber tag with tooltip hit/miss breakdown; em-dash when the upstream reported no cache data)
This commit is contained in:
@ -570,6 +570,17 @@ func recordChatUsage(rec *Req, req *types.ChatRequest, resp *types.UnifiedRespon
|
||||
if rec.Compl == 0 {
|
||||
rec.Compl = estimateTextTokens(resp.Content, resp.ReasoningContent, resp.ToolCalls)
|
||||
}
|
||||
// Cache accounting: whichever source format the adapter normalized into
|
||||
// (prompt_tokens_details.cached_tokens or legacy prompt_cache_hit_tokens),
|
||||
// read it back so the request record carries the hit/miss split.
|
||||
if d := resp.TokenUsage.PromptTokensDetails; d != nil && d.CachedTokens > 0 {
|
||||
rec.CacheHit = int64(d.CachedTokens)
|
||||
} else if resp.TokenUsage.PromptCacheHit > 0 {
|
||||
rec.CacheHit = int64(resp.TokenUsage.PromptCacheHit)
|
||||
}
|
||||
if resp.TokenUsage.PromptCacheMiss > 0 {
|
||||
rec.CacheMiss = int64(resp.TokenUsage.PromptCacheMiss)
|
||||
}
|
||||
}
|
||||
|
||||
// writeChatCompletion renders a unified response as an OpenAI
|
||||
@ -748,6 +759,16 @@ func (g *Gateway) pumpStream(w http.ResponseWriter, rec *Req, chunks <-chan type
|
||||
var tut *types.TokenUsage
|
||||
if lastUsage != nil {
|
||||
tut = lastUsage
|
||||
// Write the upstream's cache accounting back onto the request record
|
||||
// so the audit trail carries the hit/miss split for streaming too.
|
||||
if d := tut.PromptTokensDetails; d != nil && d.CachedTokens > 0 {
|
||||
rec.CacheHit = int64(d.CachedTokens)
|
||||
} else if tut.PromptCacheHit > 0 {
|
||||
rec.CacheHit = int64(tut.PromptCacheHit)
|
||||
}
|
||||
if tut.PromptCacheMiss > 0 {
|
||||
rec.CacheMiss = int64(tut.PromptCacheMiss)
|
||||
}
|
||||
} else if rec.Prompt+rec.Compl > 0 {
|
||||
u := types.TokenUsage{
|
||||
Prompt: int(rec.Prompt),
|
||||
|
||||
Reference in New Issue
Block a user