← 全部文章

LLM API SDK 集成模式:OpenAI SDK、原生 SDK 与直接 HTTP 的跨厂商选型指南

每个 LLM API 项目都面临一个起点选择:用 OpenAI Python SDK 配合自定义 base_url,用厂商自带的原生 SDK,还是直接调 HTTP。我们拆解三种模式各自的适用场景、局限和踩坑经验,讲清路由层如何受益于 OpenAI SDK 标准化。

· TheRouter

每个 LLM API 集成项目都从同一个分叉开始。手里有 API key,有模型名称,有要完成的任务,接下来要决定代码怎么跟厂商通信。三个选项摆在面前,把 OpenAI Python/TypeScript SDK 的 base_url 指向目标厂商、用厂商自己的原生 SDK、直接发 HTTP 请求。第一天看起来差不多,等你需要流式输出、tool calling、结构化输出或者多厂商容灾的时候,差距就拉开了。

我们在搭建 TheRouter 的时候选了 OpenAI SDK 兼容路线,因为它是 LLM API 生态里最接近通用适配器的东西。但兼容性在边界上断裂的场景,我们也全踩过。这篇指南记录了我们的经验,该选哪种模式、每种模式的代价在哪里、兼容性的裂缝藏在什么地方。

OpenAI 兼容指供应商提供一个 chat-completions 接口,其请求与响应结构与 OpenAI API 契约足够接近——只需替换三个值(API key、base URL、模型名),原来的 OpenAI SDK 调用即可直接工作。最小实践面是POST /v1/chat/completions 带 messages、model, 并返回 OpenAI 形式的流式响应。

三种集成模式

在比较厂商之前,先看看每种模式在代码层面到底意味着什么。

模式一:OpenAI SDK + 自定义 base_url

装好 openai 包,改两行配置,api_key 和 base_url。剩下的代码不管打哪个厂商,写法完全一样。

from openai import OpenAI

# DeepSeek
client = OpenAI(
    api_key="sk-deepseek-...",
    base_url="https://api.deepseek.com",
)

