From 6a761c2dbaa8bd08ed9003845b63c68d4d6c585e Mon Sep 17 00:00:00 2001 From: IcedTangerine Date: Tue, 4 Nov 2025 01:43:04 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20openai=20=E9=9F=B3=E9=A2=91=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E6=B5=81=E6=A8=A1=E5=BC=8F=E6=9C=AA=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=E8=AE=A1=E8=B4=B9=20(#2160)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- relay/channel/openai/relay-openai.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) 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,