feat: sync deployed v1.0.0-rc.38-custom.42
Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
This commit is contained in:
1 parent
aa6c3f50f4
commit
ceddfd3d6b
828 files changed
+122253
-13702
No files matched your search
@@ -77,15 +77,7 @@ func (a *Adaptor) ConvertClaudeRequest(c *gin.Context, info *relaycommon.RelayIn
|
||||
case relayconvert.ConverterNone:
|
||||
return a.claudeAdaptor.ConvertClaudeRequest(c, info, request)
|
||||
case relayconvert.ConverterClaudeMessagesToOpenAIChat:
|
||||
result, err := service.ConvertRequestByID(c, info, converter, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chatRequest, ok := result.Value.(*dto.GeneralOpenAIRequest)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected OpenAI chat completions request, got %T", result.Value)
|
||||
}
|
||||
return a.convertOpenAICompatibleRequest(c, info, chatRequest)
|
||||
return a.convertCrossProtocolChatRequest(c, info, converter, request)
|
||||
default:
|
||||
return nil, fmt.Errorf("converter %q does not support Anthropic Messages requests", converter)
|
||||
}
|
||||
@@ -101,15 +93,7 @@ func (a *Adaptor) ConvertGeminiRequest(c *gin.Context, info *relaycommon.RelayIn
|
||||
case relayconvert.ConverterNone:
|
||||
return a.geminiAdaptor.ConvertGeminiRequest(c, info, request)
|
||||
case relayconvert.ConverterGeminiContentToOpenAIChat:
|
||||
result, err := service.ConvertRequestByID(c, info, converter, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chatRequest, ok := result.Value.(*dto.GeneralOpenAIRequest)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected OpenAI chat completions request, got %T", result.Value)
|
||||
}
|
||||
return a.convertOpenAICompatibleRequest(c, info, chatRequest)
|
||||
return a.convertCrossProtocolChatRequest(c, info, converter, request)
|
||||
default:
|
||||
return nil, fmt.Errorf("converter %q does not support Gemini generateContent requests", converter)
|
||||
}
|
||||
@@ -124,15 +108,7 @@ func (a *Adaptor) ConvertOpenAIResponsesRequest(c *gin.Context, info *relaycommo
|
||||
case relayconvert.ConverterNone:
|
||||
return a.convertOpenAICompatibleResponsesRequest(c, info, request)
|
||||
case relayconvert.ConverterOpenAIResponsesToOpenAIChat:
|
||||
result, err := service.ConvertRequestByID(c, info, converter, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chatRequest, ok := result.Value.(*dto.GeneralOpenAIRequest)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected OpenAI chat completions request, got %T", result.Value)
|
||||
}
|
||||
return a.convertOpenAICompatibleRequest(c, info, chatRequest)
|
||||
return a.convertCrossProtocolChatRequest(c, info, converter, request)
|
||||
case relayconvert.ConverterOpenAIResponsesToGemini:
|
||||
result, err := service.ConvertRequestByID(c, info, converter, request)
|
||||
if err != nil {
|
||||
@@ -286,7 +262,7 @@ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, request
|
||||
if err := a.resolve(c, info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !a.converted && a.converter != relayconvert.ConverterNone {
|
||||
if !a.converted && !a.route.SupportsPassThroughBody() {
|
||||
return nil, errors.New("advanced custom converter routes cannot be used with pass-through request body")
|
||||
}
|
||||
|
||||
@@ -307,6 +283,8 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
|
||||
}
|
||||
|
||||
switch a.converter {
|
||||
case dto.AdvancedCustomConverterSGLangRerank:
|
||||
return a.doSGLangRerankResponse(c, resp, info)
|
||||
case relayconvert.ConverterNone:
|
||||
return a.doNativeResponse(c, resp, info)
|
||||
case relayconvert.ConverterClaudeMessagesToOpenAIChat,
|
||||
@@ -534,6 +512,25 @@ func isJSONRequest(c *gin.Context) bool {
|
||||
return strings.Contains(strings.ToLower(c.Request.Header.Get("Content-Type")), "application/json")
|
||||
}
|
||||
|
||||
// convertCrossProtocolChatRequest converts a Claude, Gemini, or Responses request into an
|
||||
// OpenAI chat completions request for an OpenAI-compatible upstream. Streaming requests
|
||||
// always ask the upstream for usage, because the downstream protocol reports usage in its
|
||||
// own format and never carries stream_options itself.
|
||||
func (a *Adaptor) convertCrossProtocolChatRequest(c *gin.Context, info *relaycommon.RelayInfo, converter string, request any) (any, error) {
|
||||
result, err := service.ConvertRequestByID(c, info, converter, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chatRequest, ok := result.Value.(*dto.GeneralOpenAIRequest)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected OpenAI chat completions request, got %T", result.Value)
|
||||
}
|
||||
if info.SupportStreamOptions && info.IsStream {
|
||||
chatRequest.StreamOptions = &dto.StreamOptions{IncludeUsage: true}
|
||||
}
|
||||
return a.convertOpenAICompatibleRequest(c, info, chatRequest)
|
||||
}
|
||||
|
||||
func (a *Adaptor) convertOpenAICompatibleRequest(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeneralOpenAIRequest) (any, error) {
|
||||
old := info.ChannelType
|
||||
info.ChannelType = constant.ChannelTypeOpenAI
|
||||
|
||||
@@ -829,6 +829,143 @@ func TestAdaptorConvertsGeminiRequestToOpenAIChatUpstream(t *testing.T) {
|
||||
assert.Equal(t, "user", chatReq.Messages[0].Role)
|
||||
}
|
||||
|
||||
func TestAdaptorCrossProtocolChatUpstreamRequestsStreamUsage(t *testing.T) {
|
||||
claudeReq := &dto.ClaudeRequest{
|
||||
Model: "gpt-test",
|
||||
Messages: []dto.ClaudeMessage{{Role: "user", Content: "hello"}},
|
||||
}
|
||||
geminiReq := &dto.GeminiChatRequest{
|
||||
Contents: []dto.GeminiChatContent{{Role: "user", Parts: []dto.GeminiPart{{Text: "hello"}}}},
|
||||
}
|
||||
responsesReq := dto.OpenAIResponsesRequest{
|
||||
Model: "gpt-test",
|
||||
Input: mustAdvancedCustomRawMessage(t, "hello"),
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
route dto.AdvancedCustomRoute
|
||||
relayFormat types.RelayFormat
|
||||
relayMode int
|
||||
requestPath string
|
||||
convert func(*Adaptor, *gin.Context, *relaycommon.RelayInfo) (any, error)
|
||||
isStream bool
|
||||
supportUsage bool
|
||||
wantUsage bool
|
||||
}{
|
||||
{
|
||||
name: "claude stream requests usage",
|
||||
route: dto.AdvancedCustomRoute{
|
||||
IncomingPath: "/v1/messages",
|
||||
UpstreamPath: "/v1/chat/completions",
|
||||
Converter: relayconvert.ConverterClaudeMessagesToOpenAIChat,
|
||||
},
|
||||
relayFormat: types.RelayFormatClaude,
|
||||
relayMode: relayconstant.RelayModeChatCompletions,
|
||||
requestPath: "/v1/messages",
|
||||
convert: func(a *Adaptor, c *gin.Context, info *relaycommon.RelayInfo) (any, error) {
|
||||
return a.ConvertClaudeRequest(c, info, claudeReq)
|
||||
},
|
||||
isStream: true,
|
||||
supportUsage: true,
|
||||
wantUsage: true,
|
||||
},
|
||||
{
|
||||
name: "gemini stream requests usage",
|
||||
route: dto.AdvancedCustomRoute{
|
||||
IncomingPath: "/v1beta/models/{model}:generateContent",
|
||||
UpstreamPath: "/v1/chat/completions",
|
||||
Converter: relayconvert.ConverterGeminiContentToOpenAIChat,
|
||||
},
|
||||
relayFormat: types.RelayFormatGemini,
|
||||
relayMode: relayconstant.RelayModeGemini,
|
||||
requestPath: "/v1beta/models/gpt-test:generateContent",
|
||||
convert: func(a *Adaptor, c *gin.Context, info *relaycommon.RelayInfo) (any, error) {
|
||||
return a.ConvertGeminiRequest(c, info, geminiReq)
|
||||
},
|
||||
isStream: true,
|
||||
supportUsage: true,
|
||||
wantUsage: true,
|
||||
},
|
||||
{
|
||||
name: "responses stream requests usage",
|
||||
route: dto.AdvancedCustomRoute{
|
||||
IncomingPath: "/v1/responses",
|
||||
UpstreamPath: "/v1/chat/completions",
|
||||
Converter: relayconvert.ConverterOpenAIResponsesToOpenAIChat,
|
||||
},
|
||||
relayFormat: types.RelayFormatOpenAIResponses,
|
||||
relayMode: relayconstant.RelayModeResponses,
|
||||
requestPath: "/v1/responses",
|
||||
convert: func(a *Adaptor, c *gin.Context, info *relaycommon.RelayInfo) (any, error) {
|
||||
return a.ConvertOpenAIResponsesRequest(c, info, responsesReq)
|
||||
},
|
||||
isStream: true,
|
||||
supportUsage: true,
|
||||
wantUsage: true,
|
||||
},
|
||||
{
|
||||
name: "claude non-stream leaves stream options unset",
|
||||
route: dto.AdvancedCustomRoute{
|
||||
IncomingPath: "/v1/messages",
|
||||
UpstreamPath: "/v1/chat/completions",
|
||||
Converter: relayconvert.ConverterClaudeMessagesToOpenAIChat,
|
||||
},
|
||||
relayFormat: types.RelayFormatClaude,
|
||||
relayMode: relayconstant.RelayModeChatCompletions,
|
||||
requestPath: "/v1/messages",
|
||||
convert: func(a *Adaptor, c *gin.Context, info *relaycommon.RelayInfo) (any, error) {
|
||||
return a.ConvertClaudeRequest(c, info, claudeReq)
|
||||
},
|
||||
isStream: false,
|
||||
supportUsage: true,
|
||||
wantUsage: false,
|
||||
},
|
||||
{
|
||||
name: "claude stream without stream options support",
|
||||
route: dto.AdvancedCustomRoute{
|
||||
IncomingPath: "/v1/messages",
|
||||
UpstreamPath: "/v1/chat/completions",
|
||||
Converter: relayconvert.ConverterClaudeMessagesToOpenAIChat,
|
||||
},
|
||||
relayFormat: types.RelayFormatClaude,
|
||||
relayMode: relayconstant.RelayModeChatCompletions,
|
||||
requestPath: "/v1/messages",
|
||||
convert: func(a *Adaptor, c *gin.Context, info *relaycommon.RelayInfo) (any, error) {
|
||||
return a.ConvertClaudeRequest(c, info, claudeReq)
|
||||
},
|
||||
isStream: true,
|
||||
supportUsage: false,
|
||||
wantUsage: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
adaptor := &Adaptor{}
|
||||
info := advancedCustomRelayInfo(&dto.AdvancedCustomConfig{Routes: []dto.AdvancedCustomRoute{tt.route}})
|
||||
info.RelayFormat = tt.relayFormat
|
||||
info.RelayMode = tt.relayMode
|
||||
info.RequestURLPath = tt.requestPath
|
||||
info.IsStream = tt.isStream
|
||||
info.SupportStreamOptions = tt.supportUsage
|
||||
c := advancedCustomGinContext(tt.requestPath)
|
||||
|
||||
converted, err := tt.convert(adaptor, c, info)
|
||||
require.NoError(t, err)
|
||||
chatReq, ok := converted.(*dto.GeneralOpenAIRequest)
|
||||
require.True(t, ok)
|
||||
|
||||
if !tt.wantUsage {
|
||||
assert.Nil(t, chatReq.StreamOptions)
|
||||
return
|
||||
}
|
||||
require.NotNil(t, chatReq.StreamOptions)
|
||||
assert.True(t, chatReq.StreamOptions.IncludeUsage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func advancedCustomRelayInfo(config *dto.AdvancedCustomConfig) *relaycommon.RelayInfo {
|
||||
return &relaycommon.RelayInfo{
|
||||
RelayFormat: types.RelayFormatOpenAI,
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package advancedcustom_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/QuantumNous/new-api/common"
|
||||
"github.com/QuantumNous/new-api/constant"
|
||||
"github.com/QuantumNous/new-api/relay"
|
||||
"github.com/QuantumNous/new-api/relay/channel/advancedcustom"
|
||||
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"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSGLangChannelProtocols(t *testing.T) {
|
||||
apiType, ok := common.ChannelType2APIType(constant.ChannelTypeSGLang)
|
||||
require.True(t, ok)
|
||||
adaptor := relay.GetAdaptor(apiType)
|
||||
require.NotNil(t, adaptor)
|
||||
assert.Equal(t, "advanced_custom", adaptor.GetChannelName())
|
||||
assert.Contains(t, common.GetEndpointTypesByChannelType(constant.ChannelTypeSGLang, "served-model"), constant.EndpointTypeAnthropic)
|
||||
assert.Contains(t, common.GetEndpointTypesByChannelType(constant.ChannelTypeSGLang, "served-model"), constant.EndpointTypeOpenAIResponse)
|
||||
info := &relaycommon.RelayInfo{ChannelMeta: &relaycommon.ChannelMeta{ChannelType: constant.ChannelTypeSGLang, ChannelBaseUrl: "https://inference.example/prefix", ApiKey: "test-key"}}
|
||||
info.ChannelOtherSettings.AdvancedCustom = common.GetAdvancedCustomPreset(constant.ChannelTypeSGLang)
|
||||
adaptor.Init(info)
|
||||
for _, path := range []string{"/v1/chat/completions", "/v1/completions", "/v1/embeddings", "/v1/responses", "/v1/messages"} {
|
||||
info.RequestURLPath = path
|
||||
adaptor = &advancedcustom.Adaptor{}
|
||||
adaptor.Init(info)
|
||||
url, err := adaptor.GetRequestURL(info)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "https://inference.example/prefix"+path, url)
|
||||
}
|
||||
for _, format := range []types.RelayFormat{types.RelayFormatOpenAI, types.RelayFormatClaude} {
|
||||
info.RelayFormat = format
|
||||
info.RequestURLPath = "/v1/messages"
|
||||
adaptor = &advancedcustom.Adaptor{}
|
||||
adaptor.Init(info)
|
||||
c, _ := gin.CreateTestContext(httptest.NewRecorder())
|
||||
c.Request = httptest.NewRequest(http.MethodPost, "/v1/messages", nil)
|
||||
headers := http.Header{}
|
||||
require.NoError(t, adaptor.SetupRequestHeader(c, &headers, info))
|
||||
assert.Equal(t, "Bearer test-key", headers.Get("Authorization"))
|
||||
}
|
||||
info.RequestURLPath = "/v1/chat/completions"
|
||||
adaptor = &advancedcustom.Adaptor{}
|
||||
adaptor.Init(info)
|
||||
c, _ := gin.CreateTestContext(httptest.NewRecorder())
|
||||
c.Request = httptest.NewRequest(http.MethodPost, "/v1/chat/completions", nil)
|
||||
request := &dto.GeneralOpenAIRequest{Model: "served-model"}
|
||||
converted, err := adaptor.ConvertOpenAIRequest(c, info, request)
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, request, converted)
|
||||
info.RequestURLPath = "/v1/messages"
|
||||
adaptor = &advancedcustom.Adaptor{}
|
||||
adaptor.Init(info)
|
||||
c.Request = httptest.NewRequest(http.MethodPost, "/v1/messages", nil)
|
||||
claudeRequest := &dto.ClaudeRequest{Model: "served-model", Thinking: &dto.Thinking{Type: "adaptive"}}
|
||||
converted, err = adaptor.ConvertClaudeRequest(c, info, claudeRequest)
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, claudeRequest, converted)
|
||||
info.RequestURLPath = "/v1beta/models/test:generateContent"
|
||||
adaptor = &advancedcustom.Adaptor{}
|
||||
adaptor.Init(info)
|
||||
_, err = adaptor.ConvertGeminiRequest(nil, info, &dto.GeminiChatRequest{})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestSGLangRerankRequestAndResponse(t *testing.T) {
|
||||
service.InitHttpClient()
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assert.Equal(t, "/prefix/v1/rerank", r.URL.Path)
|
||||
assert.Equal(t, "Bearer test-key", r.Header.Get("Authorization"))
|
||||
var request dto.RerankRequest
|
||||
require.NoError(t, common.DecodeJson(r.Body, &request))
|
||||
assert.Equal(t, "served-reranker", request.Model)
|
||||
assert.Equal(t, []any{"first", "second"}, request.Documents)
|
||||
_, _ = io.WriteString(w, `[{"index":1,"score":0.9,"document":"second","meta_info":{"prompt_tokens":5}}]`)
|
||||
}))
|
||||
defer upstream.Close()
|
||||
info := &relaycommon.RelayInfo{
|
||||
ChannelMeta: &relaycommon.ChannelMeta{ChannelType: constant.ChannelTypeSGLang, ChannelBaseUrl: upstream.URL + "/prefix", ApiKey: "test-key"},
|
||||
RequestURLPath: "/rerank", RelayMode: relayconstant.RelayModeRerank,
|
||||
RelayFormat: types.RelayFormatOpenAI,
|
||||
RerankerInfo: &relaycommon.RerankerInfo{Documents: []any{"first", "second"}, ReturnDocuments: true},
|
||||
}
|
||||
info.SetEstimatePromptTokens(12)
|
||||
adaptor := &advancedcustom.Adaptor{}
|
||||
info.ChannelOtherSettings.AdvancedCustom = common.GetAdvancedCustomPreset(constant.ChannelTypeSGLang)
|
||||
adaptor.Init(info)
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
c.Request = httptest.NewRequest(http.MethodPost, "/rerank", nil).WithContext(context.Background())
|
||||
converted, err := adaptor.ConvertRerankRequest(c, info.RelayMode, dto.RerankRequest{Model: "served-reranker", Query: "query", Documents: info.Documents})
|
||||
require.NoError(t, err)
|
||||
body, err := common.Marshal(converted)
|
||||
require.NoError(t, err)
|
||||
response, err := adaptor.DoRequest(c, info, bytes.NewReader(body))
|
||||
require.NoError(t, err)
|
||||
usage, apiErr := adaptor.DoResponse(c, response.(*http.Response), info)
|
||||
require.Nil(t, apiErr)
|
||||
assert.Equal(t, 12, usage.(*dto.Usage).TotalTokens)
|
||||
var decoded dto.RerankResponse
|
||||
require.NoError(t, common.Unmarshal(recorder.Body.Bytes(), &decoded))
|
||||
assert.Equal(t, []dto.RerankResponseResult{{Index: 1, RelevanceScore: 0.9, Document: map[string]any{"text": "second"}}}, decoded.Results)
|
||||
assert.Equal(t, 12, decoded.Usage.PromptTokens)
|
||||
assert.Zero(t, decoded.Usage.CompletionTokens)
|
||||
}
|
||||
|
||||
func TestSGLangRerankRejectsMalformedResults(t *testing.T) {
|
||||
for _, body := range []string{`null`, `{}`, `[{"index":99,"score":1}]`, `[{"index":-1,"score":0}]`, `[{"index":0}]`, `[{"score":1}]`} {
|
||||
t.Run(body, func(t *testing.T) {
|
||||
adaptor := &advancedcustom.Adaptor{}
|
||||
info := &relaycommon.RelayInfo{ChannelMeta: &relaycommon.ChannelMeta{ChannelOtherSettings: dto.ChannelOtherSettings{AdvancedCustom: common.GetAdvancedCustomPreset(constant.ChannelTypeSGLang)}}, RequestURLPath: "/v1/rerank", RelayMode: relayconstant.RelayModeRerank, RerankerInfo: &relaycommon.RerankerInfo{Documents: []any{"only document"}}}
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
usage, err := adaptor.DoResponse(c, &http.Response{Body: io.NopCloser(strings.NewReader(body))}, info)
|
||||
require.NotNil(t, err)
|
||||
assert.Nil(t, usage)
|
||||
assert.Empty(t, recorder.Body.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package advancedcustom
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/QuantumNous/new-api/common"
|
||||
relaycommon "github.com/QuantumNous/new-api/relay/common"
|
||||
"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 (a *Adaptor) doSGLangRerankResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (any, *types.NewAPIError) {
|
||||
defer service.CloseResponseBodyGracefully(resp)
|
||||
// SGLang v0.5.19 returns a sorted array with score, not a Jina results envelope.
|
||||
// https://github.com/sgl-project/sglang/blob/v0.5.19/python/sglang/srt/entrypoints/openai/serving_rerank.py
|
||||
var results []struct {
|
||||
Index *int `json:"index"`
|
||||
Score *float64 `json:"score"`
|
||||
}
|
||||
if err := common.DecodeJson(resp.Body, &results); err != nil {
|
||||
return nil, types.NewOpenAIError(err, types.ErrorCodeBadResponseBody, http.StatusBadGateway)
|
||||
}
|
||||
if results == nil {
|
||||
return nil, types.NewOpenAIError(errors.New("invalid SGLang rerank response"), types.ErrorCodeBadResponseBody, http.StatusBadGateway)
|
||||
}
|
||||
response := dto.RerankResponse{Results: make([]dto.RerankResponseResult, 0, len(results))}
|
||||
for _, result := range results {
|
||||
if result.Index == nil || result.Score == nil || *result.Index < 0 || *result.Index >= len(info.Documents) {
|
||||
return nil, types.NewOpenAIError(errors.New("invalid SGLang rerank result"), types.ErrorCodeBadResponseBody, http.StatusBadGateway)
|
||||
}
|
||||
item := dto.RerankResponseResult{Index: *result.Index, RelevanceScore: *result.Score}
|
||||
if info.ReturnDocuments {
|
||||
item.Document = dto.RerankDocument{Text: info.Documents[*result.Index]}
|
||||
}
|
||||
response.Results = append(response.Results, item)
|
||||
}
|
||||
// top_n can omit scored documents, and decoder rerankers can omit meta_info.
|
||||
// Per-result counts therefore cannot account for the full request; use the
|
||||
// existing prompt estimate, as with other rerank providers without usage.
|
||||
response.Usage = dto.Usage{PromptTokens: info.GetEstimatePromptTokens(), TotalTokens: info.GetEstimatePromptTokens()}
|
||||
c.JSON(http.StatusOK, response)
|
||||
return &response.Usage, nil
|
||||
}
|
||||
Reference in new issue
Block a user