From 57059ac73fcb6c159f4ee827e7949ce5bcb16a8c Mon Sep 17 00:00:00 2001 From: Seefs Date: Fri, 6 Feb 2026 23:03:58 +0800 Subject: [PATCH] fix: /v1/chat/completions -> /v1/responses json_schema --- service/openaicompat/chat_to_responses.go | 49 ++++++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/service/openaicompat/chat_to_responses.go b/service/openaicompat/chat_to_responses.go index 76aa6d25d..c2b44c902 100644 --- a/service/openaicompat/chat_to_responses.go +++ b/service/openaicompat/chat_to_responses.go @@ -34,6 +34,44 @@ func normalizeChatImageURLToString(v any) any { } } +func convertChatResponseFormatToResponsesText(reqFormat *dto.ResponseFormat) json.RawMessage { + if reqFormat == nil || strings.TrimSpace(reqFormat.Type) == "" { + return nil + } + + format := map[string]any{ + "type": reqFormat.Type, + } + + if reqFormat.Type == "json_schema" && len(reqFormat.JsonSchema) > 0 { + var chatSchema map[string]any + if err := common.Unmarshal(reqFormat.JsonSchema, &chatSchema); err == nil { + for key, value := range chatSchema { + if key == "type" { + continue + } + format[key] = value + } + + if nested, ok := format["json_schema"].(map[string]any); ok { + for key, value := range nested { + if _, exists := format[key]; !exists { + format[key] = value + } + } + delete(format, "json_schema") + } + } else { + format["json_schema"] = reqFormat.JsonSchema + } + } + + textRaw, _ := common.Marshal(map[string]any{ + "format": format, + }) + return textRaw +} + func ChatCompletionsRequestToResponsesRequest(req *dto.GeneralOpenAIRequest) (*dto.OpenAIResponsesRequest, error) { if req == nil { return nil, errors.New("request is nil") @@ -312,17 +350,16 @@ func ChatCompletionsRequestToResponsesRequest(req *dto.GeneralOpenAIRequest) (*d parallelToolCallsRaw, _ = common.Marshal(*req.ParallelTooCalls) } - var textRaw json.RawMessage - if req.ResponseFormat != nil && req.ResponseFormat.Type != "" { - textRaw, _ = common.Marshal(map[string]any{ - "format": req.ResponseFormat, - }) - } + textRaw := convertChatResponseFormatToResponsesText(req.ResponseFormat) maxOutputTokens := req.MaxTokens if req.MaxCompletionTokens > maxOutputTokens { maxOutputTokens = req.MaxCompletionTokens } + // OpenAI Responses API rejects max_output_tokens < 16 when explicitly provided. + //if maxOutputTokens > 0 && maxOutputTokens < 16 { + // maxOutputTokens = 16 + //} var topP *float64 if req.TopP != 0 {