# DashScope(通义千问)
client = OpenAI(
    api_key="sk-dashscope-...",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

# SiliconFlow(硅基流动)
client = OpenAI(
    api_key="sk-siliconflow-...",
    base_url="https://api.siliconflow.cn/v1",
)

response = client.chat.completions.create(
    model="deepseek-v4-flash",  # 按厂商换模型名
    messages=[{"role": "user", "content": "Hello"}],
)

拿到了什么 一个依赖,一套接口,代码在所有支持 /v1/chat/completions 协议的厂商之间可以直接迁移。

丢掉了什么 厂商在 OpenAI 兼容层之外提供的一切功能。DashScope 的异步任务 API、Anthropic 的 extended thinking blocks、Kimi 的聊天内文件上传,这些在 OpenAI SDK 的类型系统里都不存在。

模式二:厂商原生 SDK

每家主要厂商都有自己的 SDK。Anthropic 有 anthropic,Google 有 google-genai,DashScope 有 dashscope,火山引擎有 volcengine-ark。

import anthropic

client = anthropic.Anthropic(api_key="sk-ant-...")

response = client.messages.create(
    model="claude-sonnet-5-20260514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)

拿到了什么 完整访问厂商提供的每一个功能。带类型提示的厂商专属参数。更精确的错误类型。文档和你实际调用的端点完全对应。

丢掉了什么 可移植性。从 Anthropic 切到 DeepSeek 意味着重写每一个调用点。流式处理器、tool calling 解析器、重试逻辑,全都跟厂商绑死。

模式三:直接 HTTP

不装 SDK,自己构造请求,自己解析响应。

import httpx

response = httpx.post(
    "https://api.deepseek.com/chat/completions",
    headers={"Authorization": "Bearer sk-..."},
    json={
        "model": "deepseek-v4-flash",
        "messages": [{"role": "user", "content": "Hello"}],
    },
)

data = response.json()
print(data["choices"][0]["message"]["content"])

拿到了什么 零依赖。HTTP 行为完全可控,连接池、代理配置、自定义 header、重试时机全由你决定。任何语言都能用,不用等 SDK 发版。

丢掉了什么 类型安全。流式 SSE 解析。自动重试瞬态错误。每一个字节的集成代码都要自己维护。

哪些厂商支持 OpenAI SDK 兼容?

打着 "OpenAI 兼容" 旗号的端点,兼容程度参差不齐。下面是 2026 年 8 月各主要厂商的实际支持情况,均基于官方文档核实。

厂商Base URLChat Completions流式Tool Calling结构化输出视觉文件上传
DeepSeekhttps://api.deepseek.com完整完整完整完整完整通过消息体
DashScopehttps://dashscope.aliyuncs.com/compatible-mode/v1完整完整完整完整完整通过消息体
SiliconFlowhttps://api.siliconflow.cn/v1完整完整完整部分视模型通过消息体
Kimi/Moonshothttps://api.moonshot.ai/v1完整完整完整部分完整 (K2+)通过消息体
xAI (Grok)https://api.x.ai/v1完整完整完整完整完整通过消息体
Anthropic不适用(API 结构不同)需转换层格式不同schema 不同自有格式完整(原生)自有格式
Google (Gemini)仅 AI Studio仅 AI Studio格式不同schema 不同自有格式完整(原生)自有格式

数据来源见 DeepSeek API 文档(2026-08-12 检索)、DashScope OpenAI 兼容文档(2026-08-12 检索)、SiliconFlow 快速上手(2026-08-12 检索)、Kimi API 文档(2026-08-12 检索)、xAI API 文档(2026-08-12 检索)。

格局很清楚。国内厂商(DeepSeek、DashScope、SiliconFlow、Kimi)和 xAI 把 OpenAI 的 API 形态当作主接口来实现。Anthropic 和 Google 各自建了自己的 API 协议,兼容性只通过适配层或有限端点提供。

OpenAI SDK 兼容在哪里断裂

"兼容" 不等于 "一模一样"。以下是我们实际遇到过的差异。

流式 Delta 格式差异

大多数厂商在 chat.completions.chunk 的 SSE 格式上与 OpenAI 一致,但边缘场景会偏离。

思考/推理 token。 DeepSeek 和 DashScope 都支持 thinking mode,但它们把推理内容放在 choices[0].delta.reasoning_content 里。OpenAI SDK 的类型定义里没有这个字段。你可以从原始响应里读到它,但想用带类型的 SDK 访问就需要做类型转换或扩展。

流式中的 usage 统计。 OpenAI 加了 stream_options: {"include_usage": true} 让最后一个流式 chunk 返回 token 用量。DashScope 支持。部分 SiliconFlow 模型在流式响应中完全不返回 usage。

停止原因的粒度。 Kimi 有时返回的 stop reason 不在 OpenAI 的枚举范围内("length"、"stop"、"tool_calls"、"content_filter")。OpenAI SDK 会默默接受未知值,但下游代码如果对 finish_reason 做 switch,可能漏掉分支。

Tool Calling Schema 差异

Tool calling 是兼容性压力最大的地方。

并行 tool calls。 OpenAI 默认 parallel_tool_calls: true。DeepSeek 跟进了。DashScope 默认顺序执行(每次响应只返回一个 tool call),除非你显式传并行参数。

Tool choice 强制。 tool_choice: "required" 强制模型必须调用工具。DeepSeek 和 DashScope 支持。SiliconFlow 的支持取决于底层模型,有些托管模型会直接忽略 tool_choice。

函数名约束。 OpenAI 允许函数名包含连字符和点号。部分厂商拒绝包含点号的名称,或者对名称长度有不同限制。如果你从现有函数签名自动生成 tool 定义,这个差异会导致调用失败。

结构化输出支持

OpenAI 的 response_format: { type: "json_schema", json_schema: {...} } 是保证响应符合指定 schema 的标杆方案。各厂商支持程度不一。

DeepSeek 完整支持,会把 json_schema 传给模型并强制执行。DashScope 对支持该特性的 Qwen 模型提供完整支持。SiliconFlow 因托管模型而异,开源模型可能只支持 response_format: { type: "json_object" } 而无法做完整的 json_schema 强制。Kimi 支持 json_object 模式,完整 json_schema 支持取决于模型版本。

什么时候该用厂商原生 SDK

OpenAI SDK 兼容层覆盖了常见场景。当你需要的功能超出 OpenAI API 形态的覆盖范围时,原生 SDK 带来的收益值得牺牲可移植性。

Anthropic:Extended Thinking 和结构化输出

Anthropic 的 Messages API 与 OpenAI 的 Chat Completions 形态不同。原生 anthropic SDK 提供以下能力。

Extended thinking blocks。 带 budget_tokens 参数的 thinking 内容块。OpenAI 兼容层里没有对应物。

原生结构化输出。 Anthropic 的结构化输出走 tool 定义,和 OpenAI 的 json_schema 方式有本质区别。

Prompt caching。 通过 anthropic-beta: prompt-caching-2024-07-31 header 控制,原生 SDK 内置了 cache breakpoint 支持。

流式事件类型。 message_start、content_block_start、content_block_delta,和 OpenAI 的 chat.completion.chunk 是完全不同的流式模型。

如果你的应用重度使用 extended thinking 或者 Anthropic 特有功能,原生 SDK 是正确的选择。

DashScope:异步任务和非 Chat 端点

DashScope 的原生 dashscope SDK 开放了以下能力。

异步任务提交。 dashscope.Generation.call(result_format='message', ...) 支持异步轮询长耗时请求。

非 Chat 端点。 embeddings、reranking、图片生成、音频处理,部分功能无法通过 OpenAI 兼容面访问。

Qwen 专属参数。 enable_search 开启内置网页搜索,incremental_output 控制流式行为。

OpenAI 兼容端点覆盖了 chat,但如果你需要 DashScope 平台的完整能力,原生 SDK 更完整。

Google:多模态和 Grounding

Google 的 google-genai SDK 提供以下能力。

原生多模态输入。 PDF、视频、音频作为一等输入类型,不只是图片。

Google Search Grounding。 内置的网页搜索增强,带引用归属。

代码执行。 作为 tool 类型的沙箱代码执行。

上下文缓存。 显式创建和复用缓存。

Google AI Studio 对基础 chat 提供了 OpenAI 兼容端点,但丰富的多模态和 grounding 功能需要原生 SDK。

什么时候直接 HTTP 更合适

直接 HTTP 不是默认选择,但在特定场景下它是最合理的。

你在用一个没有成熟 SDK 的语言。 Rust、Go、C++ 有社区维护的 OpenAI SDK 封装,但它们跟不上官方 Python 和 TypeScript SDK 的更新节奏。直接 HTTP 让你第一时间用上新功能。

你需要非标准的 HTTP 行为。 定制代理链、双向 TLS、请求签名、或者对延迟敏感的连接池管理,SDK 的 httpx(Python)或 fetch(TypeScript)客户端可能没有暴露你需要的控制项。

你自己就在做请求路由。 如果你已经有一个 HTTP 中间件层(比如 TheRouter),SDK 只是多加了一层你用不到的抽象。你的路由器收到原始 HTTP,做路由决策,转发原始 HTTP。两端都不需要 SDK。

你要调的是 beta 端点。 厂商发布新端点的速度总是比 SDK 适配快。直接 HTTP 让你立即调用。

选型决策矩阵

你的场景推荐模式原因
单一厂商,标准 chat/completionOpenAI SDK(原生或配 base_url)最简单的配置,类型完善,自动重试
多厂商容灾或路由OpenAI SDK + 可配置 base_url换厂商只改两行配置
需要厂商特有功能(thinking、grounding、异步任务)该厂商的原生 SDKOpenAI 兼容面之外的功能只能通过原生 SDK 访问
在搭路由层或代理直接 HTTP没有 SDK 开销,请求/响应生命周期完全可控
用的语言没有成熟 SDK直接 HTTP社区 SDK 封装更新慢,HTTP 是通用的
在多厂商之间快速验证原型OpenAI SDK用同一段代码测不同厂商,最快的方式
生产流水线需要严格 schema 控制OpenAI SDK + 厂商特定回退常规路径用 OpenAI SDK,边缘场景用原生 SDK

代码示例:同一个任务,三种实现

下面用同一个任务,对 DeepSeek API 发起带 tool calling 的流式 chat completion,分别用三种模式实现。

OpenAI SDK

from openai import OpenAI

client = OpenAI(
    api_key="sk-...",
    base_url="https://api.deepseek.com",
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string"},
                },
                "required": ["location"],
            },
        },
    }
]

