模型配置与切换

基础模型配置

from deepagents import create_deep_agent

# 方式 1:直接传字符串(推荐)
agent = create_deep_agent(model="deepseek:deepseek-chat")

# 方式 2:使用 init_chat_model
from langchain.chat_models import init_chat_model

model = init_chat_model(
    model="deepseek:deepseek-chat",
    temperature=0.7,
    max_tokens=4096,
)
agent = create_deep_agent(model=model)

DeepSeek 特定配置

from langchain_deepseek import ChatDeepSeek

model = ChatDeepSeek(
    model="deepseek-chat",       # 或 "deepseek-reasoner"
    temperature=0.7,
    max_tokens=4096,
    timeout=60,
    max_retries=2,
)

agent = create_deep_agent(model=model)

运行时动态切换模型

示例代码

from env_utils import DASHSCOPE_API_KEY, DASHSCOPE_BASE_URL, DEEPSEEK_BASE_URL, DEEPSEEK_API_KEY
from langchain.chat_models import init_chat_model
from langchain.agents import create_agent
from deepagents import create_deep_agent
from dataclasses import dataclass
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
from typing import Callable

# ============================================================================
# Demo 1: 基本使用 - 创建简单的 Agent
# ============================================================================


@dataclass
class Context:
    # 运行时要切换到的模型名称
    model: str
    # 模型提供方,openai 表示使用 OpenAI 兼容协议
    model_provider: str
    # 兼容协议服务的鉴权 key,不传时会读取对应环境变量
    api_key: str | None = None
    # 兼容协议服务的接口地址,不传时使用 provider 默认地址
    base_url: str | None = None


@wrap_model_call
def configurable_model(
    request: ModelRequest,
    handler: Callable[[ModelRequest], ModelResponse],
) -> ModelResponse:
    # 从本次调用的运行时上下文中读取模型配置
    context = request.runtime.context
    # 使用上下文配置创建新模型,覆盖 agent 初始化时的默认模型
    model = init_chat_model(
        context.model,
        model_provider=context.model_provider,
        api_key=context.api_key,
        base_url=context.base_url,
    )
    return handler(request.override(model=model))


