ZBStream
Tutorials · API

一文打通 OpenAI 与 Anthropic 双接口:ZBStream API 实战指南

ZBStream · 2026-08-23 · Guide

同一个 ZBStream API Key,既可以说 OpenAI 方言(/v1/chat/completions),也可以说 Anthropic 方言(/v1/messages)。本文用 Python、Node.js、Go 三种语言把两种协议各跑一遍,并给出选型建议。

With one ZBStream API key you can speak both dialects — OpenAI's /v1/chat/completions and Anthropic's /v1/messages. This guide runs both protocols in Python, Node.js, and Go, then helps you pick the right one.

1为什么网关要同时支持两种协议 Why a gateway should speak both protocols

过去几年,OpenAI 的 Chat Completions 成了事实标准,绝大多数 SDK、框架和 Agent 工具默认讲这套协议。但 Claude 系列模型带火了另一套风格:system 是顶层字段、max_tokens 必填、响应是 content 块数组、流式事件更结构化。

如果你的技术栈里同时有两类组件——比如 Agent 框架走 Anthropic SDK,数据分析脚本走 OpenAI SDK——传统做法是分别向两家供应商申请 Key、分别管理额度。而通过 ZBStream,两套 SDK 指向同一个地址、共用一个积分账户:

OpenAI 兼容接口
https://api.zbstream.com/v1
openai-python / openai-node / go-openai 直接可用
Anthropic 兼容接口
https://api.zbstream.com
官方 anthropic SDK 只改 Base URL 即可用

2准备工作 Prerequisites

登录 ZBStream 控制台,在 API Keys 页面创建密钥,并确认账户有足够积分。模型名称通过 GET /v1/models 获取,注意大小写敏感。下文示例统一使用 deepseek-v4-pro 与环境变量 ZBSTREAM_API_KEY

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

curl https://api.zbstream.com/v1/models \
  -H "Authorization: Bearer $ZBSTREAM_API_KEY"

3OpenAI 兼容接口:三语言实战 The OpenAI-compatible API in three languages

所有请求发往 https://api.zbstream.com/v1/chat/completions,使用 Bearer 鉴权。响应结构与 OpenAI 完全一致,读取 choices[0].message.content 即可。

Python

python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["ZBSTREAM_API_KEY"],
    base_url="https://api.zbstream.com/v1",
)

resp = client.chat.completions.create(
    model="deepseek-v4-pro",
    messages=[{"role": "user", "content": "用一句话解释什么是 LLM 网关。"}],
)
print(resp.choices[0].message.content)

Node.js

javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.ZBSTREAM_API_KEY,
  baseURL: "https://api.zbstream.com/v1",
});

const resp = await client.chat.completions.create({
  model: "deepseek-v4-pro",
  messages: [{ role: "user", content: "用一句话解释什么是 LLM 网关。" }],
});
console.log(resp.choices[0].message.content);

Go

go
config := openai.DefaultConfig(os.Getenv("ZBSTREAM_API_KEY"))
config.BaseURL = "https://api.zbstream.com/v1"
client := openai.NewClientWithConfig(config)

resp, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
    Model:    "deepseek-v4-pro",
    Messages: []openai.ChatCompletionMessage{
        {Role: openai.ChatMessageRoleUser, Content: "用一句话解释什么是 LLM 网关。"},
    },
})
if err != nil {
    log.Fatal(err)
}
fmt.Println(resp.Choices[0].Message.Content)

4Anthropic 兼容接口:三语言实战 The Anthropic-compatible API in three languages

基础地址是 https://api.zbstream.com(不带 /v1,SDK 会自动拼接)。注意三个差异:max_tokens 必填、system 是顶层字段、回答在 content 数组里。

Python

python
from anthropic import Anthropic

client = Anthropic(
    api_key=os.environ["ZBSTREAM_API_KEY"],
    base_url="https://api.zbstream.com",
)

msg = client.messages.create(
    model="deepseek-v4-pro",
    max_tokens=1024,
    system="你是一个简洁的技术助手。",
    messages=[{"role": "user", "content": "用一句话解释什么是 LLM 网关。"}],
)
print(msg.content[0].text)

Node.js

javascript
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: process.env.ZBSTREAM_API_KEY,
  baseURL: "https://api.zbstream.com",
});

const msg = await client.messages.create({
  model: "deepseek-v4-pro",
  max_tokens: 1024,
  system: "你是一个简洁的技术助手。",
  messages: [{ role: "user", content: "用一句话解释什么是 LLM 网关。" }],
});
console.log(msg.content[0].text);

Go

go
client := anthropic.NewClient(
    os.Getenv("ZBSTREAM_API_KEY"),
    option.WithBaseURL("https://api.zbstream.com"),
)

msg, err := client.Messages.New(ctx, anthropic.MessageNewParams{
    Model:     anthropic.F("deepseek-v4-pro"),
    MaxTokens: anthropic.F(int64(1024)),
    Messages: anthropic.F([]anthropic.MessageParam{
        anthropic.NewUserMessage(anthropic.NewTextBlock("用一句话解释什么是 LLM 网关。")),
    }),
})
if err != nil {
    log.Fatal(err)
}
fmt.Println(msg.Content[0].Text)

5流式输出:一个参数的区别 Streaming: the one-parameter difference

两种协议都在请求体中传 "stream": true(或 SDK 的 stream=True),区别在事件格式:OpenAI 风格按 choices[].delta 增量推送并以 [DONE] 结束;Anthropic 风格按 message_start / content_block_delta / message_stop 事件推送。

python — OpenAI 流式
stream = client.chat.completions.create(
    model="deepseek-v4-pro",
    messages=[{"role": "user", "content": "请逐步回答"}],
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="", flush=True)
python — Anthropic 流式
with client.messages.stream(
    model="deepseek-v4-pro",
    max_tokens=1024,
    messages=[{"role": "user", "content": "请逐步回答"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

6怎么选 Which one should you choose?

  • 现有代码零改造:已经用 OpenAI SDK 的项目直接改 base_url,一分钟迁移完成。
  • Agent / 工具调用密集型:Anthropic Messages 的工具调用与 content 块结构更适合多轮工具编排,且 Claude 生态的框架(如 Claude Code 类工具)默认讲这套协议。
  • 混用完全没问题:两种协议共用同一个 Key 和积分账户,按各自模型费率计费,控制台的用量统计会把它们合并展示。

7常见坑 Common pitfalls

  • 404:Anthropic 基础地址多写了 /v1,SDK 又拼了一次。
  • 400:Messages 接口漏了必填的 max_tokens
  • 模型不存在:model 名称与 /v1/models 返回值大小写不一致。
  • 流式读取超时:反向代理的 proxy_read_timeout 小于模型生成时长,建议 ≥ 300 秒。