创见博客
什么是 ChatOpenAI 兼容写法:一个 baseURL 打通所有大模型
七崽爱吃小饼干2026/10/13阅读 0专栏 LangChain 开发实战

在接入大模型 API 时,你可能见过这样的说法:“这个模型支持 OpenAI 兼容接口。” 在 LangChain 里,与之对应的就是所谓的 ChatOpenAI 兼容写法——不去找某个厂商的专属 SDK,而是直接用 ChatOpenAI,把请求地址指向目标服务的 baseURL。听起来像个小技巧,实际上它背后是一套被广泛采纳的行业事实标准。这篇文章讲清楚三件事:它是什么、为什么要这样写、以及具体怎么实现。

一、什么是 ChatOpenAI 兼容写法

先看一段代码:

js
import { ChatOpenAI } from "@langchain/openai";

const model = new ChatOpenAI({
  model: "deepseek-chat",
  apiKey: process.env.DEEPSEEK_API_KEY,
  configuration: {
    baseURL: "https://api.deepseek.com",
  },
});

const res = await model.invoke("用一句话介绍你自己");
console.log(res.content);

严格来说,这里用的类叫 ChatOpenAI,但调用的却是 DeepSeek 的模型。这就是“ChatOpenAI 兼容写法”的核心:

  • 用统一的 ChatOpenAI 客户端,而不是每家厂商的专属类;
  • 通过 configuration.baseURL 把请求指向不同服务;
  • 请求和响应的数据结构遵循 OpenAI 的接口规范(/chat/completions、messages、choices 等)。

换句话说,只要某个服务的 API 在“形状”上和 OpenAI 一致,就可以被 ChatOpenAI 直接驱动。DeepSeek、Moonshot、通义千问、智谱、本地的 Ollama / vLLM 等,大多都提供了这样的兼容端点。

需要区分的是:LangChain 里的 @langchain/deepseek 包其实也是基于兼容写法实现的——它的 ChatDeepSeek 本质上继承自 OpenAI 的聊天模型,只是内置了 baseURL 和 DEEPSEEK_API_KEY 的默认值,帮你省掉了几行配置。所以专属包和兼容写法并不矛盾,后者是更底层、更通用的形态。

二、为什么需要这个兼容写法

1. OpenAI 的接口成了事实标准

ChatGPT 的爆发让 OpenAI 的 /chat/completions 接口成为业界最熟悉的协议。整个生态——SDK、中间件、可观测工具、网关——几乎都围绕它构建。新厂商如果自创一套接口,就要用户重新学习、重新适配;而如果对齐 OpenAI 协议,用户几乎零成本迁移。

2. 对厂商:降低接入成本,抢占生态

提供 OpenAI 兼容端点,意味着开发者可以把现有基于 OpenAI 的代码改一个 baseURL 就切过来,迁移摩擦极小。这是一种务实的获客策略。

3. 对开发者:一次学习,处处调用

如果没有兼容写法,你要为每个厂商引入不同的 SDK、记住不同的参数名和响应结构。有了它,代码里只保留一个 ChatOpenAI,切换模型只是改配置:

js
function createModel({ baseURL, apiKey, model }) {
  return new ChatOpenAI({
    model,
    apiKey,
    configuration: { baseURL },
  });
}

const deepseek = createModel({
  baseURL: "https://api.deepseek.com",
  apiKey: process.env.DEEPSEEK_API_KEY,
  model: "deepseek-chat",
});

const ollama = createModel({
  baseURL: "http://localhost:11434/v1",
  apiKey: "ollama",
  model: "llama3",
});

切换成本从“重写调用层”降到“改一个配置对象”。

4. 对上层框架:统一抽象更简单

LangChain 的 Chain、Agent、工具调用、结构化输出等能力,都建立在一套统一的模型接口之上(如 invoke、stream、bindTools)。当底层模型都走 OpenAI 协议时,这些能力天然可以复用,无需为每个厂商单独适配。这也是为什么很多“兼容包”选择站在 ChatOpenAI 的肩膀上。

当然,兼容写法并非万能:厂商特有的能力(比如 DeepSeek 的某些推理参数、专有工具)可能不在 OpenAI 协议里,此时仍需使用专属字段或专属包。但对绝大多数常规对话场景,兼容写法已经够用。

三、怎么实现

实现兼容写法,本质上就是配好两样东西:密钥 和 端点地址。

1. 安装依赖

bash
npm install @langchain/openai

2. 准备 API Key

沿用目标厂商的密钥,放进环境变量:

bash
export DEEPSEEK_API_KEY="sk-你的密钥"

3. 构造模型并指定 baseURL

js
import { ChatOpenAI } from "@langchain/openai";

const apiKey = process.env.DEEPSEEK_API_KEY;
if (!apiKey) {
  throw new Error("未找到 DEEPSEEK_API_KEY");
}

const model = new ChatOpenAI({
  model: "deepseek-chat",        // 目标厂商的模型名
  apiKey,                        // 目标厂商的密钥
  configuration: {
    baseURL: "https://api.deepseek.com", // 目标厂商的兼容端点
  },
});

关键点有三个:

  1. model 传目标厂商的模型名,而不是 OpenAI 的模型名;
  2. apiKey 传目标厂商的密钥——ChatOpenAI 默认读 OPENAI_API_KEY,所以这里要显式传入;
  3. configuration.baseURL 指向目标厂商的兼容接口地址。configuration 的类型来自 OpenAI 官方 SDK 的 ClientOptions,因此里面还能配置超时、自定义请求头、代理等。

4. 调用

配置好之后,用法和调用 OpenAI 完全一致:

js
const res = await model.invoke("用一句话介绍你自己");
console.log(res.content);

流式、多轮对话、工具调用等能力也一样可用:

js
// 流式输出
for await (const chunk of await model.stream("写一首关于秋天的短诗")) {
  process.stdout.write(chunk.content);
}

// 多轮对话
import { HumanMessage, SystemMessage } from "@langchain/core/messages";

const messages = [
  new SystemMessage("你是一个简洁的中文助手。"),
  new HumanMessage("LangChain 是什么?"),
];
const reply = await model.invoke(messages);
console.log(reply.content);

5. 关于 DeepSeek 的小提示

DeepSeek 的兼容端点地址是 https://api.deepseek.com(也可写成带 /v1 的形式),常用模型名为 deepseek-chat(通用对话)和 deepseek-reasoner(推理)。它的响应同样遵循 OpenAI 结构,所以上面的代码可以直接跑通。

如果你不想手动配 baseURL,也可以直接用 LangChain 提供的 @langchain/deepseek 包,它的 ChatDeepSeek 已经把这些默认值内置好了——这正是“专属包封装兼容写法”的典型例子。

四、小结

ChatOpenAI 兼容写法的本质,是把 OpenAI 的接口协议当成通用语言,用统一的 ChatOpenAI 客户端加一个可配置的 baseURL 来驱动不同厂商的模型。它之所以流行,是因为对厂商能降低接入门槛、对开发者能一次学习处处调用、对框架能复用统一抽象。实现上只需要三步:拿到厂商的 apiKey、填上厂商的 model 名、把 configuration.baseURL 指向兼容端点。

理解了这个模式,你就能在 DeepSeek、本地模型和各类兼容服务之间自由切换,而不必为每一家重新学习一套 SDK。

评论
0/100