在这里插入图片描述

文章目录


课程导读 & 学习目标

在上一节课中,我们深入理解了LangChain的Runnable抽象、LCEL声明式编程、回调与可观测性等核心设计思想。你也亲手实现了自定义Runnable,并用流式回调实时监控模型输出。但有一个关键问题始终悬而未决:我们上一节课使用的智谱AI模型,只是众多大模型中的一个。在实际开发中,你可能需要切换通义千问、DeepSeek,甚至同时使用多个模型

LangChain的“模型无关性”设计思想(我们在第2课提过)正是为了解决这个问题——让开发者用同一套代码,无缝调用不同厂商的大模型,实现“写一次,到处运行”。然而,很多初学者在实践时会遇到两大困惑:

  • 厂商差异:OpenAI用OPENAI_API_KEY,通义千问用DASHSCOPE_API_KEY,DeepSeek用DEEPSEEK_API_KEY,环境变量记不住。
  • 包导入差异ChatOpenAIChatTongyiChatDeepSeek,每个模型的导入路径和初始化方式不同,代码改来改去很麻烦。

本节课将彻底解决这些问题。我们不只教你“怎么写代码调用某个模型”,更要让你掌握:

  1. LangChain模型接入的统一接口体系:理解所有模型调用都遵循的invoke/stream/batch三件套。
  2. 三种主流接入方式
    • OpenAI官方及兼容方案(ChatOpenAI+base_url)。
    • 通义千问接入(ChatTongyi / ChatQwen)。
    • DeepSeek接入(langchain-deepseek / OpenAI兼容)。
  3. 多模型切换的最佳实践:通过配置文件+工厂模式,3行代码切换模型。
  4. 生产级注意事项:API密钥管理、超时重试、并发控制、成本追踪。

通过本课,你将在LangChain的“模型无关性”战场上彻底站稳脚跟,为后续第4-6课(Prompt工程、Output Parser、Memory)的进阶内容铺平道路。届时,你可以自由选择最合适的模型来完成不同任务,而无需为每个模型重写业务逻辑。

💡 本节课的类比:把LangChain想象成“充电器转换头”——无论你用的是哪个国家(哪个厂商)的插座,转换头(LangChain统一接口)都能让你顺利充电(调用大模型)。


前置知识与环境准备

1.1 Python版本与开发工具

继续沿用前两课的虚拟环境langchain_course,确保Python版本为3.10+。如果尚未创建环境,请参考第1课的依赖安装命令快速搭建。

1.2 你需要准备的三类API密钥

本节课需调用三个不同的大模型服务,请按需注册并获取API密钥:

服务商 注册地址 推荐理由 免费额度
OpenAI platform.openai.com 国际主流,生态最完善 新用户赠送$5额度(需绑卡)
通义千问(阿里云) dashscope.aliyun.com 国内稳定,兼容OpenAI接口 新用户送7000万tokens
DeepSeek platform.deepseek.com 性价比极高,API降价超50% 新用户送500万tokens

⚠️ 安全提示:API密钥属于敏感信息,严禁硬编码到代码中。本课全程使用.env文件管理密钥,该文件也应被.gitignore排除。

1.3 创建.env环境变量文件

在项目根目录更新或创建.env文件:

# OpenAI(如需使用)
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx

# 通义千问(DashScope)
DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx

# DeepSeek
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx

# 如果需要通过OpenAI兼容方式接入其他模型(如智谱、本地Ollama等)
# BASE_URL为自定义,本课用DeepSeek OpenAI兼容时覆盖
# OPENAI_API_BASE=https://api.deepseek.com/v1

1.4 安装依赖包

# 激活虚拟环境
source venv/bin/activate  # Mac/Linux
# venv\Scripts\activate   # Windows

# 安装LangChain核心依赖(如已安装可跳过)
pip install langchain==0.3.7 langchain-core==0.3.21 langchain-openai==0.2.8 python-dotenv==1.0.1

# 安装通义千问DashScope支持
pip install dashscope

# 安装DeepSeek社区集成包(官方推荐)
pip install langchain-deepseek

# 如需通过OpenAI兼容方式(备选),则无需额外安装

1.5 验证安装

创建check_models.py测试各包能否正常导入:

# 测试各模型包的导入
try:
    from langchain_openai import ChatOpenAI
    print("✓ langchain_openai 导入成功")
except ImportError as e:
    print(f"✗ langchain_openai 导入失败: {e}")

try:
    from langchain_community.chat_models.tongyi import ChatTongyi
    print("✓ ChatTongyi 导入成功")
except ImportError as e:
    print(f"✗ ChatTongyi 导入失败,请检查 dashscope 是否安装")

try:
    from langchain_deepseek import ChatDeepSeek
    print("✓ ChatDeepSeek 导入成功")
except ImportError as e:
    print("✗ langchain_deepseek 导入失败,请检查是否已安装该包")

核心概念深度拆解

2.1 LangChain模型的统一抽象:BaseChatModel