stream = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[{"role": "user", "content": "What is the weather in Tokyo?"}],
    tools=tools,
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.tool_calls:
        for tc in delta.tool_calls:
            print(f"Tool call: {tc.function.name}({tc.function.arguments})")
    elif delta.content:
        print(delta.content, end="")

直接 HTTP

import httpx
import json

url = "https://api.deepseek.com/chat/completions"
headers = {
    "Authorization": "Bearer sk-...",
    "Content-Type": "application/json",
}
payload = {
    "model": "deepseek-v4-flash",
    "messages": [{"role": "user", "content": "What is the weather in Tokyo?"}],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_weather",
                "description": "Get the current weather",
                "parameters": {
                    "type": "object",
                    "properties": {"location": {"type": "string"}},
                    "required": ["location"],
                },
            },
        }
    ],
    "stream": True,
}

with httpx.stream("POST", url, headers=headers, json=payload) as resp:
    for line in resp.iter_lines():
        if line.startswith("data: ") and line != "data: [DONE]":
            chunk = json.loads(line[6:])
            delta = chunk["choices"][0]["delta"]
            if "tool_calls" in delta:
                for tc in delta["tool_calls"]:
                    fn = tc.get("function", {})
                    print(f"Tool call: {fn.get('name', '')}({fn.get('arguments', '')})")
            elif "content" in delta and delta["content"]:
                print(delta["content"], end="")

