【零基础入门 LLM 开发 · Day 11】:ChatOpenAI vs init_chat_model——一行换供应商

【零基础入门 LLM 开发 · Day 11】:ChatOpenAI vs init_chat_model------一行换供应商

场景

Day 10 起我们的代码都是这么开头的:

python 复制代码
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model=..., api_key=..., base_url=...)

直接实例化,直观明了。但它有个隐形约束:类名焊死了供应商 ------ChatOpenAI 只会说"OpenAI 协议"这一种话。哪天想试 Claude、Gemini 或本地模型,每个文件都要改 import 和构造代码。

最近的练习文件换成了另一种写法:init_chat_model。这篇讲清两者区别,顺便把常见供应商的接入写法一次备齐。

姿势一:ChatOpenAI 直连

python 复制代码
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model=os.getenv("YUMC_MODEL_NAME"),
    api_key=os.getenv("YUMC_MODEL_API_KEY"),
    base_url=os.getenv("YUMC_MODEL_BASE_URL"),  # 指向任何 OpenAI 兼容端点
    temperature=0.7,
)
  • 优点 :类型明确,IDE 补全参数一个不落;装的包也最少(langchain-openai 一个就够);
  • 局限:只会 OpenAI 协议。对"兼容端点"来说这恰恰不是缺点(见下文),但要接原生 Anthropic / Google 接口就得换类、换包。

姿势二:init_chat_model 工厂

python 复制代码
from langchain.chat_models import init_chat_model

model = init_chat_model(
    model=os.getenv("YUMC_MODEL_NAME"),
    model_provider="openai",        # 决定实际造出哪个类
    temperature=0,
    api_key=os.getenv("YUMC_MODEL_API_KEY"),
    base_url=os.getenv("YUMC_MODEL_BASE_URL"),
)

model_provider 是工厂的图纸 :"openai" → 内部实例化 ChatOpenAI,"anthropic" → ChatAnthropic......其余参数原样透传给对应的类。换供应商 = 改一个字符串。

验证一下工厂没骗你:

python 复制代码
model = init_chat_model(model="gpt-4o-mini", model_provider="openai")
print(type(model))   # <class 'langchain_openai.chat_models.base.ChatOpenAI'>
ChatOpenAI 直连 init_chat_model 工厂
本质 具体类 按字符串选类的工厂函数
换供应商 改 import + 构造代码 只改 model_provider(或配置)
IDE 补全 好 一般(返回类型是动态的)
依赖 只需对应一家的包 用哪家就得装哪家的包
适用 教学/demo、只用一家 多模型切换、通用工具

不同供应商的写法(速查表)

路线 A:官方集成包 ------每家一个 model_provider 值 + 一个要单独安装的包:

供应商 model_provider 需要安装 model 示例
OpenAI openai langchain-openai gpt-4o-mini
Anthropic anthropic langchain-anthropic claude-sonnet-4-5
Google google_genai langchain-google-genai gemini-2.0-flash
DeepSeek deepseek langchain-deepseek deepseek-chat
Ollama(本地) ollama langchain-ollama qwen2.5(本地已 pull 的模型名)
python 复制代码
model = init_chat_model("claude-sonnet-4-5", model_provider="anthropic")
# api_key 从环境变量 ANTHROPIC_API_KEY 自动读取,也可以显式传

路线 B:OpenAI 兼容协议 ------很多国产服务不提供官方集成包,但都提供"OpenAI 兼容接口",统统走 model_provider="openai" + 自家 base_url:

服务 base_url
智谱 GLM https://open.bigmodel.cn/api/paas/v4
Kimi(月之暗面) https://api.moonshot.cn/v1
通义千问(兼容模式) https://dashscope.aliyuncs.com/compatible-mode/v1
DeepSeek 官方 https://api.deepseek.com
你自己的 .env YUMC_MODEL_BASE_URL(本系列一直在用的就是这种)
python 复制代码
model = init_chat_model(
    model="glm-5.3-flash",
    model_provider="openai",                      # 协议是 OpenAI 的
    base_url="https://open.bigmodel.cn/api/paas/v4",  # 但地址是智谱的
    api_key=os.getenv("ZHIPU_API_KEY"),
)

本系列的 .env(YUMC_MODEL_*)就是路线 B:协议标准、地址自选。所以代码从 Day 1 到今天几乎没变过。