无论调用哪个厂商的大模型,LangChain都通过**BaseChatMessageModel**(常简称为BaseChatModel)抽象基类统一了接口。这意味着:

  • 统一调用接口.invoke()(同步)、.ainvoke()(异步)、.stream()(流式)、.batch()(批量处理)。
  • 统一输入格式BaseMessage及其子类(SystemMessageHumanMessageAIMessage)。
  • 统一输出格式AIMessage,包含.content(文本内容)、.response_metadata(token消耗、延迟等元数据)。

📌 LangChain官方的表述:“One API for any model — Every LangChain chat model, regardless of provider, implements the same interface.”

2.2 三种接入模式

LangChain接入大模型有三种方式,本节课将依次讲解前两种(最常用):

模式一:官方集成包(直接调用)

每个主流模型厂商都有自己的LangChain集成包。例如:

  • OpenAIlangchain-openai,提供ChatOpenAI类。
  • 通义千问:通过langchain-community.chat_models.tongyi.ChatTongyi,依赖dashscope
  • DeepSeeklangchain-deepseek,提供ChatDeepSeek类。

这种模式的优点是类型安全、参数提示完整,缺点是每个模型需要记忆不同的类名和配置参数。

模式二:OpenAI兼容接口(通用方式)

由于OpenAI的API格式已成为行业事实标准,许多模型厂商(包括DeepSeek、智谱GLM、通义千问的部分版本)都提供了与OpenAI兼容的端点。

这种方式只需使用ChatOpenAI这一个类,通过配置base_urlapi_key即可切换模型。它的优点是代码复用性极高——切换模型时只需修改几行配置,业务逻辑完全不变。

本课将重点讲解两种模式,让你根据实际场景灵活选用。

模式三:自定义Runnable包装原生API(高级扩展)

当模型厂商没有提供LangChain集成包,且不支持OpenAI兼容接口时,你可以编写自定义Runnable来封装其原生API。本专栏后续的“自定义组件”课会专门讲解。

2.3 模型版本与模型名称对照

不同模型的版本迭代频繁,调用时需要指定正确的model参数。

OpenAI常用模型
模型名称 适用场景 说明
gpt-4o 多模态、高推理能力 OpenAI当前主力模型
gpt-4o-mini 高性价比、快速响应 适合简单任务
gpt-3.5-turbo 遗留支持 逐渐被淘汰
gpt-4-turbo 长上下文(128K) 适合推理+长文本
通义千问系列模型

阿里云百炼平台提供了丰富的通义千问模型,新用户赠送7000万tokens免费额度:

模型名称 适用场景 特性说明
qwen-max 复杂推理、专业分析 效果最强,适合多步骤推理
qwen-plus 内容创作、客服问答 平衡性能与成本的通用首选
qwen-flash 快速响应、基础对话 高性价比,低延迟
qwen3.5-27b 开源部署 阿里开源模型,可本地部署

💡 注意:通义千问的模型名称和版本更新频繁(如2026年2月发布了Qwen3.5-Flash API)。建议在阿里云百炼控制台查看最新的可用模型列表。

DeepSeek模型

DeepSeek的API模型名通过deepseek-chatdeepseek-reasoner两个端点提供,目前这两个模型名分别指向DeepSeek-V4-Flash的非思考模式和思考模式:

API模型名 实际模型 适用场景
deepseek-chat DeepSeek-V4-Flash(非思考模式) 通用对话,快速响应
deepseek-reasoner DeepSeek-V4-Flash(思考模式) 需要推理链路的复杂任务

⚠️ 重要提醒:旧模型名deepseek-chatdeepseek-reasoner将于2026年7月24日后停止使用,届时请切换至新模型名deepseek-v4-prodeepseek-v4-flash。本课代码将使用最新兼容写法。


底层运行原理剖析

3.1 LangChain模型的“三阶段”调用原理

无论使用哪个模型,LangChain的调用在底层都遵循一个统一的“三阶段”流程:

阶段一:输入转换(LangChain → 厂商格式)
LangChain将标准的BaseMessage列表(其中每个消息包含rolecontent字段)转换为模型厂商API所需的JSON格式。例如:

  • OpenAI需要{"role": "user", "content": "..."}格式。
  • 通义千问DashScope需要{"user": "..."}格式。
  • DeepSeek兼容OpenAI格式。

这一转换由各集成包的_generate方法完成,对用户完全透明。

阶段二:网络请求与模型推理
转换后的请求通过HTTP POST发送到厂商的API端点。这个过程包含:

  • 超时控制:防止请求长时间挂起。
  • 重试机制:网络抖动或限流时自动重试。
  • 流式回传:如果开启streaming=True,则以SSE(Server-Sent Events)方式逐步接收token。

阶段三:输出标准化(厂商格式 → LangChain格式)
厂商返回的响应(通常是JSON)被解析并封装为标准化的AIMessage对象:

  • response.content:模型生成的文本内容。
  • response.response_metadata:token消耗统计(token_usage)、finish_reason(停止原因)、延迟等元数据。

3.2 不同模型接入的底层差异对比

维度 OpenAI 通义千问(DashScope) DeepSeek
HTTP协议 HTTPS HTTPS HTTPS
认证方式 Bearer Token Bearer Token Bearer Token
请求路径 /v1/chat/completions /compatible-mode/v1/chat/completions /v1/chat/completions
必填参数 model, messages model, messages model, messages
流式支持 SSE SSE SSE
LangChain实现 ChatOpenAI ChatTongyi ChatDeepSeek