def demo1_configurable_model():
    """运行时动态切换模型
    **参考文档**:[Models](https://docs.langchain.com/oss/python/deepagents/models)
    初使化 model 时使用的是 deepseek:deepseek-chat
    在调用 agent.invoke 时,通过 context 传入不同的模型配置,model 被动态切换成了 qwen3.5-plus
    """
    print("=" * 50)
    print("Demo 1: 运行时动态切换模型")
    print("=" * 50)

    # 调用init_chat_model函数初始化模型,参数model用来指定模型名称,Langchain会根据模型名字自动设定base_url,并从环境变量中获取api_key
    model = init_chat_model(
        model="deepseek:deepseek-chat",
        # model="qwen3.5-plus",  # 模型名称,这里选择qwen3.5-plus,这是一个多模态模型,支持图片、文本、音频、视频
        # model_provider="openai",
        # base_url=DEEPSEEK_BASE_URL,  # 这个参数没有用,Langchain会根据模型名字自动设定base_url
        # api_key=DEEPSEEK_API_KEY,
        temperature=1.5,
    )

    # 方式一:使用create_deep_agent 创建 agent,默认模型为 deepseek-chat,挂载动态切换中间件
    # agent = create_deep_agent(
    #     model=model,
    #     # model="deepseek:deepseek-chat",
    #     middleware=[configurable_model],
    #     context_schema=Context,
    # )

    # 方式二:使用create_agent 创建 agent,
    agent = create_agent(
        model=model,
        # configurable_model 执行模型切换的核心中间件
        middleware=[configurable_model],
        context_schema=Context,
    )

    # 通过 context 传入 qwen 模型配置,触发 configurable_model 动态切换
    response = agent.invoke(
        {"messages": [{"role": "user", "content": "你好!"}]},
        context=Context(
            model="qwen3.5-plus",
            model_provider="openai",
            api_key=DASHSCOPE_API_KEY,
            base_url=DASHSCOPE_BASE_URL,
        ),
    )

    print(f"类型: {type(response)}")
    print(f"响应: {response}")
    print()

    # output:
    #  类型: <class 'dict'>
    # 响应: {'messages': [HumanMessage(content='你好!', additional_kwargs={}, response_metadata={}, id='b15f0052-adca-44c9-afa5-11f329fc602e'), AIMessage(content='你好!👋 有什么我可以帮你的吗?无论是聊天、查询信息、写作还是其他问题,都可以随时告诉我哦!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 750, 'prompt_tokens': 12, 'total_tokens': 762, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 717, 'rejected_prediction_tokens': None, 'text_tokens': 750}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': None, 'text_tokens': 12}}, 'model_provider': 'openai', 'model_name': 'qwen3.5-plus', 'system_fingerprint': None, 'id': 'chatcmpl-02cf02be-f58f-93e4-a8c5-c1b66dffbed2', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019ef84d-39f4-7e53-8d02-34073ecbde6a-0', tool_calls=[], invalid_tool_calls=[], usage_metadata={'input_tokens': 12, 'output_tokens': 750, 'total_tokens': 762, 'input_token_details': {}, 'output_token_details': {'reasoning': 717}})]}
    # 从结果中提取消息列表
    messages = response.get('messages', [])
    if messages:
        # 打印方式一:
        # 获取最后一条消息(通常是最终的 AI 响应)
        last_message = messages[-1]
        print(f"最后一条消息类型: {type(last_message).__name__}")
        print(f"内容: {last_message.content}")

        # output:
        # 最后一条消息类型: AIMessage
        # 内容: 你好!👋 有什么我可以帮你的吗?无论是聊天、查询信息、写作还是其他问题,都可以随时告诉我哦!

        # 打印方式二 美化打印
        for message in messages:
            # print()
            message.pretty_print()

            # output:
            # ================================ Human Message =================================

            # 你好!
            # ================================== Ai Message ==================================

            # 你好!👋 有什么我可以帮你的吗?无论是聊天、查询信息、写作还是其他问题,都可以随时告诉我哦!

            # 打印方式三: json格式打印每一项结果
            print("="*50)
            print(message.model_dump_json(indent=2))
            print("="*50)

            # output:
            # ==================================================
            # {
            # "content": "你好!",
            # "additional_kwargs": {},
            # "response_metadata": {},
            # "type": "human",
            # "name": null,
            # "id": "5cff2bc8-cbe2-4099-922a-2b8f5b3d55a1"
            # }
            # ==================================================
            # ================================== Ai Message ==================================

            # 你好!很高兴见到你。有什么我可以帮你的吗? 👋
            # ==================================================
            # {
            # "content": "你好!很高兴见到你。有什么我可以帮你的吗? 👋",
            # "additional_kwargs": {
            #     "refusal": null
            # },
            # "response_metadata": {
            #     "token_usage": {
            #     "completion_tokens": 487,
            #     "prompt_tokens": 12,
            #     "total_tokens": 499,
            #     "completion_tokens_details": {
            #         "accepted_prediction_tokens": null,
            #         "audio_tokens": null,
            #         "reasoning_tokens": 468,
            #         "rejected_prediction_tokens": null,
            #         "text_tokens": 487
            #     },
            #     "prompt_tokens_details": {
            #         "audio_tokens": null,
            #         "cached_tokens": null,
            #         "text_tokens": 12
            #     }
            #     },
            #     "model_provider": "openai",
            #     "model_name": "qwen3.5-plus",
            #     "system_fingerprint": null,
            #     "id": "chatcmpl-907b7754-4aca-9a13-a34e-be3d9cd9c03b",
            #     "finish_reason": "stop",
            #     "logprobs": null
            # },
            # "type": "ai",
            # "name": null,
            # "id": "lc_run--019ef84f-f625-7502-be0c-55d42a00d6e4-0",
            # "tool_calls": [],
            # "invalid_tool_calls": [],
            # "usage_metadata": {
            #     "input_tokens": 12,
            #     "output_tokens": 487,
            #     "total_tokens": 499,
            #     "input_token_details": {},
            #     "output_token_details": {
            #     "reasoning": 468
            #     }
            # }
            # }
            # ==================================================


def main():
    """主函数,分别调用各个 demo"""
    print("DASHSCOPE_API_KEY", DASHSCOPE_API_KEY)
    print("DASHSCOPE_BASE_URL", DASHSCOPE_BASE_URL)
    demo1_configurable_model()


if __name__ == "__main__":
    main()

运行时动态切换模型的常见使用场景

运行时动态切换模型,指的是在同一个 Agent 或应用流程中,根据当前请求的上下文、任务类型、用户等级、成本预算或故障状态,动态选择实际调用的模型。