TypeScript(Vercel AI SDK)

import { openai } from "@ai-sdk/openai";
import { streamText, tool } from "ai";
import { z } from "zod";

const result = streamText({
  model: openai("deepseek-v4-flash", {
    baseURL: "https://api.deepseek.com",
    apiKey: "sk-...",
  }),
  messages: [{ role: "user", content: "What is the weather in Tokyo?" }],
  tools: {
    getWeather: tool({
      description: "Get the current weather",
      parameters: z.object({ location: z.string() }),
    }),
  },
});

for await (const part of result.fullStream) {
  if (part.type === "tool-call") {
    console.log(`Tool call: ${part.toolName}(${JSON.stringify(part.args)})`);
  } else if (part.type === "text-delta") {
    process.stdout.write(part.textDelta);
  }
}

路由层如何受益于 OpenAI SDK 标准化

这么多厂商采用 OpenAI 的 API 形态,靠的是网络效应。所有讲 OpenAI 协议的工具、框架和路由层,都可以无需厂商专属适配器就接入任意兼容厂商。

对 TheRouter 而言,OpenAI SDK 标准化意味着我们可以在已配置的厂商之间路由请求,而不用重写请求体。一个 /v1/chat/completions 请求进来,路由逻辑按配置规则选厂商,请求以最小改动转发出去。响应回来的格式不管哪个厂商提供的服务都一样。

这套机制能工作,前提是核心协议共享,包括请求 schema、响应 schema、流式格式。当某个厂商偏离(Anthropic 的 Messages API、Google 的 Gemini API),路由层就需要为每个偏离的厂商加一个翻译层。Bug 藏在这些翻译层里。

生产环境选型清单