3.3 为什么一个“ChatOpenAI”类能调用所有OpenAI兼容模型?

ChatOpenAI类在初始化时会读取base_url参数。如果base_url为空,则默认指向https://api.openai.com/v1;如果指定了其他URL(例如https://api.deepseek.com/v1),则所有请求都会被发送到该地址。ChatOpenAI底层使用OpenAI官方Python SDK,但该SDK也支持自定义base_url,从而实现“一套代码,调用多个模型”。

这背后的设计模式是适配器模式:通过统一的接口,将不同厂商的API差异封装在内部,对外暴露一致的行为。


核心API/组件源码解读

4.1 ChatOpenAI 核心参数详解

ChatOpenAI不仅在官方OpenAI模型中使用,也是接入DeepSeek等兼容模型的首选方式。其核心参数如下(基于LangChain 0.3.x官方文档):

参数 类型 说明
model str 模型名称,如"gpt-4o""deepseek-chat"
temperature float 控制随机性,0~2,越低输出越确定
max_tokens int 最大生成token数
api_key str API密钥,若不传则自动从环境变量读取
base_url str 自定义API端点,用于接入兼容模型或代理
timeout float 请求超时时间(秒)
max_retries int 请求失败时的最大重试次数
streaming bool 是否启用流式传输
organization str OpenAI组织ID(仅OpenAI官方账号需要)

4.2 ChatTongyi(通义千问)核心用法

ChatTongyi是LangChain社区包langchain-community中提供的通义千问集成:

from langchain_community.chat_models.tongyi import ChatTongyi

llm = ChatTongyi(
    model="qwen-plus",      # 选择模型版本
    temperature=0.7,
    top_p=0.9,              # nucleus采样参数
    dashscope_api_key="your-key"  # 若不传则读取环境变量DASHSCOPE_API_KEY
)

需要注意,ChatTongyi依赖于dashscope包,这是阿里云提供的官方Python SDK,用于调用通义千问API。

4.3 ChatDeepSeek 核心用法

LangChain为DeepSeek提供了官方集成包langchain-deepseek,提供ChatDeepSeek类:

from langchain_deepseek import ChatDeepSeek

llm = ChatDeepSeek(
    model="deepseek-chat",    # 或 "deepseek-reasoner"
    temperature=0.7,
    max_tokens=1024,
    api_key="your-key",       # 若不传则读取DEEPSEEK_API_KEY
    timeout=60
)

安装方式:pip install langchain-deepseek

4.4 三种类的统一调用接口

虽然三个类的名称和初始化参数略有差异,但它们都实现了BaseChatModel接口,因此调用方式完全一致:

# 通用调用模式
response = llm.invoke([HumanMessage(content="你好")])
print(response.content)

# 流式输出
for chunk in llm.stream([HumanMessage(content="你好")]):
    print(chunk.content, end="")

# 异步调用
# response = await llm.ainvoke([HumanMessage(content="你好")])
# 批量调用
# responses = llm.batch([messages1, messages2], config={"max_concurrency": 5})

这种统一接口的设计,使得在不同模型之间切换变得异常简单——只需替换llm对象的初始化代码,下游调用代码完全不用修改。


手把手项目实战教学

现在进入实战环节。我们将依次实现:

  1. OpenAI调用:官方方式 + 国内加速代理。
  2. 通义千问调用:两种方式(直接调用 + OpenAI兼容)。
  3. DeepSeek调用:两种方式(官方包 + OpenAI兼容)。
  4. 多模型切换实战:通过配置文件实现“一键切换”。

实战一:OpenAI调用(官方方式 + 代理加速)

由于OpenAI官方API在国内访问可能受限,我们演示两种方式:直接调用和使用代理(如果配置了代理的话)。

文件01_openai_demo.py

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

load_dotenv()

# 方式一:官方端点(需要科学上网环境)
# api_key = os.getenv("OPENAI_API_KEY")
# llm = ChatOpenAI(
#     model="gpt-4o-mini",   # 使用性价比更高的mini版本
#     temperature=0.7
# )

# 方式二:通过代理(如果你配置了代理服务)
# 提前设置环境变量 HTTP_PROXY 和 HTTPS_PROXY
# 或通过 requests 库的配置(略)

# 示例:使用 OpenAI 兼容代理
# 假设你有一个用了一键加速服务的代理端点
api_key = os.getenv("OPENAI_API_KEY")
proxy_base_url = os.getenv("PROXY_BASE_URL")

if proxy_base_url:
    llm = ChatOpenAI(
        model="gpt-4o-mini",
        openai_api_key=api_key,
        openai_api_base=proxy_base_url,   # 代理地址(OpenAI兼容)
        temperature=0.7
    )
else:
    # 使用官方端点
    llm = ChatOpenAI(
        model="gpt-4o-mini",
        temperature=0.7
    )

# 调用模型
messages = [HumanMessage(content="请用一句话介绍什么是机器学习")]
response = llm.invoke(messages)
print("OpenAI回答:", response.content)

