mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
fix(usage): 修复 Gemini total 重复累加 cache_read 并补充测试
- write.rs: Gemini usage 提取 total 时不再叠加 cachedContentTokenCount - 补充 Claude 大 cache_read 场景下 input_tokens 不被扣减的测试 - 补充前端 getEffectiveInputTokens 对 Claude 格式不减 cache_read 的测试
This commit is contained in:
@@ -1340,6 +1340,31 @@ mod tests {
|
|||||||
assert_eq!(payload["cache_creation_ephemeral_1h_input_tokens"], 6);
|
assert_eq!(payload["cache_creation_ephemeral_1h_input_tokens"], 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn user_usage_payload_keeps_claude_effective_input_when_cache_read_is_large() {
|
||||||
|
let item = StoredRequestUsageAudit {
|
||||||
|
provider_name: "Claude".to_string(),
|
||||||
|
model: "claude-sonnet-4-5".to_string(),
|
||||||
|
api_format: Some("claude:chat".to_string()),
|
||||||
|
api_family: Some("claude".to_string()),
|
||||||
|
endpoint_api_format: Some("claude:chat".to_string()),
|
||||||
|
provider_api_family: Some("claude".to_string()),
|
||||||
|
input_tokens: 4941,
|
||||||
|
output_tokens: 973,
|
||||||
|
total_tokens: 59474,
|
||||||
|
cache_creation_input_tokens: 687,
|
||||||
|
cache_read_input_tokens: 52873,
|
||||||
|
..sample_usage("completed")
|
||||||
|
};
|
||||||
|
|
||||||
|
let payload = build_users_me_usage_record_payload(&item, false, &BTreeMap::new(), false);
|
||||||
|
|
||||||
|
assert_eq!(payload["input_tokens"], 4941);
|
||||||
|
assert_eq!(payload["effective_input_tokens"], 4941);
|
||||||
|
assert_eq!(payload["cache_creation_input_tokens"], 687);
|
||||||
|
assert_eq!(payload["cache_read_input_tokens"], 52873);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn user_usage_active_pending_with_failure_signal_is_not_active() {
|
fn user_usage_active_pending_with_failure_signal_is_not_active() {
|
||||||
let item = StoredRequestUsageAudit {
|
let item = StoredRequestUsageAudit {
|
||||||
|
|||||||
@@ -418,6 +418,54 @@ mod tests {
|
|||||||
assert_eq!(usage.cache_read_tokens, 1);
|
assert_eq!(usage.cache_read_tokens, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn maps_claude_usage_with_large_cache_read_tokens_without_subtracting_input() {
|
||||||
|
let usage = map_usage(
|
||||||
|
&serde_json::json!({
|
||||||
|
"input_tokens": 4941,
|
||||||
|
"cache_creation_input_tokens": 687,
|
||||||
|
"cache_read_input_tokens": 52873,
|
||||||
|
"output_tokens": 973
|
||||||
|
}),
|
||||||
|
"claude:chat",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(usage.input_tokens, 4941);
|
||||||
|
assert_eq!(usage.cache_creation_tokens, 687);
|
||||||
|
assert_eq!(usage.cache_read_tokens, 52873);
|
||||||
|
assert_eq!(usage.output_tokens, 973);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn maps_claude_usage_with_cache_creation_total_and_zero_ttl_breakdown() {
|
||||||
|
let usage = map_usage(
|
||||||
|
&serde_json::json!({
|
||||||
|
"cache_creation": {
|
||||||
|
"ephemeral_1h_input_tokens": 0,
|
||||||
|
"ephemeral_5m_input_tokens": 0
|
||||||
|
},
|
||||||
|
"cache_creation_input_tokens": 2051,
|
||||||
|
"cache_read_input_tokens": 2051,
|
||||||
|
"inference_geo": "inference_geo",
|
||||||
|
"input_tokens": 2095,
|
||||||
|
"output_tokens": 503,
|
||||||
|
"server_tool_use": {
|
||||||
|
"web_fetch_requests": 2,
|
||||||
|
"web_search_requests": 0
|
||||||
|
},
|
||||||
|
"service_tier": "standard"
|
||||||
|
}),
|
||||||
|
"claude:chat",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(usage.input_tokens, 2095);
|
||||||
|
assert_eq!(usage.cache_creation_tokens, 2051);
|
||||||
|
assert_eq!(usage.cache_creation_ephemeral_5m_tokens, 0);
|
||||||
|
assert_eq!(usage.cache_creation_ephemeral_1h_tokens, 0);
|
||||||
|
assert_eq!(usage.cache_read_tokens, 2051);
|
||||||
|
assert_eq!(usage.output_tokens, 503);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn maps_claude_usage_with_ephemeral_cache_breakdown() {
|
fn maps_claude_usage_with_ephemeral_cache_breakdown() {
|
||||||
let usage = map_usage(
|
let usage = map_usage(
|
||||||
|
|||||||
@@ -2180,16 +2180,7 @@ fn extract_token_counts_from_json(value: &Value) -> Option<(u64, u64, u64)> {
|
|||||||
.get("totalTokenCount")
|
.get("totalTokenCount")
|
||||||
.and_then(Value::as_u64)
|
.and_then(Value::as_u64)
|
||||||
.unwrap_or(input + output);
|
.unwrap_or(input + output);
|
||||||
let cache_read = usage
|
return Some((input, output, raw_total));
|
||||||
.get("cachedContentTokenCount")
|
|
||||||
.and_then(Value::as_u64)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let total = if cache_read > 0 {
|
|
||||||
input.saturating_add(output).saturating_add(cache_read)
|
|
||||||
} else {
|
|
||||||
raw_total
|
|
||||||
};
|
|
||||||
return Some((input, output, total));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(chunks) = value.get("chunks").and_then(Value::as_array) {
|
if let Some(chunks) = value.get("chunks").and_then(Value::as_array) {
|
||||||
@@ -2353,6 +2344,21 @@ mod tests {
|
|||||||
assert_eq!(tokens, (6, 20, 41883));
|
assert_eq!(tokens, (6, 20, 41883));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extracts_gemini_usage_tokens_without_adding_cached_content_twice() {
|
||||||
|
let tokens = extract_token_counts_from_json(&json!({
|
||||||
|
"usageMetadata": {
|
||||||
|
"promptTokenCount": 14,
|
||||||
|
"candidatesTokenCount": 6,
|
||||||
|
"cachedContentTokenCount": 2,
|
||||||
|
"totalTokenCount": 20
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.expect("tokens should exist");
|
||||||
|
|
||||||
|
assert_eq!(tokens, (14, 6, 20));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn extracts_usage_tokens_from_last_matching_chunk() {
|
fn extracts_usage_tokens_from_last_matching_chunk() {
|
||||||
let tokens = extract_token_counts_from_json(&json!({
|
let tokens = extract_token_counts_from_json(&json!({
|
||||||
|
|||||||
@@ -26,4 +26,14 @@ describe('usage token normalization', () => {
|
|||||||
api_format: 'openai:chat',
|
api_format: 'openai:chat',
|
||||||
})).toBe(80)
|
})).toBe(80)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('does not subtract cache read tokens for Claude usage', () => {
|
||||||
|
expect(getEffectiveInputTokens({
|
||||||
|
input_tokens: 4941,
|
||||||
|
cache_creation_input_tokens: 687,
|
||||||
|
cache_read_input_tokens: 52873,
|
||||||
|
output_tokens: 973,
|
||||||
|
api_format: 'claude:chat',
|
||||||
|
})).toBe(4941)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user