mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-09-20 00:48:00 +00:00
feat(types): pass through upstream cache tokens in TokenUsage
dsh displays cache-hit %, but llmsproxy dropped every upstream's cache fields — deepseek prompt_cache_hit_tokens, OpenAI prompt_tokens_details. cached_tokens, anthropic cache_read_input_tokens, gemini cachedContentTokenCount. Changes: - TokenUsage: add PromptTokensDetails (with CachedTokens) + PromptCacheHit/Miss - MarshalJSON: emit prompt_tokens_details.cached_tokens (OpenAI v2 standard) and prompt_cache_hit/miss_tokens (DeepSeek legacy) — dsh reads the former first, falls back to the latter - mergeUsage: preserve cache fields across stream chunks - standardSSEChunk: parse the upstream raw prompt_tokens_details too - deepseek.lua: forward prompt_cache_hit/miss_tokens + create prompt_tokens_details from them - openai.lua: forward prompt_tokens_details.cached_tokens and legacy prompt_cache_hit/miss_tokens; normalize legacy hits into the standard object so dsh sees them regardless of upstream format - anthropic.lua: map cache_read_input_tokens → prompt_tokens_details - gemini.lua: map cachedContentTokenCount → prompt_tokens_details
This commit is contained in:
@ -1058,12 +1058,17 @@ func standardSSEChunk(data string) string {
|
||||
FinishReason *string `json:"finish_reason"`
|
||||
} `json:"choices"`
|
||||
UpstreamUsage struct {
|
||||
PromptTokens int `json:"prompt_tokens"`
|
||||
CompletionTokens int `json:"completion_tokens"`
|
||||
TotalTokens int `json:"total_tokens"`
|
||||
Prompt int `json:"prompt"`
|
||||
Completion int `json:"completion"`
|
||||
Total int `json:"total"`
|
||||
PromptTokens int `json:"prompt_tokens"`
|
||||
CompletionTokens int `json:"completion_tokens"`
|
||||
TotalTokens int `json:"total_tokens"`
|
||||
Prompt int `json:"prompt"`
|
||||
Completion int `json:"completion"`
|
||||
Total int `json:"total"`
|
||||
PromptCacheHit int `json:"prompt_cache_hit_tokens"`
|
||||
PromptCacheMiss int `json:"prompt_cache_miss_tokens"`
|
||||
PromptTokensDetails *struct {
|
||||
CachedTokens int `json:"cached_tokens"`
|
||||
} `json:"prompt_tokens_details"`
|
||||
} `json:"usage"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), &raw); err != nil {
|
||||
@ -1076,9 +1081,16 @@ func standardSSEChunk(data string) string {
|
||||
pu := raw.UpstreamUsage
|
||||
if pu.Total > 0 || pu.TotalTokens > 0 {
|
||||
usage = &types.TokenUsage{
|
||||
Prompt: pickFirst(pu.PromptTokens, pu.Prompt),
|
||||
Completion: pickFirst(pu.CompletionTokens, pu.Completion),
|
||||
Total: pickFirst(pu.TotalTokens, pu.Total),
|
||||
Prompt: pickFirst(pu.PromptTokens, pu.Prompt),
|
||||
Completion: pickFirst(pu.CompletionTokens, pu.Completion),
|
||||
Total: pickFirst(pu.TotalTokens, pu.Total),
|
||||
PromptCacheHit: pu.PromptCacheHit,
|
||||
PromptCacheMiss: pu.PromptCacheMiss,
|
||||
}
|
||||
if pu.PromptTokensDetails != nil && pu.PromptTokensDetails.CachedTokens > 0 {
|
||||
usage.PromptTokensDetails = &types.PromptTokensDetails{
|
||||
CachedTokens: pu.PromptTokensDetails.CachedTokens,
|
||||
}
|
||||
}
|
||||
}
|
||||
finish := ""
|
||||
|
||||
Reference in New Issue
Block a user