在确定集成模式之前,过一遍这个清单。

  1. 列出你今天需要的每个厂商,以及未来 6 个月可能需要的。 如果答案是 "只有 OpenAI" 或 "只有 Anthropic",用它们的原生 SDK 就好。如果你需要两个或更多 OpenAI 兼容厂商,用 OpenAI SDK + 可配置 base_url 的收益立刻显现。

  2. 列出你在基础 chat 之外需要的每个功能。 Thinking mode、结构化输出、视觉理解、文件上传、embeddings、异步任务。对照上面的兼容性表格检查。如果某个关键功能在 OpenAI 兼容面之外,为那个特定调用准备原生 SDK 回退方案。

  3. 决定如何处理厂商故障。 如果答案是 "对同一个厂商重试",任何模式都行。如果答案是 "切换到另一个厂商",你需要统一接口,也就是 OpenAI SDK 或者路由层。

  4. 检查你的语言生态。 Python 和 TypeScript 有成熟的 OpenAI SDK。Java、Go、Rust、C++ 有社区封装,成熟度不一。如果你用的 SDK 不成熟,直接 HTTP 可能比一个半成品封装更可靠。

  5. 测试实际兼容性。 不要相信厂商的 "OpenAI 兼容" 标签。把你实际的 tool 定义、你实际的流式处理器、你实际的结构化输出 schema 发过去试。兼容性的裂缝出现在你的具体用法里,不在 hello-world 示例里。

  6. 为你够不到的功能做规划。 如果你为了可移植性选了 OpenAI SDK,但有一个工作流需要 Anthropic 的 extended thinking,为那个特定调用写一个薄适配层就好,不用把整个代码库转到原生 SDK。

常见问题

能用 OpenAI SDK 调 Anthropic 的 API 吗?

不能直接调。Anthropic 的 Messages API 请求/响应形态不同。一些代理服务和路由层(包括 TheRouter 在配置 Anthropic 为厂商时)可以在 OpenAI 和 Anthropic 格式之间做翻译,但原生 OpenAI SDK 仅靠切换 base_url 无法直接访问 api.anthropic.com。

改 base_url 会影响重试和超时行为吗?

不会。OpenAI SDK 的重试逻辑、超时设置、连接池管理不受 base_url 指向哪里的影响。厂商的服务端限流仍然生效,SDK 只是按配置对 429 和 5xx 做重试。

厂商新增了一个 OpenAI SDK 不支持的参数怎么办?

可以通过 Python SDK 的 extra_body 或 TypeScript SDK 的 body 传入未知参数。SDK 会把它们原样放进请求体,不做校验。这就是你通过 OpenAI SDK 访问厂商专属功能(比如 DashScope 的 enable_search)的方式,不用等 SDK 更新。

Vercel AI SDK 算第四种模式吗?

它是模式一和模式二之上的抽象层。Vercel AI SDK(ai 包)提供了统一的 streamText/generateText 接口,每个厂商有对应的 adapter。它在前端侧重的 TypeScript 应用里很有用,但多加了一层抽象。底层每个 adapter 调的还是厂商的 API,通常走 OpenAI 兼容路径或原生 SDK。

该不该用 LiteLLM 而不是自己管 base_url?

LiteLLM 是一个 Python 代理,把 100 多个厂商的 API 归一化成 OpenAI 格式。它解决的问题和自己管 base_url 一样,但多了一个依赖和一个翻译层。如果你需要接很多厂商又不想自己处理兼容性差异,LiteLLM 或者像 TheRouter 这样的路由层是合理的选择。如果你只用 2 到 3 个 OpenAI 兼容厂商,直接管 base_url 更简单。


本文引用的数据来源包括 DeepSeek API 文档(2026-08-12 检索)、DashScope OpenAI 兼容文档(2026-08-12 检索)、SiliconFlow 快速上手(2026-08-12 检索)、Kimi API 文档(2026-08-12 检索)、xAI API 文档(2026-08-12 检索)、Anthropic Messages API 参考(2026-08-12 检索)、OpenAI Python SDK 仓库(2026-08-12 检索)。

帮助与联系