fix: bound uncached remainder by prompt-max(cached,write) and forward compact prompt_cache_key

This commit is contained in:
CaIon
2026-07-11 22:18:26 +08:00
parent 48068ce923
commit 92d3c9d18f
9 changed files with 34 additions and 18 deletions
@@ -44,7 +44,8 @@ func buildClaudeUsageFromOpenAIUsage(oaiUsage *dto.Usage) *dto.ClaudeUsage {
if oaiUsage.PromptTokensDetails.CacheWriteTokens > 0 {
// OpenAI native cache-write usage counts cached and cache-write tokens
// inside prompt_tokens, while Claude semantics reports input_tokens
// excluding both; the uncached remainder clamps at zero.
// excluding both. Both counts are unadjusted prefixes and may overlap,
// so clamp a negative remainder at zero.
inputTokens = oaiUsage.PromptTokens - oaiUsage.PromptTokensDetails.CachedTokens - cacheCreationTokens
if inputTokens < 0 {
inputTokens = 0
@@ -92,7 +92,7 @@ func TestBuildClaudeUsageFromOpenAICacheWriteUsage(t *testing.T) {
require.NotNil(t, usage)
// Claude semantics reports input_tokens excluding cache read/write; the
// remainder 3619-2921-3616 clamps to 0.
// overlapping unadjusted prefixes drive the remainder negative, clamp to 0.
assert.Equal(t, 0, usage.InputTokens)
assert.Equal(t, 2921, usage.CacheReadInputTokens)
assert.Equal(t, 3616, usage.CacheCreationInputTokens)
+4 -3
View File
@@ -294,9 +294,10 @@ func calculateTextQuotaSummary(ctx *gin.Context, relayInfo *relaycommon.RelayInf
}
}
// OpenAI cache-write usage can report cached_tokens + cache_write_tokens
// exceeding prompt_tokens; the uncached remainder must clamp at zero so
// billing never subtracts more than the reported input.
// OpenAI cache-write usage reports unadjusted prefix counts, so
// cached_tokens + cache_write_tokens can exceed prompt_tokens and the
// remainder can go negative. Clamp at zero so overlap never turns into
// a negative base charge.
if baseTokens.IsNegative() {
baseTokens = decimal.Zero
}
+2 -2
View File
@@ -411,8 +411,8 @@ func TestCalculateTextQuotaSummaryBillsOpenAICacheWriteTokens(t *testing.T) {
t.Run("uncached remainder clamps to zero", func(t *testing.T) {
// Real OpenAI payload shape: cached_tokens + cache_write_tokens exceeds
// prompt_tokens, so the uncached remainder must clamp to 0 instead of
// producing a negative charge component.
// prompt_tokens because both are unadjusted prefix counts. The negative
// remainder must clamp to zero, never turn into a negative base charge.
usage := &dto.Usage{
PromptTokens: 3619,
CompletionTokens: 36,
+2
View File
@@ -67,6 +67,8 @@ func BuildTieredTokenParams(usage *dto.Usage, isClaudeUsageSemantic bool, usedVa
}
}
// OpenAI cache-write usage reports unadjusted prefix counts, so cr + cc can
// exceed the prompt and drive the remainder negative. Clamp at zero.
if p < 0 {
p = 0
}