feat: publish v1.0.0-rc.36-custom.1
Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 9m20s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 55m7s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 9m20s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 55m7s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
This commit is contained in:
commit
bb7968b612
2381 files changed
+551494
No files matched your search
@@ -0,0 +1,204 @@
|
||||
package relay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/QuantumNous/new-api/common"
|
||||
"github.com/QuantumNous/new-api/constant"
|
||||
"github.com/QuantumNous/new-api/relay/channel"
|
||||
openaichannel "github.com/QuantumNous/new-api/relay/channel/openai"
|
||||
relaycommon "github.com/QuantumNous/new-api/relay/common"
|
||||
relayconstant "github.com/QuantumNous/new-api/relay/constant"
|
||||
"github.com/QuantumNous/new-api/relaykit/dto"
|
||||
"github.com/QuantumNous/new-api/relaykit/types"
|
||||
"github.com/QuantumNous/new-api/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func applySystemPromptIfNeeded(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeneralOpenAIRequest) {
|
||||
if info == nil || request == nil {
|
||||
return
|
||||
}
|
||||
if info.ChannelSetting.SystemPrompt == "" {
|
||||
return
|
||||
}
|
||||
|
||||
systemRole := request.GetSystemRoleName()
|
||||
|
||||
// A Kimi K3 dynamic tool loading message ({"role":"system","tools":[...]})
|
||||
// declares tools rather than a system prompt and must never receive content.
|
||||
containSystemPrompt := false
|
||||
for _, message := range request.Messages {
|
||||
if message.Role == systemRole && len(message.Tools) == 0 {
|
||||
containSystemPrompt = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !containSystemPrompt {
|
||||
systemMessage := dto.Message{
|
||||
Role: systemRole,
|
||||
Content: info.ChannelSetting.SystemPrompt,
|
||||
}
|
||||
request.Messages = append([]dto.Message{systemMessage}, request.Messages...)
|
||||
return
|
||||
}
|
||||
|
||||
if !info.ChannelSetting.SystemPromptOverride {
|
||||
return
|
||||
}
|
||||
|
||||
common.SetContextKey(c, constant.ContextKeySystemPromptOverride, true)
|
||||
for i, message := range request.Messages {
|
||||
if message.Role != systemRole || len(message.Tools) > 0 {
|
||||
continue
|
||||
}
|
||||
if message.IsStringContent() {
|
||||
request.Messages[i].SetStringContent(info.ChannelSetting.SystemPrompt + "\n" + message.StringContent())
|
||||
return
|
||||
}
|
||||
contents := message.ParseContent()
|
||||
contents = append([]dto.MediaContent{
|
||||
{
|
||||
Type: dto.ContentTypeText,
|
||||
Text: info.ChannelSetting.SystemPrompt,
|
||||
},
|
||||
}, contents...)
|
||||
request.Messages[i].Content = contents
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func textRequestViaResponses(c *gin.Context, info *relaycommon.RelayInfo, adaptor channel.Adaptor, request any) (*dto.Usage, *types.NewAPIError) {
|
||||
paramOverrideApplied := false
|
||||
if chatRequest, ok := request.(*dto.GeneralOpenAIRequest); ok {
|
||||
chatJSON, err := common.Marshal(chatRequest)
|
||||
if err != nil {
|
||||
return nil, types.NewError(err, types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
|
||||
chatJSON, err = relaycommon.RemoveDisabledFields(chatJSON, info.ChannelOtherSettings, info.ChannelSetting.PassThroughBodyEnabled)
|
||||
if err != nil {
|
||||
return nil, types.NewError(err, types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
|
||||
if len(info.ParamOverride) > 0 {
|
||||
chatJSON, err = relaycommon.ApplyParamOverrideWithRelayInfo(chatJSON, info)
|
||||
if err != nil {
|
||||
return nil, newAPIErrorFromParamOverride(err)
|
||||
}
|
||||
paramOverrideApplied = true
|
||||
}
|
||||
|
||||
var overriddenChatReq dto.GeneralOpenAIRequest
|
||||
if err := common.Unmarshal(chatJSON, &overriddenChatReq); err != nil {
|
||||
return nil, types.NewError(err, types.ErrorCodeChannelParamOverrideInvalid, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
request = &overriddenChatReq
|
||||
}
|
||||
|
||||
result, err := service.ConvertRequest(c, info, types.RelayFormatOpenAIResponses, request)
|
||||
if err != nil {
|
||||
return nil, types.NewErrorWithStatusCode(err, types.ErrorCodeInvalidRequest, http.StatusBadRequest, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
responsesReq, ok := result.Value.(*dto.OpenAIResponsesRequest)
|
||||
if !ok {
|
||||
return nil, types.NewError(fmt.Errorf("expected OpenAI responses request, got %T", result.Value), types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
return relayResponsesRequest(c, info, adaptor, responsesReq, paramOverrideApplied)
|
||||
}
|
||||
|
||||
func relayResponsesRequest(c *gin.Context, info *relaycommon.RelayInfo, adaptor channel.Adaptor, responsesReq *dto.OpenAIResponsesRequest, paramOverrideApplied bool) (*dto.Usage, *types.NewAPIError) {
|
||||
savedRelayMode := info.RelayMode
|
||||
savedRequestURLPath := info.RequestURLPath
|
||||
defer func() {
|
||||
info.RelayMode = savedRelayMode
|
||||
info.RequestURLPath = savedRequestURLPath
|
||||
}()
|
||||
|
||||
info.RelayMode = relayconstant.RelayModeResponses
|
||||
info.RequestURLPath = "/v1/responses"
|
||||
|
||||
convertedRequest, err := adaptor.ConvertOpenAIResponsesRequest(c, info, *responsesReq)
|
||||
if err != nil {
|
||||
return nil, newConvertRequestFailedError(c, info, err)
|
||||
}
|
||||
relaycommon.AppendRequestConversionFromRequest(info, convertedRequest)
|
||||
|
||||
jsonData, err := common.Marshal(convertedRequest)
|
||||
if err != nil {
|
||||
return nil, types.NewError(err, types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
|
||||
jsonData, err = relaycommon.RemoveDisabledFields(jsonData, info.ChannelOtherSettings, info.ChannelSetting.PassThroughBodyEnabled)
|
||||
if err != nil {
|
||||
return nil, types.NewError(err, types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
if !paramOverrideApplied && len(info.ParamOverride) > 0 {
|
||||
jsonData, err = relaycommon.ApplyParamOverrideWithRelayInfo(jsonData, info)
|
||||
if err != nil {
|
||||
return nil, newAPIErrorFromParamOverride(err)
|
||||
}
|
||||
}
|
||||
|
||||
body, closer, err := relaycommon.NewOutboundJSONBody(jsonData)
|
||||
if err != nil {
|
||||
return nil, types.NewError(err, types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
defer closer.Close()
|
||||
jsonData = nil
|
||||
var requestBody io.Reader = body
|
||||
|
||||
var httpResp *http.Response
|
||||
resp, err := adaptor.DoRequest(c, info, requestBody)
|
||||
if err != nil {
|
||||
return nil, types.NewOpenAIError(err, types.ErrorCodeDoRequestFailed, http.StatusInternalServerError)
|
||||
}
|
||||
if resp == nil {
|
||||
return nil, types.NewOpenAIError(nil, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
statusCodeMappingStr := c.GetString("status_code_mapping")
|
||||
|
||||
httpResp = resp.(*http.Response)
|
||||
clientStream := info.IsStream
|
||||
upstreamStream := isResponsesEventStreamContentType(httpResp.Header.Get("Content-Type"))
|
||||
info.IsStream = clientStream || upstreamStream
|
||||
if httpResp.StatusCode != http.StatusOK {
|
||||
newApiErr := service.RelayErrorHandler(c.Request.Context(), httpResp, false)
|
||||
service.ResetStatusCode(newApiErr, statusCodeMappingStr)
|
||||
return nil, newApiErr
|
||||
}
|
||||
|
||||
if upstreamStream && clientStream {
|
||||
usage, newApiErr := openaichannel.OaiResponsesToChatStreamHandler(c, info, httpResp)
|
||||
if newApiErr != nil {
|
||||
service.ResetStatusCode(newApiErr, statusCodeMappingStr)
|
||||
return nil, newApiErr
|
||||
}
|
||||
return usage, nil
|
||||
}
|
||||
if upstreamStream {
|
||||
info.IsStream = false
|
||||
usage, newApiErr := openaichannel.OaiResponsesToChatBufferedStreamHandler(c, info, httpResp)
|
||||
if newApiErr != nil {
|
||||
service.ResetStatusCode(newApiErr, statusCodeMappingStr)
|
||||
return nil, newApiErr
|
||||
}
|
||||
return usage, nil
|
||||
}
|
||||
|
||||
usage, newApiErr := openaichannel.OaiResponsesToChatHandler(c, info, httpResp)
|
||||
if newApiErr != nil {
|
||||
service.ResetStatusCode(newApiErr, statusCodeMappingStr)
|
||||
return nil, newApiErr
|
||||
}
|
||||
return usage, nil
|
||||
}
|
||||
|
||||
func isResponsesEventStreamContentType(contentType string) bool {
|
||||
return strings.Contains(strings.ToLower(contentType), "text/event-stream")
|
||||
}
|
||||
Reference in new issue
Block a user