From d68b6d45fcce18c63b76db5d99414fc295b22a56 Mon Sep 17 00:00:00 2001 From: redflyingfish <1250238459@qq.com> Date: Thu, 11 Jun 2026 14:26:11 +0800 Subject: [PATCH] fix(openai): support custom headers in chat model config --- components/model/openai/README.md | 4 +++ components/model/openai/README_zh.md | 4 +++ components/model/openai/chatmodel.go | 5 ++++ components/model/openai/chatmodel_test.go | 32 +++++++++++++++++++++++ components/model/openai/go.mod | 10 +++---- components/model/openai/go.sum | 13 +++++++++ 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/components/model/openai/README.md b/components/model/openai/README.md index b8f5ff43e..840e79de9 100644 --- a/components/model/openai/README.md +++ b/components/model/openai/README.md @@ -180,6 +180,10 @@ User *string `json:"user,omitempty"` // Optional. Useful for experimental features not yet officially supported. ExtraFields map[string]any `json:"extra_fields,omitempty"` +// CustomHeaders specifies custom HTTP headers to include in API requests. +// Optional. Useful for custom routing, tracing, or experimental gateway features. +CustomHeaders map[string]string `json:"custom_headers,omitempty"` + // ReasoningEffort will override the default reasoning level of "medium" // Optional. Useful for fine tuning response latency vs. accuracy ReasoningEffort ReasoningEffortLevel diff --git a/components/model/openai/README_zh.md b/components/model/openai/README_zh.md index 0f90d5651..4c85235bb 100644 --- a/components/model/openai/README_zh.md +++ b/components/model/openai/README_zh.md @@ -180,6 +180,10 @@ User *string `json:"user,omitempty"` // Optional. Useful for experimental features not yet officially supported. ExtraFields map[string]any `json:"extra_fields,omitempty"` +// CustomHeaders specifies custom HTTP headers to include in API requests. +// Optional. Useful for custom routing, tracing, or experimental gateway features. +CustomHeaders map[string]string `json:"custom_headers,omitempty"` + // ReasoningEffort will override the default reasoning level of "medium" // Optional. Useful for fine tuning response latency vs. accuracy ReasoningEffort ReasoningEffortLevel diff --git a/components/model/openai/chatmodel.go b/components/model/openai/chatmodel.go index 36314f0a1..551fd8b5c 100644 --- a/components/model/openai/chatmodel.go +++ b/components/model/openai/chatmodel.go @@ -179,6 +179,10 @@ type ChatModelConfig struct { // Optional. Useful for experimental features not yet officially supported. ExtraFields map[string]any `json:"extra_fields,omitempty"` + // CustomHeaders specifies custom HTTP headers to include in API requests. + // Optional. Useful for custom routing, tracing, or experimental gateway features. + CustomHeaders map[string]string `json:"custom_headers,omitempty"` + // ReasoningEffort will override the default reasoning level of "medium" // Optional. Useful for fine tuning response latency vs. accuracy ReasoningEffort ReasoningEffortLevel @@ -226,6 +230,7 @@ func NewChatModel(ctx context.Context, config *ChatModelConfig) (*ChatModel, err User: config.User, AzureModelMapperFunc: config.AzureModelMapperFunc, ExtraFields: config.ExtraFields, + CustomHeaders: config.CustomHeaders, ReasoningEffort: openai.ReasoningEffortLevel(config.ReasoningEffort), Modalities: config.Modalities, } diff --git a/components/model/openai/chatmodel_test.go b/components/model/openai/chatmodel_test.go index da00b8ae0..e3744133d 100644 --- a/components/model/openai/chatmodel_test.go +++ b/components/model/openai/chatmodel_test.go @@ -323,4 +323,36 @@ func TestOpenAIGenerate(t *testing.T) { t.Fatal(err) } }) + t.Run("custom headers from config", func(t *testing.T) { + defer mockey.Mock((*openai.Client).CreateChatCompletion).To(func(ctx context.Context, + request openai.ChatCompletionRequest, opts ...openai.ChatCompletionRequestOption) (response openai.ChatCompletionResponse, err error) { + if len(opts) != 1 { + t.Fatalf("expected one request option for custom headers, got %d", len(opts)) + } + return openai.ChatCompletionResponse{ + Choices: []openai.ChatCompletionChoice{ + { + Message: openai.ChatCompletionMessage{ + Role: openai.ChatMessageRoleAssistant, + Content: "ok", + }, + }, + }, + }, nil + }).Build().UnPatch() + + ctx := context.Background() + m, err := NewChatModel(ctx, &ChatModelConfig{ + APIKey: "test-key", + Model: "gpt-4", + CustomHeaders: map[string]string{"X-Custom": "value"}, + }) + if err != nil { + t.Fatal(err) + } + _, err = m.Generate(ctx, []*schema.Message{schema.UserMessage("hello")}) + if err != nil { + t.Fatal(err) + } + }) } diff --git a/components/model/openai/go.mod b/components/model/openai/go.mod index becb5bf8d..84f559bb9 100644 --- a/components/model/openai/go.mod +++ b/components/model/openai/go.mod @@ -4,9 +4,9 @@ go 1.18 require ( github.com/bytedance/mockey v1.3.0 - github.com/bytedance/sonic v1.14.1 - github.com/cloudwego/eino v0.7.13 - github.com/cloudwego/eino-ext/libs/acl/openai v0.1.17 + github.com/bytedance/sonic v1.15.0 + github.com/cloudwego/eino v0.9.0 + github.com/cloudwego/eino-ext/libs/acl/openai v0.1.18-0.20260527084435-846f52bd97c6 github.com/eino-contrib/jsonschema v1.0.3 github.com/meguminnnnnnnnn/go-openai v0.1.2 github.com/wk8/go-ordered-map/v2 v2.1.8 @@ -16,7 +16,7 @@ require ( github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/sonic/loader v0.5.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/evanphx/json-patch v0.5.2 // indirect @@ -40,6 +40,6 @@ require ( github.com/yargevad/filepathx v1.0.0 // indirect golang.org/x/arch v0.11.0 // indirect golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect - golang.org/x/sys v0.28.0 // indirect + golang.org/x/sys v0.29.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/components/model/openai/go.sum b/components/model/openai/go.sum index 5753d7b70..847cf4f19 100644 --- a/components/model/openai/go.sum +++ b/components/model/openai/go.sum @@ -13,15 +13,23 @@ github.com/bytedance/mockey v1.3.0 h1:ONLRdvhqmCfr9rTasUB8ZKCfvbdD2tohOg4u+4Q/ed github.com/bytedance/mockey v1.3.0/go.mod h1:1BPHF9sol5R1ud/+0VEHGQq/+i2lN+GTsr3O2Q9IENY= github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w= github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= +github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cloudwego/eino v0.7.13 h1:Ku7hY+83gGJJjf4On3UgqjC57UcA+DXe0tqAZiNDDew= github.com/cloudwego/eino v0.7.13/go.mod h1:nA8Vacmuqv3pqKBQbTWENBLQ8MmGmPt/WqiyLeB8ohQ= +github.com/cloudwego/eino v0.9.0 h1:no5bko5r21pM7oJv9BQMux5ncfXIy0Dkd9tjIF5bC0A= +github.com/cloudwego/eino v0.9.0/go.mod h1:OBD1mrkfkt/pJa4rkg1P0VnaMeOVl7l8IAdEqY//3IQ= github.com/cloudwego/eino-ext/libs/acl/openai v0.1.17 h1:EeVcR1TslRA2IdNW1h/2LaGbPlffwGhQm99jM3zWZiI= github.com/cloudwego/eino-ext/libs/acl/openai v0.1.17/go.mod h1:Zkcx6DPTR2NfWmtSXbhItswGw6hqUezNPhNcke0pOG8= +github.com/cloudwego/eino-ext/libs/acl/openai v0.1.18-0.20260527084435-846f52bd97c6 h1:ES/xufN5eqJ3h+9tw/tq6F8kkgnAxBAHVUB6nqKsIDU= +github.com/cloudwego/eino-ext/libs/acl/openai v0.1.18-0.20260527084435-846f52bd97c6/go.mod h1:5Xj74dGrfHo1z7I07Fzp3SlTF7Bt4tss3A2FSt8SqQ4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -97,6 +105,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -104,6 +113,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -126,7 +136,10 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=