@@ -575,24 +575,34 @@ func OpenaiHandlerWithUsage(c *gin.Context, info *relaycommon.RelayInfo, resp *h
575575 // 写入新的 response body
576576 service .IOCopyBytesGracefully (c , resp , responseBody )
577577
578- // Once we've written to the client, we should not return errors anymore
579- // because the upstream has already consumed resources and returned content
580- // We should still perform billing even if parsing fails
581- // format
582- if usageResp .InputTokens > 0 {
583- usageResp .PromptTokens += usageResp .InputTokens
578+ normalizeOpenAIUsage (& usageResp .Usage )
579+ applyUsagePostProcessing (info , & usageResp .Usage , responseBody )
580+ return & usageResp .Usage , nil
581+ }
582+
583+ // normalizeOpenAIUsage maps OpenAI usage aliases into NewAPI billing fields.
584+ func normalizeOpenAIUsage (usage * dto.Usage ) {
585+ if usage == nil {
586+ return
584587 }
585- if usageResp . OutputTokens > 0 {
586- usageResp . CompletionTokens += usageResp . OutputTokens
588+ if usage . InputTokens != 0 {
589+ usage . PromptTokens = usage . InputTokens
587590 }
588- if usageResp .InputTokensDetails != nil {
589- usageResp .PromptTokensDetails .ImageTokens += usageResp .InputTokensDetails .ImageTokens
590- usageResp .PromptTokensDetails .TextTokens += usageResp .InputTokensDetails .TextTokens
591+ if usage .OutputTokens != 0 {
592+ usage .CompletionTokens = usage .OutputTokens
593+ }
594+ if usage .InputTokensDetails != nil {
595+ usage .PromptTokensDetails .CachedTokens = usage .InputTokensDetails .CachedTokens
596+ usage .PromptTokensDetails .ImageTokens = usage .InputTokensDetails .ImageTokens
597+ usage .PromptTokensDetails .TextTokens = usage .InputTokensDetails .TextTokens
598+ usage .PromptTokensDetails .AudioTokens = usage .InputTokensDetails .AudioTokens
599+ }
600+ if usage .TotalTokens == 0 {
601+ usage .TotalTokens = usage .PromptTokens + usage .CompletionTokens
591602 }
592- applyUsagePostProcessing (info , & usageResp .Usage , responseBody )
593- return & usageResp .Usage , nil
594603}
595604
605+ // OpenaiImageStreamHandler forwards OpenAI Images SSE events and extracts usage.
596606func OpenaiImageStreamHandler (c * gin.Context , info * relaycommon.RelayInfo , resp * http.Response ) (* dto.Usage , * types.NewAPIError ) {
597607 if resp == nil || resp .Body == nil {
598608 logger .LogError (c , "invalid image stream response" )
@@ -609,7 +619,7 @@ func OpenaiImageStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp
609619 }
610620
611621 scanner := bufio .NewScanner (resp .Body )
612- scanner .Buffer (make ([]byte , helper .InitialScannerBufferSize ), helper .DefaultMaxScannerBufferSize )
622+ scanner .Buffer (make ([]byte , helper .InitialScannerBufferSize ), helper .GetScannerBufferSize () )
613623 for scanner .Scan () {
614624 line := scanner .Text ()
615625 if strings .HasPrefix (line , "data:" ) {
@@ -621,8 +631,11 @@ func OpenaiImageStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp
621631 info .ReceivedResponseCount ++
622632 lastStreamData = common .StringToByteSlice (data )
623633 var usageResp dto.SimpleResponse
624- if err := common .Unmarshal (lastStreamData , & usageResp ); err == nil && service .ValidUsage (& usageResp .Usage ) {
625- usage = & usageResp .Usage
634+ if err := common .Unmarshal (lastStreamData , & usageResp ); err == nil {
635+ normalizeOpenAIUsage (& usageResp .Usage )
636+ if service .ValidUsage (& usageResp .Usage ) {
637+ usage = & usageResp .Usage
638+ }
626639 }
627640 }
628641 }
0 commit comments