Skip to content

[Bug] WithExtraFields 覆盖而非合并参数,导致 EnableThinking 与其他配置无法共存 #671

@jhonor777

Description

@jhonor777

WithExtraFields 应该合并参数而不是覆盖

问题描述

当同时使用 ChatModelConfig.EnableThinkingqwen.WithExtraFields() 传递额外参数(如 enable_search)时,额外字段会被覆盖而不是合并。这导致用户提供的参数丢失。

问题根源在于 eino-ext/libs/acl/openai/option.goWithExtraFields() 的实现:

func WithExtraFields(extraFields map[string]any) model.Option {
    return model.WrapImplSpecificOptFn(func(o *openaiOptions) {
        o.ExtraFields = extraFields  // 直接赋值 - 覆盖已有字段
    })
}

当设置了 ChatModelConfig.EnableThinking 时,Qwen 模型的 parseCustomOptions() 方法会在内部创建另一个 WithExtraFields() 调用,从而覆盖用户提供的额外字段。

重现步骤

  1. 创建一个在配置中启用 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),  // 在配置中启用思考模式
})
  1. 调用 Stream() 时传入额外的字段:
stream, err := chatModel.Stream(ctx, messages, qwen.WithExtraFields(map[string]any{
    "enable_search": true,  // 这个参数会丢失!
}))
  1. 观察到 enable_search 参数没有被发送到 API,因为它被框架内部设置 enable_thinkingchat_template_kwargsWithExtraFields() 调用覆盖了。

期望行为

多个 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)与自定义额外字段结合使用的场景。常见用例包括:

  1. 思考模式 + 网络搜索:为千问模型同时启用深度思考和联网搜索
  2. 思考模式 + 自定义参数:将思考模式与其他供应商特定参数一起使用
  3. 多个自定义参数:从不同来源传递多个额外字段

当前的覆盖行为使得在不使用临时解决方案的情况下无法同时使用这些功能,这不够直观,并且要求用户了解内部实现细节。

相关 Issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugThis is a bug-report. Bug-fix PRs use `C-enhancement` instead.D-chatmodel-implDomain: This is an issue related to particular ChatModel implementation

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions