mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-03-30 02:25:00 +00:00
fix: Fix Openrouter test errors and optimize error messages (#2433)
* fix: Refine openrouter error * fix: Refine openrouter error * fix: openrouter test max_output_token * fix: optimize messages * fix: maxToken unified to 16 * fix: codex系列模型使用 responses接口 * fix: codex系列模型使用 responses接口 * fix: 状态码非200打印错误信息 * fix: 日志里没有报错的响应体
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -23,3 +23,4 @@ web/bun.lock
|
|||||||
electron/node_modules
|
electron/node_modules
|
||||||
electron/dist
|
electron/dist
|
||||||
data/
|
data/
|
||||||
|
.gomodcache/
|
||||||
@@ -97,6 +97,11 @@ func testChannel(channel *model.Channel, testModel string, endpointType string)
|
|||||||
if channel.Type == constant.ChannelTypeVolcEngine && strings.Contains(testModel, "seedream") {
|
if channel.Type == constant.ChannelTypeVolcEngine && strings.Contains(testModel, "seedream") {
|
||||||
requestPath = "/v1/images/generations"
|
requestPath = "/v1/images/generations"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// responses-only models
|
||||||
|
if strings.Contains(strings.ToLower(testModel), "codex") {
|
||||||
|
requestPath = "/v1/responses"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Request = &http.Request{
|
c.Request = &http.Request{
|
||||||
@@ -176,7 +181,7 @@ func testChannel(channel *model.Channel, testModel string, endpointType string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request := buildTestRequest(testModel, endpointType)
|
request := buildTestRequest(testModel, endpointType, channel)
|
||||||
|
|
||||||
info, err := relaycommon.GenRelayInfo(c, relayFormat, request, nil)
|
info, err := relaycommon.GenRelayInfo(c, relayFormat, request, nil)
|
||||||
|
|
||||||
@@ -319,6 +324,16 @@ func testChannel(channel *model.Channel, testModel string, endpointType string)
|
|||||||
httpResp = resp.(*http.Response)
|
httpResp = resp.(*http.Response)
|
||||||
if httpResp.StatusCode != http.StatusOK {
|
if httpResp.StatusCode != http.StatusOK {
|
||||||
err := service.RelayErrorHandler(c.Request.Context(), httpResp, true)
|
err := service.RelayErrorHandler(c.Request.Context(), httpResp, true)
|
||||||
|
common.SysError(fmt.Sprintf(
|
||||||
|
"channel test bad response: channel_id=%d name=%s type=%d model=%s endpoint_type=%s status=%d err=%v",
|
||||||
|
channel.Id,
|
||||||
|
channel.Name,
|
||||||
|
channel.Type,
|
||||||
|
testModel,
|
||||||
|
endpointType,
|
||||||
|
httpResp.StatusCode,
|
||||||
|
err,
|
||||||
|
))
|
||||||
return testResult{
|
return testResult{
|
||||||
context: c,
|
context: c,
|
||||||
localErr: err,
|
localErr: err,
|
||||||
@@ -389,7 +404,7 @@ func testChannel(channel *model.Channel, testModel string, endpointType string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildTestRequest(model string, endpointType string) dto.Request {
|
func buildTestRequest(model string, endpointType string, channel *model.Channel) dto.Request {
|
||||||
// 根据端点类型构建不同的测试请求
|
// 根据端点类型构建不同的测试请求
|
||||||
if endpointType != "" {
|
if endpointType != "" {
|
||||||
switch constant.EndpointType(endpointType) {
|
switch constant.EndpointType(endpointType) {
|
||||||
@@ -423,7 +438,7 @@ func buildTestRequest(model string, endpointType string) dto.Request {
|
|||||||
}
|
}
|
||||||
case constant.EndpointTypeAnthropic, constant.EndpointTypeGemini, constant.EndpointTypeOpenAI:
|
case constant.EndpointTypeAnthropic, constant.EndpointTypeGemini, constant.EndpointTypeOpenAI:
|
||||||
// 返回 GeneralOpenAIRequest
|
// 返回 GeneralOpenAIRequest
|
||||||
maxTokens := uint(10)
|
maxTokens := uint(16)
|
||||||
if constant.EndpointType(endpointType) == constant.EndpointTypeGemini {
|
if constant.EndpointType(endpointType) == constant.EndpointTypeGemini {
|
||||||
maxTokens = 3000
|
maxTokens = 3000
|
||||||
}
|
}
|
||||||
@@ -453,6 +468,14 @@ func buildTestRequest(model string, endpointType string) dto.Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Responses-only models (e.g. codex series)
|
||||||
|
if strings.Contains(strings.ToLower(model), "codex") {
|
||||||
|
return &dto.OpenAIResponsesRequest{
|
||||||
|
Model: model,
|
||||||
|
Input: json.RawMessage("\"hi\""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Chat/Completion 请求 - 返回 GeneralOpenAIRequest
|
// Chat/Completion 请求 - 返回 GeneralOpenAIRequest
|
||||||
testRequest := &dto.GeneralOpenAIRequest{
|
testRequest := &dto.GeneralOpenAIRequest{
|
||||||
Model: model,
|
Model: model,
|
||||||
@@ -466,7 +489,7 @@ func buildTestRequest(model string, endpointType string) dto.Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(model, "o") {
|
if strings.HasPrefix(model, "o") {
|
||||||
testRequest.MaxCompletionTokens = 10
|
testRequest.MaxCompletionTokens = 16
|
||||||
} else if strings.Contains(model, "thinking") {
|
} else if strings.Contains(model, "thinking") {
|
||||||
if !strings.Contains(model, "claude") {
|
if !strings.Contains(model, "claude") {
|
||||||
testRequest.MaxTokens = 50
|
testRequest.MaxTokens = 50
|
||||||
@@ -474,7 +497,7 @@ func buildTestRequest(model string, endpointType string) dto.Request {
|
|||||||
} else if strings.Contains(model, "gemini") {
|
} else if strings.Contains(model, "gemini") {
|
||||||
testRequest.MaxTokens = 3000
|
testRequest.MaxTokens = 3000
|
||||||
} else {
|
} else {
|
||||||
testRequest.MaxTokens = 10
|
testRequest.MaxTokens = 16
|
||||||
}
|
}
|
||||||
|
|
||||||
return testRequest
|
return testRequest
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type GeneralErrorResponse struct {
|
|||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
Err string `json:"err"`
|
Err string `json:"err"`
|
||||||
ErrorMsg string `json:"error_msg"`
|
ErrorMsg string `json:"error_msg"`
|
||||||
|
Metadata json.RawMessage `json:"metadata,omitempty"`
|
||||||
Header struct {
|
Header struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
} `json:"header"`
|
} `json:"header"`
|
||||||
|
|||||||
@@ -90,11 +90,17 @@ func RelayErrorHandler(ctx context.Context, resp *http.Response, showBodyWhenFai
|
|||||||
}
|
}
|
||||||
CloseResponseBodyGracefully(resp)
|
CloseResponseBodyGracefully(resp)
|
||||||
var errResponse dto.GeneralErrorResponse
|
var errResponse dto.GeneralErrorResponse
|
||||||
|
buildErrWithBody := func(message string) error {
|
||||||
|
if message == "" {
|
||||||
|
return fmt.Errorf("bad response status code %d, body: %s", resp.StatusCode, string(responseBody))
|
||||||
|
}
|
||||||
|
return fmt.Errorf("bad response status code %d, message: %s, body: %s", resp.StatusCode, message, string(responseBody))
|
||||||
|
}
|
||||||
|
|
||||||
err = common.Unmarshal(responseBody, &errResponse)
|
err = common.Unmarshal(responseBody, &errResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if showBodyWhenFail {
|
if showBodyWhenFail {
|
||||||
newApiErr.Err = fmt.Errorf("bad response status code %d, body: %s", resp.StatusCode, string(responseBody))
|
newApiErr.Err = buildErrWithBody("")
|
||||||
} else {
|
} else {
|
||||||
logger.LogError(ctx, fmt.Sprintf("bad response status code %d, body: %s", resp.StatusCode, string(responseBody)))
|
logger.LogError(ctx, fmt.Sprintf("bad response status code %d, body: %s", resp.StatusCode, string(responseBody)))
|
||||||
newApiErr.Err = fmt.Errorf("bad response status code %d", resp.StatusCode)
|
newApiErr.Err = fmt.Errorf("bad response status code %d", resp.StatusCode)
|
||||||
@@ -107,10 +113,16 @@ func RelayErrorHandler(ctx context.Context, resp *http.Response, showBodyWhenFai
|
|||||||
oaiError := errResponse.TryToOpenAIError()
|
oaiError := errResponse.TryToOpenAIError()
|
||||||
if oaiError != nil {
|
if oaiError != nil {
|
||||||
newApiErr = types.WithOpenAIError(*oaiError, resp.StatusCode)
|
newApiErr = types.WithOpenAIError(*oaiError, resp.StatusCode)
|
||||||
|
if showBodyWhenFail {
|
||||||
|
newApiErr.Err = buildErrWithBody(newApiErr.Error())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newApiErr = types.NewOpenAIError(errors.New(errResponse.ToMessage()), types.ErrorCodeBadResponseStatusCode, resp.StatusCode)
|
newApiErr = types.NewOpenAIError(errors.New(errResponse.ToMessage()), types.ErrorCodeBadResponseStatusCode, resp.StatusCode)
|
||||||
|
if showBodyWhenFail {
|
||||||
|
newApiErr.Err = buildErrWithBody(newApiErr.Error())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -10,10 +11,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type OpenAIError struct {
|
type OpenAIError struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Param string `json:"param"`
|
Param string `json:"param"`
|
||||||
Code any `json:"code"`
|
Code any `json:"code"`
|
||||||
|
Metadata json.RawMessage `json:"metadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClaudeError struct {
|
type ClaudeError struct {
|
||||||
@@ -92,6 +94,7 @@ type NewAPIError struct {
|
|||||||
errorType ErrorType
|
errorType ErrorType
|
||||||
errorCode ErrorCode
|
errorCode ErrorCode
|
||||||
StatusCode int
|
StatusCode int
|
||||||
|
Metadata json.RawMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap enables errors.Is / errors.As to work with NewAPIError by exposing the underlying error.
|
// Unwrap enables errors.Is / errors.As to work with NewAPIError by exposing the underlying error.
|
||||||
@@ -301,6 +304,13 @@ func WithOpenAIError(openAIError OpenAIError, statusCode int, ops ...NewAPIError
|
|||||||
Err: errors.New(openAIError.Message),
|
Err: errors.New(openAIError.Message),
|
||||||
errorCode: ErrorCode(code),
|
errorCode: ErrorCode(code),
|
||||||
}
|
}
|
||||||
|
// OpenRouter
|
||||||
|
if len(openAIError.Metadata) > 0 {
|
||||||
|
openAIError.Message = fmt.Sprintf("%s (%s)", openAIError.Message, openAIError.Metadata)
|
||||||
|
e.Metadata = openAIError.Metadata
|
||||||
|
e.RelayError = openAIError
|
||||||
|
e.Err = errors.New(openAIError.Message)
|
||||||
|
}
|
||||||
for _, op := range ops {
|
for _, op := range ops {
|
||||||
op(e)
|
op(e)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user