在当前示例中,agent 初始化时有一个默认模型,但在调用 agent.invoke(..., context=Context(...)) 时,会通过 configurable_model 中间件读取 context 中的模型配置,并把本次调用实际使用的模型替换掉。

1. 按任务复杂度切换模型

简单问题使用速度快、成本低的模型;复杂推理、代码分析、长文理解等任务切换到能力更强的模型。

if task_type == "simple_chat":
    model = "qwen-turbo"
elif task_type == "reasoning":
    model = "deepseek-reasoner"

适合场景:

  • 普通闲聊
  • 简单问答
  • 复杂推理
  • 代码分析
  • 多步骤规划

2. 按用户等级切换模型

普通用户使用成本较低的模型,付费用户或高优先级用户使用更强的模型。

if user_plan == "pro":
    model = "qwen3.5-plus"
else:
    model = "qwen-turbo"

适合场景:

  • 免费版和付费版能力区分
  • 企业用户优先使用高质量模型
  • 高价值请求使用更强模型

3. 按成本预算切换模型

当请求量较大或预算紧张时,自动切到低成本模型;重要任务再使用高质量模型。

适合场景:

  • 高并发业务
  • 成本敏感型应用
  • 批量文本处理
  • 非关键任务降成本

这种方式可以避免所有请求都打到最贵模型上。

4. 按模型能力切换模型

不同模型擅长不同任务,可以根据任务类型选择最合适的模型。

常见匹配方式:

  • 代码生成:使用代码能力强的模型
  • 数学推理:使用 reasoning 模型
  • 多模态任务:使用支持图片、音频或视频的模型
  • 中文问答:使用中文表现更好的模型
  • 长文总结:使用长上下文模型

5. 按上下文长度切换模型

短上下文使用普通模型,长文档、长对话、RAG 场景切换到支持更大上下文窗口的模型。

适合场景:

  • 文档问答
  • 长对话总结
  • RAG 检索增强生成
  • 法律、论文、报告类长文本分析

如果检索出来的内容很长,就可以动态切换到长上下文模型。

6. 故障降级

如果主模型超时、限流或报错,可以切换到备用模型继续完成请求。

try:
    use_model("qwen3.5-plus")
except Exception:
    use_model("deepseek-chat")

适合场景:

  • 主模型不可用
  • 请求超时
  • API 限流
  • 服务商异常
  • 生产系统容灾

7. A/B 测试和灰度发布

同一类请求随机分配到不同模型,用来比较回答质量、延迟、成本和用户满意度。

适合场景:

  • 新模型上线前评估
  • 比较不同模型效果
  • 逐步灰度切流
  • 收集用户反馈

8. 不同业务模块使用不同模型

一个系统中,不同业务模块可以使用不同模型。

例如:

  • 客服对话:使用响应快的模型
  • 工单总结:使用长上下文模型
  • 代码审查:使用代码能力强的模型
  • 复杂规划:使用推理模型
  • 内容审核:使用分类或安全模型

9. Agent 内部不同步骤切换模型

一个 Agent 的不同步骤不一定都需要使用同一个模型。

例如:

  • 第一步:使用便宜模型判断用户意图
  • 第二步:使用强模型生成方案
  • 第三步:使用快模型整理输出格式

这种方式可以在保证效果的同时控制成本和延迟。

当前代码中的对应关系

当前代码里的动态切换逻辑主要由三部分组成:

@dataclass
class Context:
    model: str
    model_provider: str
    api_key: str | None = None
    base_url: str | None = None

Context 用来保存本次调用要使用的模型配置。

@wrap_model_call
def configurable_model(request, handler):
    context = request.runtime.context
    model = init_chat_model(
        context.model,
        model_provider=context.model_provider,
        api_key=context.api_key,
        base_url=context.base_url,
    )
    return handler(request.override(model=model))

configurable_model 中间件从运行时上下文中读取模型配置,并覆盖默认模型。

response = agent.invoke(
    {"messages": [{"role": "user", "content": "你好!"}]},
    context=Context(
        model="qwen3.5-plus",
        model_provider="openai",
        api_key=DASHSCOPE_API_KEY,
        base_url=DASHSCOPE_BASE_URL,
    ),
)

agent.invoke 调用时通过 context 指定本次请求实际使用的模型。这样同一个 agent 实例就可以在不同请求中动态切换不同模型。

作者:海马  创建时间:2026-06-24 11:33
最后编辑:海马  更新时间:2026-07-01 20:05