💡 善意提示:本栏目鼓励合规使用AI技术。如果你所在地区网络有限制,可考虑使用国内稳定的大模型替代方案(如通义千问、DeepSeek)。

实战二:通义千问调用(ChatTongyi + OpenAI兼容)

文件02_tongyi_demo.py

import os
from dotenv import load_dotenv
from langchain_core.messages import HumanMessage

load_dotenv()

# ========== 方式一:直接使用 ChatTongyi ==========
try:
    from langchain_community.chat_models.tongyi import ChatTongyi
    
    tongyi_llm = ChatTongyi(
        model="qwen-plus",           # 平衡性能与成本
        temperature=0.7,
        dashscope_api_key=os.getenv("DASHSCOPE_API_KEY")
    )
    
    response = tongyi_llm.invoke([HumanMessage(content="请用一句话介绍什么是LangChain")])
    print("【通义千问 - 直接方式】:", response.content)
    print("Token消耗:", response.response_metadata.get("token_usage", {}))
    
except ImportError:
    print("需要安装 dashscope: pip install dashscope")

# ========== 方式二:使用 OpenAI 兼容接口 ==========
# 阿里云百炼平台提供了兼容OpenAI的API端点
# 文档参考:https://help.aliyun.com/zh/dashscope/developer-reference/api-details

tongyi_base_url = os.getenv("TONGYI_OPENAI_BASE_URL")
if tongyi_base_url:
    from langchain_openai import ChatOpenAI
    
    tongyi_compatible = ChatOpenAI(
        model="qwen-plus",
        openai_api_key=os.getenv("DASHSCOPE_API_KEY"),
        openai_api_base=tongyi_base_url,
        temperature=0.7
    )
    
    response2 = tongyi_compatible.invoke([HumanMessage(content="请用一句话介绍什么是LangChain")])
    print("【通义千问 - OpenAI兼容方式】:", response2.content)

实战三:DeepSeek调用(官方包 + OpenAI兼容)

文件03_deepseek_demo.py

import os
from dotenv import load_dotenv
from langchain_core.messages import HumanMessage

load_dotenv()

# ========== 方式一:使用官方 langchain-deepseek 包 ==========
try:
    from langchain_deepseek import ChatDeepSeek
    
    deepseek_llm = ChatDeepSeek(
        model="deepseek-chat",           # DeepSeek-V4-Flash非思考模式
        temperature=0.7,
        api_key=os.getenv("DEEPSEEK_API_KEY"),
        timeout=60
    )
    
    response = deepseek_llm.invoke([HumanMessage(content="请用一句话介绍什么是RAG技术")])
    print("【DeepSeek - 官方包】:", response.content)
    print("元数据:", response.response_metadata)
    
except ImportError:
    print("需要安装 langchain-deepseek: pip install langchain-deepseek")

# ========== 方式二:使用 OpenAI 兼容接口 ==========
# DeepSeek 官方提供了 OpenAI 兼容的端点
from langchain_openai import ChatOpenAI

deepseek_compatible = ChatOpenAI(
    model="deepseek-chat",
    openai_api_key=os.getenv("DEEPSEEK_API_KEY"),
    openai_api_base="https://api.deepseek.com/v1",   # DeepSeek官方兼容端点
    temperature=0.7
)

response2 = deepseek_compatible.invoke([HumanMessage(content="请用一句话介绍什么是RAG技术")])
print("【DeepSeek - OpenAI兼容方式】:", response2.content)

📌 关于模型名称的特别说明:截至2026年5月,DeepSeek的API已升级为DeepSeek-V4,官方推荐使用deepseek-v4-prodeepseek-v4-flash作为模型名称,旧的deepseek-chatdeepseek-reasoner将于2026年7月24日停止使用。本课中的示例考虑到兼容性,仍使用deepseek-chat,建议你在实际项目中尽快切换到新模型名称。

实战四:多模型切换(配置文件 + 工厂模式)

这是本课的核心实战——向你展示如何用一个配置文件管理多个模型,实现“切换模型不改业务代码”。

文件04_model_factory.py

import os
from dotenv import load_dotenv
from langchain_core.language_models import BaseChatModel
from langchain_core.messages import HumanMessage

load_dotenv()

class ModelFactory:
    """模型工厂:根据配置字符串返回对应的模型实例"""
    
    @staticmethod
    def get_model(provider: str, model: str = None, temperature: float = 0.7) -> BaseChatModel:
        provider = provider.lower()
        
        if provider == "openai":
            from langchain_openai import ChatOpenAI
            return ChatOpenAI(
                model=model or "gpt-4o-mini",
                temperature=temperature
            )
        
        elif provider == "tongyi":
            from langchain_community.chat_models.tongyi import ChatTongyi
            return ChatTongyi(
                model=model or "qwen-plus",
                temperature=temperature,
                dashscope_api_key=os.getenv("DASHSCOPE_API_KEY")
            )
        
        elif provider == "deepseek":
            from langchain_deepseek import ChatDeepSeek
            return ChatDeepSeek(
                model=model or "deepseek-chat",
                temperature=temperature,
                api_key=os.getenv("DEEPSEEK_API_KEY")
            )
        
        elif provider == "zhipu":   # 延续第1课
            from langchain_openai import ChatOpenAI
            return ChatOpenAI(
                model=model or "glm-4",
                openai_api_key=os.getenv("ZHIPU_API_KEY"),
                openai_api_base=os.getenv("BASE_URL"),
                temperature=temperature
            )
        
        else:
            raise ValueError(f"不支持的模型供应商: {provider}")

