refactor(gateway): introduce OpenAI request view
Cache hot-path request scalars before full body decoding so later branches can avoid repeated map work while preserving current decode behavior.
This commit is contained in:
parent
34de99ee0e
commit
6a5f6b96b6
@ -2346,7 +2346,8 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
|
|||||||
}
|
}
|
||||||
|
|
||||||
originalBody := body
|
originalBody := body
|
||||||
reqModel, reqStream, promptCacheKey := extractOpenAIRequestMetaFromBody(body)
|
requestView := newOpenAIRequestView(body)
|
||||||
|
reqModel, reqStream, promptCacheKey := requestView.Model, requestView.Stream, requestView.PromptCacheKey
|
||||||
originalModel := reqModel
|
originalModel := reqModel
|
||||||
|
|
||||||
if account.Type == AccountTypeAPIKey && !openai_compat.ShouldUseResponsesAPI(account.Extra) {
|
if account.Type == AccountTypeAPIKey && !openai_compat.ShouldUseResponsesAPI(account.Extra) {
|
||||||
@ -2396,7 +2397,7 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
|
|||||||
return s.forwardOpenAIPassthrough(ctx, c, account, originalBody, reqModel, reasoningEffort, reqStream, startTime)
|
return s.forwardOpenAIPassthrough(ctx, c, account, originalBody, reqModel, reasoningEffort, reqStream, startTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqBody, err := getOpenAIRequestBodyMap(c, body)
|
reqBody, err := requestView.Decode(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6274,15 +6275,39 @@ func deriveOpenAIReasoningEffortFromModel(model string) string {
|
|||||||
return normalizeOpenAIReasoningEffort(parts[len(parts)-1])
|
return normalizeOpenAIReasoningEffort(parts[len(parts)-1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractOpenAIRequestMetaFromBody(body []byte) (model string, stream bool, promptCacheKey string) {
|
type openAIRequestView struct {
|
||||||
if len(body) == 0 {
|
body []byte
|
||||||
return "", false, ""
|
Model string
|
||||||
}
|
Stream bool
|
||||||
|
PromptCacheKey string
|
||||||
|
PreviousResponseID string
|
||||||
|
ServiceTier string
|
||||||
|
ReasoningEffort string
|
||||||
|
}
|
||||||
|
|
||||||
model = strings.TrimSpace(gjson.GetBytes(body, "model").String())
|
func newOpenAIRequestView(body []byte) openAIRequestView {
|
||||||
stream = gjson.GetBytes(body, "stream").Bool()
|
if len(body) == 0 {
|
||||||
promptCacheKey = strings.TrimSpace(gjson.GetBytes(body, "prompt_cache_key").String())
|
return openAIRequestView{}
|
||||||
return model, stream, promptCacheKey
|
}
|
||||||
|
return openAIRequestView{
|
||||||
|
body: body,
|
||||||
|
Model: strings.TrimSpace(gjson.GetBytes(body, "model").String()),
|
||||||
|
Stream: gjson.GetBytes(body, "stream").Bool(),
|
||||||
|
PromptCacheKey: strings.TrimSpace(gjson.GetBytes(body, "prompt_cache_key").String()),
|
||||||
|
PreviousResponseID: strings.TrimSpace(gjson.GetBytes(body, "previous_response_id").String()),
|
||||||
|
ServiceTier: strings.TrimSpace(gjson.GetBytes(body, "service_tier").String()),
|
||||||
|
ReasoningEffort: strings.TrimSpace(gjson.GetBytes(body, "reasoning.effort").String()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode 保留阶段一既有 full-map 行为;后续阶段会把调用点下沉到复杂分支。
|
||||||
|
func (v openAIRequestView) Decode(c *gin.Context) (map[string]any, error) {
|
||||||
|
return getOpenAIRequestBodyMap(c, v.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractOpenAIRequestMetaFromBody(body []byte) (model string, stream bool, promptCacheKey string) {
|
||||||
|
view := newOpenAIRequestView(body)
|
||||||
|
return view.Model, view.Stream, view.PromptCacheKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalizeOpenAIPassthroughOAuthBody 将透传 OAuth 请求体收敛为旧链路关键行为:
|
// normalizeOpenAIPassthroughOAuthBody 将透传 OAuth 请求体收敛为旧链路关键行为:
|
||||||
|
|||||||
@ -9,6 +9,26 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestOpenAIRequestView_ExtractsRawScalars(t *testing.T) {
|
||||||
|
view := newOpenAIRequestView([]byte(`{"model":" gpt-5 ","stream":true,"prompt_cache_key":" ses-1 ","previous_response_id":" resp-1 ","service_tier":" fast ","reasoning":{"effort":" medium "}}`))
|
||||||
|
|
||||||
|
require.Equal(t, "gpt-5", view.Model)
|
||||||
|
require.True(t, view.Stream)
|
||||||
|
require.Equal(t, "ses-1", view.PromptCacheKey)
|
||||||
|
require.Equal(t, "resp-1", view.PreviousResponseID)
|
||||||
|
require.Equal(t, "fast", view.ServiceTier)
|
||||||
|
require.Equal(t, "medium", view.ReasoningEffort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOpenAIRequestView_DecodeKeepsFullMapBehavior(t *testing.T) {
|
||||||
|
view := newOpenAIRequestView([]byte(`{"model":"gpt-5","stream":true,"input":[{"type":"message","content":"hi"}]}`))
|
||||||
|
|
||||||
|
reqBody, err := view.Decode(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "gpt-5", reqBody["model"])
|
||||||
|
require.IsType(t, []any{}, reqBody["input"])
|
||||||
|
}
|
||||||
|
|
||||||
func TestExtractOpenAIRequestMetaFromBody(t *testing.T) {
|
func TestExtractOpenAIRequestMetaFromBody(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user