Context
#226 (non-chat UsageEvent emission) is now complete — all 6 endpoints emit (embeddings/responses/completions/rerank #402/#426/#425/#428, audio/images #454). But the audio/images MVP (#406/#407) only carries token counts. The token shape covers the modern models (gpt-image-1, gpt-4o-transcribe), which return a usage token block. The legacy models do not, and are not billed by tokens at all:
- audio (
whisper-1, and gpt-4o-transcribe under some response_formats) → billed by duration-seconds (OpenAI returns usage:{type:"duration",seconds:N}).
- images (
dall-e-2/3) → billed by (model, size, quality) × n — no token block at all.
Today those requests emit a zero-token UsageEvent: visible + attributed in the ledger (no longer invisible — that gap is closed by #454), but with no cost basis, so cp-api cannot price them.
Gap
The UsageEvent wire struct (aisix-obs) has no field to carry duration-seconds or image (count/size/quality). cp-api's pricing therefore can't compute spend for legacy audio/image traffic even though the event now arrives.
Proposed work (cross-repo)
- ai-gateway — extend
UsageEvent with optional cost-basis fields, e.g. audio_duration_seconds: Option<f64> and image_count/image_size/image_quality: Option<...> (all #[serde(skip_serializing_if)] so existing token-only events are unchanged on the wire). Populate them in audio.rs / images.rs from the response usage.duration and the request n/size/quality.
- cp-api (AISIX-Cloud) — add pricing rules keyed on duration-seconds (audio) and (model,size,quality) tuples (images), and apply them when the new fields are present.
Cross-checked against comparable open-source multi-provider gateways: audio is priced cost_per_second × duration; images via a (quality,size,n) cost calculator — confirming duration + (n,size,quality) are the right cost dimensions.
Acceptance
Refs: #226 (parent, now complete), #454 (origin — the token-MVP that deferred this)
Context
#226 (non-chat UsageEvent emission) is now complete — all 6 endpoints emit (embeddings/responses/completions/rerank #402/#426/#425/#428, audio/images #454). But the audio/images MVP (#406/#407) only carries token counts. The token shape covers the modern models (
gpt-image-1,gpt-4o-transcribe), which return ausagetoken block. The legacy models do not, and are not billed by tokens at all:whisper-1, andgpt-4o-transcribeunder someresponse_formats) → billed by duration-seconds (OpenAI returnsusage:{type:"duration",seconds:N}).dall-e-2/3) → billed by (model, size, quality) × n — no token block at all.Today those requests emit a zero-token UsageEvent: visible + attributed in the ledger (no longer invisible — that gap is closed by #454), but with no cost basis, so cp-api cannot price them.
Gap
The
UsageEventwire struct (aisix-obs) has no field to carry duration-seconds or image (count/size/quality). cp-api's pricing therefore can't compute spend for legacy audio/image traffic even though the event now arrives.Proposed work (cross-repo)
UsageEventwith optional cost-basis fields, e.g.audio_duration_seconds: Option<f64>andimage_count/image_size/image_quality: Option<...>(all#[serde(skip_serializing_if)]so existing token-only events are unchanged on the wire). Populate them inaudio.rs/images.rsfrom the responseusage.durationand the requestn/size/quality.Cross-checked against comparable open-source multi-provider gateways: audio is priced
cost_per_second × duration; images via a(quality,size,n)cost calculator — confirming duration + (n,size,quality) are the right cost dimensions.Acceptance
UsageEventcarries duration (audio) + n/size/quality (images), back-compatible on the wirewhisper-1/dall-e-*trafficdall-e-3/whisper-1request produces a priced (non-zero spend) ledger entryRefs: #226 (parent, now complete), #454 (origin — the token-MVP that deferred this)