# 在配置文件中定义当前使用的模型
# 你可以修改这一行来切换模型,下游代码完全不变
CURRENT_PROVIDER = os.getenv("PROVIDER", "tongyi")  # 可选: openai, tongyi, deepseek, zhipu
CURRENT_MODEL = os.getenv("MODEL_NAME")  # 可选,留空则使用默认模型

# 创建模型实例
llm = ModelFactory.get_model(
    provider=CURRENT_PROVIDER,
    model=CURRENT_MODEL,
    temperature=0.7
)

# 以下代码无需任何修改,即可自动适配当前模型
print(f"当前使用的模型供应商: {CURRENT_PROVIDER}")
question = "请用一句话介绍什么是LangChain"
response = llm.invoke([HumanMessage(content=question)])
print(f"回答: {response.content}")
print(f"Token使用情况: {response.response_metadata.get('token_usage', {})}")

对应的.env配置

# 选择当前使用的模型供应商(openai / tongyi / deepseek / zhipu)
PROVIDER=tongyi

# 可选:指定具体模型名称
MODEL_NAME=qwen-plus

# API密钥保持各自的
OPENAI_API_KEY=sk-xxx
DASHSCOPE_API_KEY=sk-xxx
DEEPSEEK_API_KEY=sk-xxx

核心优势:当你想切换模型时,只需修改.env中的PROVIDER值,业务代码一行都不用改。这完美体现了LangChain“统一接口”的设计哲学。


完整可运行Python代码(带逐行详细注释)

将四个实战整合为一个独立脚本,可直接复制运行。只需确保.env文件中配置好了至少一个模型的API密钥。

