用 OpenAI SDK 调 BUZZ
一个 SDK,一个 base URL,所有支持的模型家族。把官方 OpenAI client 指向 https://buzzai.cc/v1,改一下 model 名,就能调 Claude / Gemini / Grok / GPT。流式、Tool Use、重试策略、可观测性 wrapper 全部不用动。
/v1 暴露 OpenAI 兼容的 chat.completions 端点。网关用 chat.completions 解析你的请求,根据 model 字段分发到对应上游,响应再翻译回 OpenAI 形状。OpenAI 自家模型走原生透传;Claude / Gemini / Grok 由网关在协议之间做桥接。
1. 安装与配置
装官方 client 即可,没有 BUZZ 专用包。
pip install openainpm install openai构造 client 时只填两个字符串:base_url 和 api_key。
from openai import OpenAI
client = OpenAI(
api_key="sk-YOUR_BUZZ_KEY",
base_url="https://buzzai.cc/v1",
)import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.BUZZ_API_KEY,
baseURL: "https://buzzai.cc/v1",
});两个 SDK 都会以 Authorization: Bearer <value> 形式发送 key,BUZZ 直接接受。sk- 前缀可有可无 — 服务端会剥离前缀。
2. 调 Claude
model 填 Claude ID,正常调 chat.completions.create 即可。网关把请求转成 Anthropic Messages 格式调上游,再把响应转回 OpenAI ChatCompletion,你的代码继续按 OpenAI 形状解析。
resp = client.chat.completions.create(
model="claude-haiku-4-5-20251001",
messages=[
{"role": "system", "content": "你是一个严谨的技术写作者。"},
{"role": "user", "content": "用三句话解释 content-addressable storage。"},
],
temperature=0.3,
max_tokens=400,
)
print(resp.choices[0].message.content)
print(resp.usage)const resp = await client.chat.completions.create({
model: "claude-haiku-4-5-20251001",
messages: [
{ role: "system", content: "你是一个严谨的技术写作者。" },
{ role: "user", content: "用三句话解释 content-addressable storage。" },
],
temperature: 0.3,
max_tokens: 400,
});
console.log(resp.choices[0].message.content);curl -sS https://buzzai.cc/v1/chat/completions \
-H "Authorization: Bearer $BUZZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-4-5-20251001",
"messages": [
{"role": "system", "content": "你是一个严谨的技术写作者。"},
{"role": "user", "content": "用三句话解释 content-addressable storage。"}
],
"max_tokens": 400
}'常用 Claude 模型 ID(实时列表见 GET /v1/models):
claude-opus-4-7·claude-opus-4-6·claude-opus-4-5-20251101claude-sonnet-4-6·claude-sonnet-4-5-20250929claude-haiku-4-5-20251001·claude-haiku-4-5-20251001
3. 调 Gemini、Grok、GPT
切家族就是改 model 名。同一个 client、同一段调用、同一套重试 wrapper。
# 同一个 client,不同模型家族
gemini = client.chat.completions.create(
model="gemini-2.5-pro",
messages=[{"role": "user", "content": "总结这份会议记录..."}],
)
grok = client.chat.completions.create(
model="grok-4",
messages=[{"role": "user", "content": "本周市场发生了什么?"}],
)
gpt = client.chat.completions.create(
model="gpt-5",
messages=[{"role": "user", "content": "给出一份迁移方案大纲。"}],
)
支持的完整模型 ID 列表见 buzzai.cc/models,实时按 token 价格见 buzzai.cc/api/pricing。
4. 流式
传 stream=true 后迭代响应。无论上游是 Anthropic 类型事件还是 OpenAI 类型事件,网关统一以 OpenAI chat.completion.chunk 形状对外发出。
stream = client.chat.completions.create(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": "写一首关于冷存储的俳句。"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)const stream = await client.chat.completions.create({
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "写一首关于冷存储的俳句。" }],
stream: true,
});
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content;
if (delta) process.stdout.write(delta);
}想在流结束时拿到 token 用量,加 stream_options:
stream = client.chat.completions.create(
model="claude-haiku-4-5-20251001",
messages=[{"role": "user", "content": "ping"}],
stream=True,
stream_options={"include_usage": True},
)
最后一个 chunk 会带非空 usage 对象。当上游是 Claude 时,BUZZ 会在 usage 上额外标记 usage.usage_source = "anthropic" — 在可观测平台里做跨家族成本归因很方便。
5. Tool Use / Function Calling
按 OpenAI 标准格式定义 tools,网关在出口侧把它们映射成 Anthropic tool_use 块(或 Gemini functionDeclarations),响应进入时再把上游的工具选择映射回 tool_calls。原有 OpenAI tool-calling 调用循环不需要改。
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取某城市的当前天气。",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"units": {"type": "string", "enum": ["c", "f"]},
},
"required": ["city"],
},
},
}]
resp = client.chat.completions.create(
model="claude-opus-4-7",
messages=[{"role": "user", "content": "东京现在天气怎么样?"}],
tools=tools,
tool_choice="auto",
)
call = resp.choices[0].message.tool_calls[0]
print(call.function.name, call.function.arguments)
# 后续把 assistant 消息追加进对话,再加一条
# {"role": "tool", "tool_call_id": call.id, "content": "..."} 然后再调一次。
6. Claude 路径下被静默丢弃的字段
网关分发到 Claude 上游时,会用你的 chat.completions 请求重建 Messages-API 请求体。在 Anthropic 侧没有对应概念的字段不会出现在上游调用里。它们不会触发 400 — 它们直接消失。下表是已确认的丢弃清单,按这个心智模型设计就行。
| chat.completions 入参 | Claude 路径行为 |
|---|---|
n(> 1) | 丢弃。Claude 上游只返回单 choice,n > 1 不可用。 |
presence_penalty | 丢弃。Anthropic 没有对应参数。 |
frequency_penalty | 丢弃。Anthropic 没有对应参数。 |
logit_bias | 丢弃。Anthropic 没有对应参数。 |
logprobs / top_logprobs | 丢弃。Claude 响应永远不返回 logprobs。 |
seed | 丢弃。Anthropic 没有确定性采样旋钮。 |
response_format | 丢弃。JSON 模式 / JSON Schema 约束在 Claude 路径不生效;改用 prompt 引导或 tool-calling。 |
function_call / functions | 丢弃(旧 API 形式)。改用 tools + tool_choice — 这条路径已接通。 |
prediction / modalities / audio | 丢弃。Anthropic Messages 不暴露这些。 |
verbosity | 丢弃。仅 GPT 支持。 |
user / safety_identifier / prompt_cache_key / metadata / store | Claude 路径丢弃。其中部分字段在 OpenAI 路径上也是通道级开关 — 见下方 callout。 |
service_tier | 默认丢弃。可由通道侧 allow_service_tier 开启。 |
带 opus-4-7 或 -thinking 后缀的模型 + temperature / top_p / top_k | 会被强制清空。Extended Thinking 模式下采样参数被刻意忽略,即使你显式传也无效。 |
反过来,网关也帮你把若干 OpenAI 入参翻译到 Claude 概念:
stop(string 或 array)→ Anthropicstop_sequencestools+tool_choice→ Anthropictools+tool_choice(含 parallel-tool-calls 映射)web_search_options→web_search_20250305工具,search_context_sizelow/medium/high →maxUses1/5/10reasoning_effortlow/medium/high →thinking.budget_tokens1280/2048/4096- image / audio / file / video 内容片段会拉取并转 base64,作为 Anthropic content block 发出
service_tier、safety_identifier、stream_options.include_obfuscation,以及 Claude 侧的 inference_geo / speed。如果业务真的需要这几个端到端透传,联系支持开通对应开关。
7. 什么场景该改用 Anthropic SDK
对于在 chat.completions 里没有标准位置的 Claude 原生特性,改用 Anthropic SDK 调同一个网关 — 同 key、同网关、不同协议。
- Extended Thinking 块。Claude 可以返回结构化的
thinking块。OpenAI 适配会把它折叠到delta.reasoning_content;如果你需要原始的 typed block(含 signature),用 Anthropic SDK。 - Prompt Cache。
cache_control是绑定到具体内容块的 Anthropic 概念 — OpenAI 请求体没有承载它的字段。需要 Prompt Cache 就用 Anthropic SDK,详见 Prompt Caching 概念。 - Provider-typed 流事件。需要原始
content_block_start/message_delta事件粒度(比如要把 thinking 块单独渲染),用 Anthropic SDK;OpenAI 适配把它们合并成delta。
from anthropic import Anthropic
ant = Anthropic(
api_key="sk-YOUR_BUZZ_KEY",
base_url="https://buzzai.cc",
)
msg = ant.messages.create(
model="claude-opus-4-7",
max_tokens=1024,
messages=[{"role": "user", "content": "帮我规划一个模块重构..."}],
extra_body={"thinking": {"type": "enabled", "budget_tokens": 8000}},
)
8. 框架集成
任何 OpenAI client 包装、且暴露 baseURL 配置的框架都直接可用。三种典型接线:
LangChain(Python)
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="claude-haiku-4-5-20251001",
api_key="sk-YOUR_BUZZ_KEY",
base_url="https://buzzai.cc/v1",
temperature=0.2,
)
print(llm.invoke("一句话总结 BUZZ gateway。").content)
LangGraph
LangGraph 的 node 通常接收一个 chat model 实例。按上面的方式构造 ChatOpenAI,然后传进 graph。Graph 层不需要任何改动 — 路由决策完全靠 model ID 传递。
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="claude-sonnet-4-6",
api_key="sk-YOUR_BUZZ_KEY",
base_url="https://buzzai.cc/v1",
)
agent = create_react_agent(model, tools=[...])
result = agent.invoke({"messages": [("user", "这次发布做了什么?")]})
Vercel AI SDK
import { createOpenAI } from "@ai-sdk/openai";
import { generateText } from "ai";
const openai = createOpenAI({
apiKey: process.env.BUZZ_API_KEY,
baseURL: "https://buzzai.cc/v1",
});
const { text } = await generateText({
model: openai("claude-haiku-4-5-20251001"),
prompt: "为缓存改进写一条简短的发布说明。",
});
streamText 的流式、tools 选项的工具调用、Zod schema 的结构化输出都继续可用 — 网关保持的是 @ai-sdk/openai 期望的线协议形状。
9. 可观测性与重试
因为出入两个方向都是 OpenAI 原生形状,所有包装 OpenAI client 的工具都能不修改地继续用:OpenTelemetry GenAI 语义约定、Langfuse / Helicone / Phoenix 这类追踪处理器、429 重试装饰器、请求/响应日志器,都按原配置工作。BUZZ 侧值得在监控里多采一个字段:usage.usage_source,值为 "anthropic" 时表示该响应来自 Claude 上游 — 跨家族成本归因很方便。
10. 错误码
| HTTP | error.type | 典型场景 |
|---|---|---|
| 400 | invalid_request_error / buzz_error | JSON 格式错误或缺必填字段 |
| 401 | buzz_error | API key 缺失或非法 |
| 403 | permission_error | Key 权限不足、IP 不在允许列表 |
| 429 | rate_limit_error | 命中限流,遵守 retry-after |
| 500 | api_error | 内部错误,带退避重试 |
| 503 | buzz_error / model_not_found | 该 model 在你的 group 下没有可用 channel。换一个别名或调 GET /v1/models 看实时列表。 |
BUZZ 侧错误返回 {"error": {"type": "buzz_error", "message": "... (request id: ...)"}}。上游透传错误保留上游的包络形状(根据路由模型,可能是 Anthropic 风格或 OpenAI 风格)。
相关链接
POST /v1/chat/completions— 完整参数参考POST /v1/messages— 同一 key 上的 Anthropic 原生路径- Claude Code 配置指南 — 同一 key 接 CLI
- 用 OpenAI SDK 调 Claude 深度解析