fix(usage): stop inferring cache reads from prompt_cache_key

This commit is contained in:
ZheFox
2026-05-17 03:04:33 +08:00
parent 41ffb18604
commit ab0d766f47

View File

@@ -2203,7 +2203,7 @@ fn apply_cancelled_usage_estimate(data: &mut UsageEventData) {
.provider_request_body .provider_request_body
.as_ref() .as_ref()
.or(data.request_body.as_ref()) .or(data.request_body.as_ref())
.and_then(|value| estimate_request_usage(value, cancelled_usage_api_format(data))); .and_then(estimate_request_usage);
if positive_tokens(data.input_tokens) == 0 { if positive_tokens(data.input_tokens) == 0 {
if let Some(usage) = request_usage.as_ref() { if let Some(usage) = request_usage.as_ref() {
@@ -2235,12 +2235,6 @@ fn apply_cancelled_usage_estimate(data: &mut UsageEventData) {
} }
} }
fn cancelled_usage_api_format(data: &UsageEventData) -> Option<&str> {
data.endpoint_api_format
.as_deref()
.or(data.api_format.as_deref())
}
fn apply_cancelled_request_cache_estimate( fn apply_cancelled_request_cache_estimate(
data: &mut UsageEventData, data: &mut UsageEventData,
request_usage: Option<&EstimatedRequestUsage>, request_usage: Option<&EstimatedRequestUsage>,
@@ -2283,10 +2277,7 @@ struct EstimatedRequestUsage {
cache_creation_ephemeral_1h_tokens: u64, cache_creation_ephemeral_1h_tokens: u64,
} }
fn estimate_request_usage( fn estimate_request_usage(value: &Value) -> Option<EstimatedRequestUsage> {
value: &Value,
api_format: Option<&str>,
) -> Option<EstimatedRequestUsage> {
let preferred_total = match value { let preferred_total = match value {
Value::Object(object) => [ Value::Object(object) => [
"instructions", "instructions",
@@ -2317,9 +2308,6 @@ fn estimate_request_usage(
..EstimatedRequestUsage::default() ..EstimatedRequestUsage::default()
}; };
apply_explicit_request_cache_usage(value, &mut usage); apply_explicit_request_cache_usage(value, &mut usage);
if usage.cache_read_tokens == 0 && request_has_openai_prompt_cache_key(value, api_format) {
usage.cache_read_tokens = usage.input_tokens;
}
Some(usage) Some(usage)
} }
@@ -2387,25 +2375,6 @@ fn value_as_positive_u64(value: &Value) -> Option<u64> {
.filter(|value| *value > 0) .filter(|value| *value > 0)
} }
fn request_has_openai_prompt_cache_key(value: &Value, api_format: Option<&str>) -> bool {
api_family_matches(api_format, "openai")
&& value
.get("prompt_cache_key")
.and_then(Value::as_str)
.is_some_and(|value| !value.trim().is_empty())
}
fn api_family_matches(api_format: Option<&str>, expected: &str) -> bool {
api_format
.and_then(|value| {
value
.split_once(':')
.map(|(family, _)| family)
.or(Some(value))
})
.is_some_and(|family| family.eq_ignore_ascii_case(expected))
}
fn estimate_json_tokens(value: &Value) -> u64 { fn estimate_json_tokens(value: &Value) -> u64 {
match value { match value {
Value::String(text) => estimate_text_tokens(text), Value::String(text) => estimate_text_tokens(text),
@@ -3349,7 +3318,7 @@ mod tests {
} }
#[test] #[test]
fn cancelled_stream_usage_estimates_prompt_cache_read_tokens() { fn cancelled_stream_usage_does_not_infer_cache_read_from_prompt_cache_key() {
let request_body = json!({ let request_body = json!({
"model": "gpt-5.4", "model": "gpt-5.4",
"input": "Use the cached project context and answer briefly", "input": "Use the cached project context and answer briefly",
@@ -3406,7 +3375,7 @@ mod tests {
.expect("input estimate should exist"); .expect("input estimate should exist");
assert_eq!(event.event_type, UsageEventType::Cancelled); assert_eq!(event.event_type, UsageEventType::Cancelled);
assert_eq!(event.data.cache_read_input_tokens, Some(input_tokens)); assert_eq!(event.data.cache_read_input_tokens, None);
assert_eq!(event.data.output_tokens, Some(4)); assert_eq!(event.data.output_tokens, Some(4));
assert_eq!(event.data.total_tokens, Some(input_tokens + 4)); assert_eq!(event.data.total_tokens, Some(input_tokens + 4));
} }