diff --git a/components/model/ark/go.mod b/components/model/ark/go.mod index 3e136ee9c..a9f195ce0 100644 --- a/components/model/ark/go.mod +++ b/components/model/ark/go.mod @@ -49,3 +49,5 @@ require ( gopkg.in/yaml.v2 v2.2.8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/volcengine/volcengine-go-sdk => github.com/jesse-engineer/volcengine-go-sdk v1.2.26-0.20260428152021-d3ac2bef0584 diff --git a/components/model/ark/go.sum b/components/model/ark/go.sum index 96f141149..7560c9f6f 100644 --- a/components/model/ark/go.sum +++ b/components/model/ark/go.sum @@ -66,6 +66,8 @@ github.com/goph/emperror v0.17.2/go.mod h1:+ZbQ+fUNO/6FNiUo0ujtMjhgad9Xa6fQL9KhH github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jesse-engineer/volcengine-go-sdk v1.2.26-0.20260428152021-d3ac2bef0584 h1:hdi/IU3ATB4ZSmG1r15rJignySbT2c14PLQ9I2Adddc= +github.com/jesse-engineer/volcengine-go-sdk v1.2.26-0.20260428152021-d3ac2bef0584/go.mod h1:oxoVo+A17kvkwPkIeIHPVLjSw7EQAm+l/Vau1YGHN+A= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -137,8 +139,6 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/volcengine/volc-sdk-golang v1.0.23 h1:anOslb2Qp6ywnsbyq9jqR0ljuO63kg9PY+4OehIk5R8= github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU= -github.com/volcengine/volcengine-go-sdk v1.2.9 h1:du2gnImtyWXKkQFnJW/GXCs+UBibGGOXIbP1Ams2pB8= -github.com/volcengine/volcengine-go-sdk v1.2.9/go.mod h1:oxoVo+A17kvkwPkIeIHPVLjSw7EQAm+l/Vau1YGHN+A= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= diff --git a/components/model/ark/option.go b/components/model/ark/option.go index d112effb4..3a725eee6 100644 --- a/components/model/ark/option.go +++ b/components/model/ark/option.go @@ -35,6 +35,9 @@ type arkOptions struct { maxToolCalls *int64 enableReasoningContentPassback bool + + // extraFields are shallow-merged into serialized Responses API JSON after multimodal preprocessing. + extraFields map[string]any } // WithCustomHeader sets custom headers for a single request @@ -153,3 +156,12 @@ func WithEnableReasoningContentPassback(enable bool) model.Option { o.enableReasoningContentPassback = enable }) } + +// WithExtraFields sets extra top-level JSON fields on the Responses API request body. +// Merged inside volcengine-go-sdk after the request is built and multimodal inputs are preprocessed; +// keys in extraFields override existing keys. See arkruntime.WithResponsesExtraFields. +func WithExtraFields(extraFields map[string]any) model.Option { + return model.WrapImplSpecificOptFn(func(o *arkOptions) { + o.extraFields = extraFields + }) +} diff --git a/components/model/ark/option_test.go b/components/model/ark/option_test.go index 0b11df7b7..7d5d0d168 100644 --- a/components/model/ark/option_test.go +++ b/components/model/ark/option_test.go @@ -46,3 +46,9 @@ func TestOptions(t *testing.T) { assert.Equal(t, cacheOpt, *opt.cache) assert.Equal(t, arkModel.ThinkingTypeEnabled, opt.thinking.Type) } + +func TestWithExtraFieldsOption(t *testing.T) { + fields := map[string]any{"k": "v"} + opt := model.GetImplSpecificOptions(&arkOptions{}, WithExtraFields(fields)) + assert.Equal(t, fields, opt.extraFields) +} diff --git a/components/model/ark/responses_api.go b/components/model/ark/responses_api.go index 2b9caf156..e5a0a0aa1 100644 --- a/components/model/ark/responses_api.go +++ b/components/model/ark/responses_api.go @@ -283,7 +283,7 @@ func (cm *ResponsesAPIChatModel) Generate(ctx context.Context, input []*schema.M } }() - responseObject, err := cm.client.CreateResponses(ctx, responseReq, arkruntime.WithCustomHeaders(specOptions.customHeaders)) + responseObject, err := cm.invokeCreateResponses(ctx, responseReq, specOptions) if err != nil { return nil, fmt.Errorf("failed to create responses: %w", err) } @@ -350,7 +350,7 @@ func (cm *ResponsesAPIChatModel) Stream(ctx context.Context, input []*schema.Mes } }() - responseStreamReader, err := cm.client.CreateResponsesStream(ctx, responseReq, arkruntime.WithCustomHeaders(specOptions.customHeaders)) + responseStreamReader, err := cm.invokeCreateResponsesStream(ctx, responseReq, specOptions) if err != nil { return nil, fmt.Errorf("failed to create responses: %w", err) } @@ -948,6 +948,33 @@ func (cm *ResponsesAPIChatModel) getOptions(opts []model.Option) (*model.Options return options, arkOpts, nil } +func extraFieldsToIface(m map[string]any) map[string]interface{} { + if len(m) == 0 { + return nil + } + out := make(map[string]interface{}, len(m)) + for k, v := range m { + out[k] = v + } + return out +} + +func (cm *ResponsesAPIChatModel) invokeCreateResponses(ctx context.Context, responseReq *responses.ResponsesRequest, spec *arkOptions) (*responses.ResponseObject, error) { + h := arkruntime.WithCustomHeaders(spec.customHeaders) + if len(spec.extraFields) == 0 { + return cm.client.CreateResponses(ctx, responseReq, h) + } + return cm.client.CreateResponses(ctx, responseReq, h, arkruntime.WithResponsesExtraFields(extraFieldsToIface(spec.extraFields))) +} + +func (cm *ResponsesAPIChatModel) invokeCreateResponsesStream(ctx context.Context, responseReq *responses.ResponsesRequest, spec *arkOptions) (*utils.ResponsesStreamReader, error) { + h := arkruntime.WithCustomHeaders(spec.customHeaders) + if len(spec.extraFields) == 0 { + return cm.client.CreateResponsesStream(ctx, responseReq, h) + } + return cm.client.CreateResponsesStream(ctx, responseReq, h, arkruntime.WithResponsesExtraFields(extraFieldsToIface(spec.extraFields))) +} + func (cm *ResponsesAPIChatModel) toTools(tis []*schema.ToolInfo) ([]*responses.ResponsesTool, error) { tools := make([]*responses.ResponsesTool, len(tis)) for i := range tis { @@ -1712,7 +1739,7 @@ func (cm *ResponsesAPIChatModel) CreatePrefixCache(ctx context.Context, prefix [ return nil, err } - responseObject, err := cm.client.CreateResponses(ctx, responseReq) + responseObject, err := cm.invokeCreateResponses(ctx, responseReq, specOptions) if err != nil { return nil, err }