文件multi_model_demo.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
LangChain第3课:OpenAI、通义千问、DeepSeek 通用调用完整演示
"""

import os
import sys
from dotenv import load_dotenv
from langchain_core.messages import HumanMessage

# 加载 .env 文件中的环境变量
load_dotenv()


# ============================================================
# 第一部分:OpenAI 调用(官方方式)
# ============================================================
def demo_openai():
    """演示 OpenAI 官方模型调用"""
    print("\n" + "=" * 60)
    print("【演示一】OpenAI 模型调用")
    print("=" * 60)
    
    try:
        from langchain_openai import ChatOpenAI
        
        # 从环境变量读取API密钥
        api_key = os.getenv("OPENAI_API_KEY")
        if not api_key:
            print("⚠️ 未配置 OPENAI_API_KEY,跳过 OpenAI 演示")
            return
        
        # 初始化模型
        llm = ChatOpenAI(
            model="gpt-4o-mini",      # 模型名称,性价比高
            temperature=0.7,           # 控制随机性
            timeout=60,                # 超时时间(秒)
            max_retries=2              # 失败重试次数
        )
        
        # 调用模型
        messages = [HumanMessage(content="请用一句话介绍什么是LangChain")]
        response = llm.invoke(messages)
        
        print("✓ OpenAI 调用成功!")
        print(f"回答: {response.content}")
        print(f"Token消耗: {response.response_metadata.get('token_usage', {})}")
        
    except ImportError:
        print("✗ 未安装 langchain-openai,请执行: pip install langchain-openai")
    except Exception as e:
        print(f"✗ OpenAI 调用失败: {e}")


# ============================================================
# 第二部分:通义千问调用
# ============================================================
def demo_tongyi():
    """演示通义千问(阿里云 Qwen)模型调用"""
    print("\n" + "=" * 60)
    print("【演示二】通义千问(Qwen)模型调用")
    print("=" * 60)
    
    # 检查依赖
    try:
        import dashscope
        from langchain_community.chat_models.tongyi import ChatTongyi
    except ImportError:
        print("✗ 未安装 dashscope,请执行: pip install dashscope")
        return
    
    # 检查API密钥
    api_key = os.getenv("DASHSCOPE_API_KEY")
    if not api_key:
        print("⚠️ 未配置 DASHSCOPE_API_KEY,跳过通义千问演示")
        return
    
    # 初始化模型
    llm = ChatTongyi(
        model="qwen-plus",            # qwen-plus 平衡性能与成本
        temperature=0.7,
        dashscope_api_key=api_key
    )
    
    # 调用模型
    messages = [HumanMessage(content="请用一句话介绍什么是RAG检索增强生成")]
    response = llm.invoke(messages)
    
    print("✓ 通义千问调用成功!")
    print(f"回答: {response.content}")
    print(f"Token消耗: {response.response_metadata.get('token_usage', {})}")


# ============================================================
# 第三部分:DeepSeek 调用(官方包方式)
# ============================================================
def demo_deepseek():
    """演示 DeepSeek 模型调用"""
    print("\n" + "=" * 60)
    print("【演示三】DeepSeek 模型调用")
    print("=" * 60)
    
    # 检查依赖
    try:
        from langchain_deepseek import ChatDeepSeek
    except ImportError:
        print("✗ 未安装 langchain-deepseek,请执行: pip install langchain-deepseek")
        return
    
    # 检查API密钥
    api_key = os.getenv("DEEPSEEK_API_KEY")
    if not api_key:
        print("⚠️ 未配置 DEEPSEEK_API_KEY,跳过 DeepSeek 演示")
        return
    
    # 初始化模型
    # 注意:截至2026年5月,DeepSeek推荐使用 deepseek-v4-flash 或 deepseek-v4-pro
    # 此处使用 deepseek-chat 保持向后兼容,后续请切换至新模型名
    llm = ChatDeepSeek(
        model="deepseek-chat",
        temperature=0.7,
        api_key=api_key,
        timeout=60
    )
    
    # 调用模型
    messages = [HumanMessage(content="请用一句话介绍什么是Agent智能体")]
    response = llm.invoke(messages)
    
    print("✓ DeepSeek 调用成功!")
    print(f"回答: {response.content}")
    print(f"元数据: {response.response_metadata}")


# ============================================================
# 第四部分:多模型切换工厂
# ============================================================
class ModelFactory:
    """
    模型工厂类:根据配置字符串返回对应的模型实例
    支持模型:openai, tongyi, deepseek, zhipu
    """
    
    @staticmethod
    def get_model(provider: str, model: str = None, temperature: float = 0.7):
        """
        获取指定供应商的模型实例
        
        Args:
            provider: 模型供应商(openai/tongyi/deepseek/zhipu)
            model: 模型名称(可选,不传则使用默认)
            temperature: 温度参数
        
        Returns:
            BaseChatModel实例
        """
        provider_lower = provider.lower()
        
        if provider_lower == "openai":
            from langchain_openai import ChatOpenAI
            return ChatOpenAI(
                model=model or "gpt-4o-mini",
                temperature=temperature
            )
        
        elif provider_lower == "tongyi":
            from langchain_community.chat_models.tongyi import ChatTongyi
            return ChatTongyi(
                model=model or "qwen-plus",
                temperature=temperature,
                dashscope_api_key=os.getenv("DASHSCOPE_API_KEY")
            )
        
        elif provider_lower == "deepseek":
            from langchain_deepseek import ChatDeepSeek
            return ChatDeepSeek(
                model=model or "deepseek-chat",
                temperature=temperature,
                api_key=os.getenv("DEEPSEEK_API_KEY")
            )
        
        elif provider_lower == "zhipu":
            from langchain_openai import ChatOpenAI
            return ChatOpenAI(
                model=model or "glm-4",
                openai_api_key=os.getenv("ZHIPU_API_KEY"),
                openai_api_base=os.getenv("BASE_URL"),
                temperature=temperature
            )
        
        else:
            raise ValueError(f"不支持的模型供应商: {provider}")


def demo_model_factory():
    """演示模型工厂:多模型一键切换"""
    print("\n" + "=" * 60)
    print("【演示四】模型工厂 - 多模型一键切换")
    print("=" * 60)
    
    # 从环境变量读取当前使用的模型供应商
    current_provider = os.getenv("PROVIDER", "tongyi")
    
    print(f"当前配置的模型供应商: {current_provider}")
    
    try:
        # 通过工厂创建模型实例
        llm = ModelFactory.get_model(
            provider=current_provider,
            temperature=0.7
        )
        
        # 统一的业务逻辑
        question = "请用一句话介绍什么是大语言模型(LLM)"
        response = llm.invoke([HumanMessage(content=question)])
        
        print(f"✓ {current_provider.upper()} 调用成功!")
        print(f"问题: {question}")
        print(f"回答: {response.content}")
        
    except Exception as e:
        print(f"✗ {current_provider} 调用失败: {e}")
        print("  请检查环境变量配置(OPENAI_API_KEY / DASHSCOPE_API_KEY / DEEPSEEK_API_KEY)")


# ============================================================
# 主函数
# ============================================================
def main():
    """主入口:依次执行所有演示"""
    print("\n" + "=" * 60)
    print("LangChain 第3课:多模型通用调用完整演示")
    print("=" * 60)
    
    # 依次执行各个演示
    demo_openai()
    demo_tongyi()
    demo_deepseek()
    demo_model_factory()
    
    print("\n" + "=" * 60)
    print("所有演示执行完毕")
    print("=" * 60)


if __name__ == "__main__":
    main()

环境依赖安装命令

# 激活虚拟环境
source venv/bin/activate  # Mac/Linux
# venv\Scripts\activate   # Windows

# LangChain核心依赖
pip install langchain==0.3.7 langchain-core==0.3.21 langchain-openai==0.2.8 python-dotenv==1.0.1

# 通义千问依赖(ChatTongyi方式)
pip install dashscope

# DeepSeek官方集成包
pip install langchain-deepseek

# [可选] 通义千问的OpenAI兼容方式无需额外包
# [可选] 智谱AI已在第1课中配置

# 一键安装全部依赖(推荐)
pip install langchain==0.3.7 langchain-core==0.3.21 langchain-openai==0.2.8 python-dotenv==1.0.1 dashscope langchain-deepseek

常见报错坑点与避坑方案

坑1:ImportError: cannot import name 'ChatTongyi' from 'langchain_community.chat_models.tongyi'

原因:未安装dashscope包。

解决:执行pip install dashscope

坑2:ImportError: No module named 'langchain_deepseek'

原因:未安装langchain-deepseek包。

解决:执行pip install langchain-deepseek。或使用OpenAI兼容方式接入,无需此包。

坑3:通义千问返回 "code": "InvalidApiKey" 或 401错误

原因:API密钥无效或过期。

解决

  • 登录阿里云百炼控制台重新生成API Key。
  • 确认环境变量名正确:DASHSCOPE_API_KEY(非QWEN_API_KEY)。

坑4:DeepSeek调用返回 404: model not found

原因:模型名称不正确,或使用了已废弃的旧模型名。

解决:截至2026年5月,DeepSeek推荐使用deepseek-v4-flashdeepseek-v4-pro作为模型名称。旧的deepseek-chatdeepseek-reasoner将于2026年7月24日停止使用。建议尽快迁移至新模型名:

# 旧写法(即将废弃)
llm = ChatDeepSeek(model="deepseek-chat")

# 新写法(推荐)
llm = ChatDeepSeek(model="deepseek-v4-flash")

坑5:OpenAI调用报 RateLimitError 限流

原因:请求频率超过API限制(免费账号每分钟数次的限制)。

解决

  • 增加max_retries参数,让SDK自动重试。
  • 使用batch方法时降低max_concurrency
  • 升级到付费套餐。

坑6:dotenv加载.env文件不生效

原因.env文件位置不对,或文件名拼写错误。

解决

  • 确保.env文件与脚本在同一目录,或在项目根目录。
  • 使用load_dotenv(verbose=True)查看加载状态。
  • 尝试指定路径:load_dotenv(dotenv_path="/path/to/.env")

坑7:ChatOpenAI初始化时base_url参数名错误

原因:不同LangChain版本中参数名不同。0.1.x使用openai_api_base,0.3.x仍支持该参数但推荐使用base_url

解决:使用openai_api_base保持向后兼容:

llm = ChatOpenAI(
    openai_api_key="xxx",
    openai_api_base="https://api.deepseek.com/v1",  # 使用此参数名更稳妥
    model="deepseek-chat"
)

本节核心知识点总结

📌 LangChain的统一模型接口:所有模型都继承自BaseChatModel,提供相同的.invoke().stream().batch()等方法,实现“One API for any model”。

📌 模型切换的“三种方式”

  • 官方集成包langchain-openailangchain-community.tongyilangchain-deepseek
  • OpenAI兼容接口:通过ChatOpenAI+base_url接入任何兼容OpenAI格式的模型。
  • 自定义包装:编写自定义Runnable封装原生API(高级)。

📌 OpenAI调用:使用from langchain_openai import ChatOpenAI,核心参数是modeltemperature。国内访问可通过base_url配置代理。

📌 通义千问调用:使用from langchain_community.chat_models.tongyi import ChatTongyi,需要安装dashscope包。主要模型:qwen-max(最强)、qwen-plus(均衡)、qwen-flash(高性价比)。

📌 DeepSeek调用:官方包langchain-deepseek提供ChatDeepSeek类。新用户赠送500万tokens免费额度,性价比极高。注意模型名称即将升级迁移。

📌 模型工厂模式:通过配置文件(.env)定义当前使用的模型供应商,业务代码完全复用,实现“一键切换模型”。

📌 API密钥管理最佳实践

  • 使用.env文件管理,绝不硬编码。
  • 各厂商密钥环境变量各不相同:OPENAI_API_KEYDASHSCOPE_API_KEYDEEPSEEK_API_KEY
  • 通过python-dotenv自动加载。

课后练习题(含原题+标准答案+详细解析)

选择题

1. 以下哪一个是LangChain中所有大模型调用类都实现的统一基类?
A. BaseLLM
B. BaseChatModel
C. BaseLanguageModel
D. Runnable

2. 要通过OpenAI兼容方式接入DeepSeek API,以下代码中正确的是?
A. llm = ChatDeepSeek(model="deepseek-chat")
B. llm = ChatOpenAI(model="deepseek-chat", openai_api_key="xxx")
C. llm = ChatOpenAI(model="deepseek-chat", openai_api_base="https://api.openai.com/v1")
D. llm = ChatOpenAI(model="deepseek-chat", openai_api_key="xxx", openai_api_base="https://api.deepseek.com/v1")

3. 关于通义千问(Qwen)的接入方式,以下说法错误的是?
A. ChatTongyi需要安装dashscope
B. 通义千问可以通过OpenAI兼容接口接入
C. ChatTongyi的环境变量是QWEN_API_KEY
D. 通义千问有qwen-plusqwen-max等多个模型版本

4. 以下哪个是DeepSeek新版推荐使用的模型名称(截至2026年5月)?
A. deepseek-chat
B. deepseek-v3
C. deepseek-v4-flash
D. deepseek-reasoner

答案及解析:

  1. B。所有聊天模型都继承自BaseChatModel,它定义了invokestream等核心方法。BaseLLM是早期的文本补全模型基类(已逐渐废弃)。Runnable是所有可调用组件的基类,但模型通常以其作为父接口,具体实现为BaseChatModel

  2. DChatOpenAI通过配置openai_api_base指向DeepSeek官方兼容端点https://api.deepseek.com/v1,同时传入DeepSeek的API密钥。选项A是官方包方式而非兼容方式;选项B缺少base_url配置;选项C指向了OpenAI官方端点。

  3. CChatTongyi使用的环境变量是DASHSCOPE_API_KEYQWEN_API_KEY不是标准环境变量名。其他选项均正确。

  4. C。根据DeepSeek官方更新日志,旧模型名deepseek-chatdeepseek-reasoner将于2026年7月24日停止使用,新模型名应为deepseek-v4-prodeepseek-v4-flash

简答题

5. 请对比 LangChain 接入大模型的“官方集成包”和“OpenAI兼容接口”两种方式的优缺点。

参考答案

维度 官方集成包 OpenAI兼容接口
优点 类型提示完整,模型特有参数支持好(如通义千问的enable_search),官方维护更新及时 代码高度复用,切换模型只需改几行配置,业务逻辑完全不变
缺点 每个模型需记忆不同的类名和初始化参数,代码改动较大 可能无法完全利用某些模型的特色功能(如专用参数),部分模型兼容性不够完美

使用建议:快速原型开发时优先使用OpenAI兼容方式,追求功能完整性和稳定性时使用官方集成包。

6. 设计一个方案,在你的LangChain应用中实现“模型热切换”(不重启服务即可切换模型)。

参考答案:可以使用以下方案:

  • 将模型供应商和模型名称配置在配置文件(如.env或YAML)或数据库配置表中。
  • 在代码中使用模型工厂模式(如本课中的ModelFactory),每次调用模型时根据当前配置动态创建实例。
  • 对于需要长期运行的服务,可使用lru_cachefunctools.lru_cache缓存模型实例,避免频繁创建的开销。
  • 如需实时切换而不重启服务,可监听配置文件变更(如使用watchdog库),配置文件变化时自动过期原有缓存,重新创建模型实例。

实践题

7. 编写一段代码,实现一个函数ask_with_cost_tracking(query: str) -> dict,该函数调用任意LangChain模型,返回结果和本次调用的token消耗统计,要求返回格式为{"answer": str, "input_tokens": int, "output_tokens": int, "total_tokens": int, "cost_usd": float}(假设OpenAI定价:输入$0.15/1M tokens,输出$0.6/1M tokens)。

参考答案

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

load_dotenv()

# 定价参考 OpenAI GPT-4o-mini(2025年标准)
PRICE_INPUT_PER_1K = 0.00015      # $0.15 per 1M = $0.00015 per 1K
PRICE_OUTPUT_PER_1K = 0.0006      # $0.60 per 1M = $0.0006 per 1K

def ask_with_cost_tracking(query: str) -> dict:
    """
    调用模型并返回答案和Token消耗统计
    
    Args:
        query: 用户问题
        
    Returns:
        包含答案和Token统计的字典
    """
    llm = ChatOpenAI(
        model="gpt-4o-mini",
        temperature=0.7
    )
    
    response = llm.invoke([HumanMessage(content=query)])
    
    token_usage = response.response_metadata.get("token_usage", {})
    input_tokens = token_usage.get("prompt_tokens", 0)   # 输入Token数
    output_tokens = token_usage.get("completion_tokens", 0)  # 输出Token数
    total_tokens = token_usage.get("total_tokens", 0)
    
    # 计算成本(单位:USD)
    cost_usd = (input_tokens / 1000 * PRICE_INPUT_PER_1K) + (output_tokens / 1000 * PRICE_OUTPUT_PER_1K)
    
    return {
        "answer": response.content,
        "input_tokens": input_tokens,
        "output_tokens": output_tokens,
        "total_tokens": total_tokens,
        "cost_usd": round(cost_usd, 6)
    }

# 示例调用
if __name__ == "__main__":
    result = ask_with_cost_tracking("介绍LangChain的核心功能")
    print(f"答案: {result['answer']}")
    print(f"输入Token: {result['input_tokens']}")
    print(f"输出Token: {result['output_tokens']}")
    print(f"总Token: {result['total_tokens']}")
    print(f"成本: ${result['cost_usd']}")

解析:此题目考察对模型响应的元数据解析能力。response.response_metadata中的token_usage字段包含了prompt_tokens(输入)和completion_tokens(输出),根据不同模型的定价公式可计算出单次调用的成本。这对于在生产环境中控制API开销非常实用。


🔗《30节课 LangChain 从入门到精通》系列课程导航

去订阅

🌟 感谢您耐心阅读到这里!
💡 如果本文对您有所启发欢迎:
👍 点赞📌 收藏 📤 分享给更多需要的伙伴。
🗣️ 期待在评论区看到您的想法, 共同进步。
🔔 关注我,持续获取更多干货内容~
🤗 我们下篇文章见~

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