WithExtraFields 应该合并参数而不是覆盖
问题描述
当同时使用 ChatModelConfig.EnableThinking 和 qwen.WithExtraFields() 传递额外参数(如 enable_search)时,额外字段会被覆盖而不是合并。这导致用户提供的参数丢失。
问题根源在于 eino-ext/libs/acl/openai/option.go 中 WithExtraFields() 的实现:
func WithExtraFields(extraFields map[string]any) model.Option {
return model.WrapImplSpecificOptFn(func(o *openaiOptions) {
o.ExtraFields = extraFields // 直接赋值 - 覆盖已有字段
})
}
当设置了 ChatModelConfig.EnableThinking 时,Qwen 模型的 parseCustomOptions() 方法会在内部创建另一个 WithExtraFields() 调用,从而覆盖用户提供的额外字段。
重现步骤
- 创建一个在配置中启用
EnableThinking 的 Qwen 聊天模型:
chatModel, err := qwen.NewChatModel(ctx, &qwen.ChatModelConfig{
BaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
APIKey: apiKey,
Model: "qwen-flash",
EnableThinking: utils.Ptr(true), // 在配置中启用思考模式
})
- 调用
Stream() 时传入额外的字段:
stream, err := chatModel.Stream(ctx, messages, qwen.WithExtraFields(map[string]any{
"enable_search": true, // 这个参数会丢失!
}))
- 观察到
enable_search 参数没有被发送到 API,因为它被框架内部设置 enable_thinking 和 chat_template_kwargs 的 WithExtraFields() 调用覆盖了。
期望行为
多个 WithExtraFields() 调用应该合并参数,而不是覆盖。期望的行为应该是:
- 用户的
WithExtraFields:{"enable_search": true}
- 框架的
WithExtraFields:{"enable_thinking": true, "chat_template_kwargs": {...}}
- 最终结果:
{"enable_search": true, "enable_thinking": true, "chat_template_kwargs": {...}}
但目前的最终结果只有 {"enable_thinking": true, "chat_template_kwargs": {...}},丢失了用户的参数。
临时解决方案
当前的解决方法是避免使用 ChatModelConfig.EnableThinking,而是通过 WithExtraFields() 传递所有参数:
// 不在配置中使用 EnableThinking
chatModel, err := qwen.NewChatModel(ctx, &qwen.ChatModelConfig{
BaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
APIKey: apiKey,
Model: "qwen-flash",
// EnableThinking: utils.Ptr(true), // 不使用这个
})
// 在 WithExtraFields 中传递所有参数
stream, err := chatModel.Stream(ctx, messages, qwen.WithExtraFields(map[string]any{
"enable_thinking": true, // 在这里传递思考模式
"enable_search": true, // 现在两者可以一起工作
}))
建议的解决方案
修改 WithExtraFields() 以合并参数而不是覆盖:
func WithExtraFields(extraFields map[string]any) model.Option {
return model.WrapImplSpecificOptFn(func(o *openaiOptions) {
if o.ExtraFields == nil {
o.ExtraFields = make(map[string]any)
}
// 合并而不是覆盖
for k, v := range extraFields {
o.ExtraFields[k] = v
}
})
}
版本信息
- eino: v0.7.13
- eino-ext/components/model/qwen: v0.1.5
- eino-ext/libs/acl/openai: v0.1.11
环境信息
GOARCH='arm64'
GOOS='darwin'
GOVERSION='go1.25.3'
完整的 go env 输出:
GOARCH='arm64'
GOOS='darwin'
GOVERSION='go1.25.3'
CGO_ENABLED='1'
补充说明
这个问题影响所有需要将框架提供的配置选项(如 EnableThinking)与自定义额外字段结合使用的场景。常见用例包括:
- 思考模式 + 网络搜索:为千问模型同时启用深度思考和联网搜索
- 思考模式 + 自定义参数:将思考模式与其他供应商特定参数一起使用
- 多个自定义参数:从不同来源传递多个额外字段
当前的覆盖行为使得在不使用临时解决方案的情况下无法同时使用这些功能,这不够直观,并且要求用户了解内部实现细节。
相关 Issue
WithExtraFields 应该合并参数而不是覆盖
问题描述
当同时使用
ChatModelConfig.EnableThinking和qwen.WithExtraFields()传递额外参数(如enable_search)时,额外字段会被覆盖而不是合并。这导致用户提供的参数丢失。问题根源在于
eino-ext/libs/acl/openai/option.go中WithExtraFields()的实现:当设置了
ChatModelConfig.EnableThinking时,Qwen 模型的parseCustomOptions()方法会在内部创建另一个WithExtraFields()调用,从而覆盖用户提供的额外字段。重现步骤
EnableThinking的 Qwen 聊天模型:Stream()时传入额外的字段:enable_search参数没有被发送到 API,因为它被框架内部设置enable_thinking和chat_template_kwargs的WithExtraFields()调用覆盖了。期望行为
多个
WithExtraFields()调用应该合并参数,而不是覆盖。期望的行为应该是:WithExtraFields:{"enable_search": true}WithExtraFields:{"enable_thinking": true, "chat_template_kwargs": {...}}{"enable_search": true, "enable_thinking": true, "chat_template_kwargs": {...}}但目前的最终结果只有
{"enable_thinking": true, "chat_template_kwargs": {...}},丢失了用户的参数。临时解决方案
当前的解决方法是避免使用
ChatModelConfig.EnableThinking,而是通过WithExtraFields()传递所有参数:建议的解决方案
修改
WithExtraFields()以合并参数而不是覆盖:版本信息
环境信息
完整的
go env输出:补充说明
这个问题影响所有需要将框架提供的配置选项(如
EnableThinking)与自定义额外字段结合使用的场景。常见用例包括:当前的覆盖行为使得在不使用临时解决方案的情况下无法同时使用这些功能,这不够直观,并且要求用户了解内部实现细节。
相关 Issue