The OpenAI-compatible POST /v1/chat/completions route converts Pydantic AI RequestUsage into Phoenix's OpenAI-shaped ChatCompletionUsage, but it only emits prompt_tokens, completion_tokens, and total_tokens.
When the backing provider reports prompt cache reads via RequestUsage.cache_read_tokens, that value is not surfaced as usage.prompt_tokens_details.cached_tokens in the OpenAI-compatible response.
Minimal reproduction at the helper boundary:
_to_openai_usage(RequestUsage(input_tokens=100, output_tokens=20, cache_read_tokens=60)).model_dump(exclude_none=True)
Current output:
{
"prompt_tokens": 100,
"completion_tokens": 20,
"total_tokens": 120,
}
Expected output:
{
"prompt_tokens": 100,
"completion_tokens": 20,
"total_tokens": 120,
"prompt_tokens_details": {"cached_tokens": 60},
}
This matters for downstream OpenAI-compatible clients and telemetry that separate cached prompt reads from non-cached prompt input.
The OpenAI-compatible
POST /v1/chat/completionsroute converts Pydantic AIRequestUsageinto Phoenix's OpenAI-shapedChatCompletionUsage, but it only emitsprompt_tokens,completion_tokens, andtotal_tokens.When the backing provider reports prompt cache reads via
RequestUsage.cache_read_tokens, that value is not surfaced asusage.prompt_tokens_details.cached_tokensin the OpenAI-compatible response.Minimal reproduction at the helper boundary:
Current output:
{ "prompt_tokens": 100, "completion_tokens": 20, "total_tokens": 120, }Expected output:
{ "prompt_tokens": 100, "completion_tokens": 20, "total_tokens": 120, "prompt_tokens_details": {"cached_tokens": 60}, }This matters for downstream OpenAI-compatible clients and telemetry that separate cached prompt reads from non-cached prompt input.