diff --git a/relay/channel/openai/relay-openai.go b/relay/channel/openai/relay-openai.go index c08e396fe..e05f1af83 100644 --- a/relay/channel/openai/relay-openai.go +++ b/relay/channel/openai/relay-openai.go @@ -122,6 +122,10 @@ func OaiStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Re var usage = &dto.Usage{} var streamItems []string // store stream items var lastStreamData string + var secondLastStreamData string // 存储倒数第二个stream data,用于音频模型 + + // 检查是否为音频模型 + isAudioModel := strings.Contains(strings.ToLower(model), "audio") helper.StreamScannerHandler(c, resp, info, func(data string) bool { if lastStreamData != "" { @@ -131,12 +135,35 @@ func OaiStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Re } } if len(data) > 0 { + // 对音频模型,保存倒数第二个stream data + if isAudioModel && lastStreamData != "" { + secondLastStreamData = lastStreamData + } + lastStreamData = data streamItems = append(streamItems, data) } return true }) + // 对音频模型,从倒数第二个stream data中提取usage信息 + if isAudioModel && secondLastStreamData != "" { + var streamResp struct { + Usage *dto.Usage `json:"usage"` + } + err := json.Unmarshal([]byte(secondLastStreamData), &streamResp) + if err == nil && streamResp.Usage != nil && service.ValidUsage(streamResp.Usage) { + usage = streamResp.Usage + containStreamUsage = true + + if common.DebugEnabled { + logger.LogDebug(c, fmt.Sprintf("Audio model usage extracted from second last SSE: PromptTokens=%d, CompletionTokens=%d, TotalTokens=%d, InputTokens=%d, OutputTokens=%d", + usage.PromptTokens, usage.CompletionTokens, usage.TotalTokens, + usage.InputTokens, usage.OutputTokens)) + } + } + } + // 处理最后的响应 shouldSendLastResp := true if err := handleLastResponse(lastStreamData, &responseId, &createAt, &systemFingerprint, &model, &usage,