Просмотр исходного кода

refactor(relay): enhance error logging and improve multipart form handling in audio requests #2127

CaIon 4 месяцев назад
Родитель
Сommit
c4ca9d7c3b
3 измененных файлов с 35 добавлено и 34 удалено
  1. 2 1
      controller/relay.go
  2. 26 7
      relay/channel/openai/adaptor.go
  3. 7 26
      relay/channel/siliconflow/adaptor.go

+ 2 - 1
controller/relay.go

@@ -84,6 +84,7 @@ func Relay(c *gin.Context, relayFormat types.RelayFormat) {
 
 	defer func() {
 		if newAPIError != nil {
+			logger.LogError(c, fmt.Sprintf("relay error: %s", newAPIError.Error()))
 			newAPIError.SetMessage(common.MessageWithRequestId(newAPIError.Error(), requestId))
 			switch relayFormat {
 			case types.RelayFormatOpenAIRealtime:
@@ -281,7 +282,7 @@ func shouldRetry(c *gin.Context, openaiErr *types.NewAPIError, retryTimes int) b
 }
 
 func processChannelError(c *gin.Context, channelError types.ChannelError, err *types.NewAPIError) {
-	logger.LogError(c, fmt.Sprintf("relay error (channel #%d, status code: %d): %s", channelError.ChannelId, err.StatusCode, err.Error()))
+	logger.LogError(c, fmt.Sprintf("channel error (channel #%d, status code: %d): %s", channelError.ChannelId, err.StatusCode, err.Error()))
 	// 不要使用context获取渠道信息,异步处理时可能会出现渠道信息不一致的情况
 	// do not use context to get channel info, there may be inconsistent channel info when processing asynchronously
 	if service.ShouldDisableChannel(channelError.ChannelId, err) && channelError.AutoBan {

+ 26 - 7
relay/channel/openai/adaptor.go

@@ -15,9 +15,11 @@ import (
 	"github.com/QuantumNous/new-api/common"
 	"github.com/QuantumNous/new-api/constant"
 	"github.com/QuantumNous/new-api/dto"
+	"github.com/QuantumNous/new-api/logger"
 	"github.com/QuantumNous/new-api/relay/channel"
 	"github.com/QuantumNous/new-api/relay/channel/ai360"
 	"github.com/QuantumNous/new-api/relay/channel/lingyiwanwu"
+
 	//"github.com/QuantumNous/new-api/relay/channel/minimax"
 	"github.com/QuantumNous/new-api/relay/channel/openrouter"
 	"github.com/QuantumNous/new-api/relay/channel/xinference"
@@ -352,27 +354,43 @@ func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInf
 
 		writer.WriteField("model", request.Model)
 
-		// 获取所有表单字段
-		formData := c.Request.PostForm
+		formData, err2 := common.ParseMultipartFormReusable(c)
+		if err2 != nil {
+			return nil, fmt.Errorf("error parsing multipart form: %w", err2)
+		}
+
+		// 打印类似 curl 命令格式的信息
+		logger.LogDebug(c.Request.Context(), fmt.Sprintf("--form 'model=\"%s\"'", request.Model))
 
 		// 遍历表单字段并打印输出
-		for key, values := range formData {
+		for key, values := range formData.Value {
 			if key == "model" {
 				continue
 			}
 			for _, value := range values {
 				writer.WriteField(key, value)
+				logger.LogDebug(c.Request.Context(), fmt.Sprintf("--form '%s=\"%s\"'", key, value))
 			}
 		}
 
-		// 添加文件字段
-		file, header, err := c.Request.FormFile("file")
-		if err != nil {
+		// 从 formData 中获取文件
+		fileHeaders := formData.File["file"]
+		if len(fileHeaders) == 0 {
 			return nil, errors.New("file is required")
 		}
+
+		// 使用 formData 中的第一个文件
+		fileHeader := fileHeaders[0]
+		logger.LogDebug(c.Request.Context(), fmt.Sprintf("--form 'file=@\"%s\"' (size: %d bytes, content-type: %s)",
+			fileHeader.Filename, fileHeader.Size, fileHeader.Header.Get("Content-Type")))
+
+		file, err := fileHeader.Open()
+		if err != nil {
+			return nil, fmt.Errorf("error opening audio file: %v", err)
+		}
 		defer file.Close()
 
-		part, err := writer.CreateFormFile("file", header.Filename)
+		part, err := writer.CreateFormFile("file", fileHeader.Filename)
 		if err != nil {
 			return nil, errors.New("create form file failed")
 		}
@@ -383,6 +401,7 @@ func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInf
 		// 关闭 multipart 编写器以设置分界线
 		writer.Close()
 		c.Request.Header.Set("Content-Type", writer.FormDataContentType())
+		logger.LogDebug(c.Request.Context(), fmt.Sprintf("--header 'Content-Type: %s'", writer.FormDataContentType()))
 		return &requestBody, nil
 	}
 }

+ 7 - 26
relay/channel/siliconflow/adaptor.go

@@ -31,8 +31,8 @@ func (a *Adaptor) ConvertClaudeRequest(c *gin.Context, info *relaycommon.RelayIn
 }
 
 func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
-	//TODO implement me
-	return nil, errors.New("not supported")
+	adaptor := openai.Adaptor{}
+	return adaptor.ConvertAudioRequest(c, info, request)
 }
 
 func (a *Adaptor) ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.ImageRequest) (any, error) {
@@ -65,16 +65,8 @@ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
 func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
 	if info.RelayMode == constant.RelayModeRerank {
 		return fmt.Sprintf("%s/v1/rerank", info.ChannelBaseUrl), nil
-	} else if info.RelayMode == constant.RelayModeEmbeddings {
-		return fmt.Sprintf("%s/v1/embeddings", info.ChannelBaseUrl), nil
-	} else if info.RelayMode == constant.RelayModeChatCompletions {
-		return fmt.Sprintf("%s/v1/chat/completions", info.ChannelBaseUrl), nil
-	} else if info.RelayMode == constant.RelayModeCompletions {
-		return fmt.Sprintf("%s/v1/completions", info.ChannelBaseUrl), nil
-	} else if info.RelayMode == constant.RelayModeImagesGenerations {
-		return fmt.Sprintf("%s/v1/images/generations", info.ChannelBaseUrl), nil
 	}
-	return fmt.Sprintf("%s/v1/chat/completions", info.ChannelBaseUrl), nil
+	return relaycommon.GetFullRequestURL(info.ChannelBaseUrl, info.RequestURLPath, info.ChannelType), nil
 }
 
 func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error {
@@ -103,7 +95,8 @@ func (a *Adaptor) ConvertOpenAIResponsesRequest(c *gin.Context, info *relaycommo
 }
 
 func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
-	return channel.DoApiRequest(a, c, info, requestBody)
+	adaptor := openai.Adaptor{}
+	return adaptor.DoRequest(c, info, requestBody)
 }
 
 func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error) {
@@ -118,21 +111,9 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
 	switch info.RelayMode {
 	case constant.RelayModeRerank:
 		usage, err = siliconflowRerankHandler(c, info, resp)
-	case constant.RelayModeEmbeddings:
-		usage, err = openai.OpenaiHandler(c, info, resp)
-	case constant.RelayModeCompletions:
-		fallthrough
-	case constant.RelayModeChatCompletions:
-		fallthrough
-	case constant.RelayModeImagesGenerations:
-		fallthrough
 	default:
-		if info.IsStream {
-			usage, err = openai.OaiStreamHandler(c, info, resp)
-		} else {
-			usage, err = openai.OpenaiHandler(c, info, resp)
-		}
-
+		adaptor := openai.Adaptor{}
+		usage, err = adaptor.DoResponse(c, resp, info)
 	}
 	return
 }