小技巧:新版还支持冒号简写,一行连供应商带模型名一起写:

python 复制代码
model = init_chat_model("openai:gpt-4o-mini")

怎么选?

  • 教学阶段 / 确定只用 OpenAI 系 :ChatOpenAI 直连------直观、补全友好;
  • 想随时切换模型对比效果 / 做通用工具 :init_chat_model------把供应商选择变成一行配置;
  • 两者可以混用:核心代码面向 LangChain 的统一消息/工具接口编程,初始化交给工厂。

今日踩坑点

  1. 没装对应的集成包 :init_chat_model(model_provider="anthropic") 但没装 langchain-anthropic,报 ModuleNotFoundError------工厂是按需导入的,图纸认了、零件没货。
  2. 兼容端点漏了 base_url :以为传了 api_key 就行,请求直奔官方 api.openai.com,拿着智谱的 key 报 401。路线 B 的 base_url 是命根子。
  3. 参数拼写错误被"透传" :init_chat_model(..., temperatre=0) 不报"参数不存在",而是把未知参数转发给底层类,最后在 API 调用时才炸:TypeError: unexpected keyword argument 'temperatre'------报错位置离案发现场很远(Day 14 的 methond 同款坑)。参数拼错先查构造处。
  4. 换了供应商 ≠ 行为一致 :bind_tools、with_structured_output 各家支持度不同(Day 14 的 json_schema 假装支持问题就是典型)。切了供应商,这些能力要重新验证。

今日小练习

  1. 必做:把 Day 10 的 ChatOpenAI 换成 init_chat_model,跑通同样的对话,print(type(model)) 亲眼看看工厂造出了什么。
  2. 进阶:写一个 load_model() 函数------供应商、模型名、密钥全部从 .env 读取,实现"不改一行代码换供应商"。
  3. 思考:把 base_url 改成一个不存在的地址,和直接删掉 base_url,分别报什么错?为什么报错不一样?

明日预告

Day 12:LangChain 流式输出------比 Day 5 手动拼 delta 简单得多,一行 for 搞定。


附录:完整练习代码

langchainTest4-tools2.py 的初始化段(tools 系列练习文件统一用这种写法)

python 复制代码
import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model

load_dotenv()
model = init_chat_model(
    model=os.getenv("YUMC_MODEL_NAME"),
    model_provider="openai",
    temperature=0,
    api_key=os.getenv("YUMC_MODEL_API_KEY"),
    base_url=os.getenv("YUMC_MODEL_BASE_URL"),
)

换供应商实战:只动 .env,代码零修改

python 复制代码
import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model

load_dotenv()

# .env 里配什么就用什么:
#   YUMC_MODEL_NAME=glm-5.3-flash
#   YUMC_MODEL_API_KEY=你的密钥
#   YUMC_MODEL_BASE_URL=https://open.bigmodel.cn/api/paas/v4
# 想换 Kimi?改这三行配置即可,下面的代码原封不动。
model = init_chat_model(
    model=os.getenv("YUMC_MODEL_NAME"),
    model_provider="openai",                     # 兼容协议走 openai
    api_key=os.getenv("YUMC_MODEL_API_KEY"),
    base_url=os.getenv("YUMC_MODEL_BASE_URL"),
)

response = model.invoke("用一句话介绍你自己")
print(response.content)
相关推荐
小码哥_常3 小时前
一套自己部署的 IM,客户端是同一份 Flutter
前端·后端
蜗牛攻城狮5 小时前
微前端四大方案选型对比与最佳实践:qiankun、micro-app、wujie、Module Federation
前端·微前端·qiankun·前端架构·micro-app·wujie
学长毕设6 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
她说可以呀6 小时前
Vue插槽
前端·javascript·vue.js
qq_448011166 小时前
Vue + Jinja2两套模版与法冲突造成undefinedError
前端·javascript·vue.js
zzu123zsw7 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
aixingpan7 小时前
aixingpan.cn API开发文档:前端查询夏令时和时区接口指南
前端·php
2601_958352907 小时前
23.5×19mm 换掉一整条音频链?|A-68 集成了什么:ADC / DAC / 24.576MHz 时钟 / AEC / 波束降噪,主控仅需 6 根线
前端·音视频·ai降噪·回声消除·语音模块
源码集结号8 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统
论文复现现场8 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算