把 OpenAI SDK 的示例改成豆包模型时,第一条请求经常直接 404,或者返回 gateway_error。这个豆包 api 调用教程不聊账号开通,只做一件事:用 Python 和 OpenAI SDK 把第一个对话请求跑通。读完你会有一套能复制运行的脚本,以及三条排错路径。
场景与前置条件
这篇教程解决的是:你已经有一个可用 Key,也想通过 OpenAI 兼容端点调用豆包模型,但把手上的 DeepSeek 或 GPT 示例改完 model 后仍然失败。失败点大多不是模型不会说话,而是 base_url 没改对,或者模型调用名靠猜。下面的代码以 doubao-seed-2.0-pro 为例,你可以替换成 doubao-seed-2.0-mini 或 doubao-seed-2.0-lite,但不要自己拼接版本号。
运行环境要求是 Python 3.9 以上,并安装 openai 1.x。用 0.x SDK 的人会发现连 OpenAI() 都构造不出来,直接抛 TypeError,因为你传了它不认识的 base_url 参数。本教程不涉及账号开通和模型权限申请;如果 Key 没有豆包模型的调用权限,你会在排错一节看到对应的 401 或 403 处理方式。
环境准备
先安装 OpenAI SDK,然后把 Key 放进环境变量。不要硬编码到源码里,原因有两个:一是临时脚本很容易被提交到 git,Key 会跟着泄漏;二是排错 401 时,硬编码值让你很难判断到底是 Key 失效,还是环境没刷新。
bash
python -m pip install -U openai
安装完成后,把密钥创建页保存好的 sk_live_... 值设置成环境变量。变量名不要自己起,就用最下方完整脚本里 os.environ[...] 读取的那个名字。Linux/macOS 终端用 export,Windows 的 cmd 用 set,PowerShell 用 $env:。设置完在同一个终端会话里运行脚本,不要换新窗口。
另一个准备动作是确认模型调用名。模型广场里,同一个模型可能既有展示名也有调用名,代码里只能填调用名。假设展示名是"豆包 Seed 2.0 Pro",实际送入 model 的参数可能是 doubao-seed-2.0-pro。把展示名直接填进去,首条请求就会告诉你模型不存在。
最小可跑示例
下面是完整脚本。把文件保存为 main.py,不要漏掉 import os 和 from openai import OpenAI。脚本没有读取 .env 文件,因为那又需要多一个依赖;你只要保证环境变量已经导出即可。
python
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["SILVAMUX_API_KEY"],
base_url="https://www.silvamux.com/api/v1",
)
response = client.chat.completions.create(
model="doubao-seed-2.0-pro",
messages=[
{"role": "system", "content": "你是一个简洁的中文助手。"},
{"role": "user", "content": "用一句话解释豆包 API 的作用"},
],
temperature=0.7,
max_tokens=512,
)
print(response.choices[0].message.content)
print(response.model)
print(response.usage)
几个参数里最容易填错的是 base_url。它只写到 /api/v1,SDK 会在这个地址后面自己拼上 /chat/completions。如果你把路径补成 /chat/completions,最终会变成重复路径;如果你把域名写成另一个常见地址,连接阶段就会失败。api_key 从环境变量读取,不是直接把字符串粘进去。model 必须来自详情页的调用名,doubao-seed-2.0-pro 是一个可用的稳定调用名;doubao-seed-2.0、doubao-2.0-pro 这类名称不要猜。temperature 控制随机性,0.7 适合一般对话,调成 0 会稳定很多。max_tokens 限制最大输出长度,设太小回复会被截断,但不会报错,只会让你以为模型没说完。
逐步扩展
最小示例是一次性请求。实际接到业务里,大概率要改两个地方:流式输出和多轮上下文。先看流式。改成流式后,服务端不再一次性返回完整 JSON,而是通过 SSE 一段段推。客户端判断结束不要只盯住 data: [DONE],因为最后一次可能带 usage 但 choices 为空。迭代器自然结束时是最可靠的分界。
python
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["SILVAMUX_API_KEY"],
base_url="https://www.silvamux.com/api/v1",
)
stream = client.chat.completions.create(
model="doubao-seed-2.0-pro",
messages=[
{"role": "user", "content": "用三句话介绍豆包模型"}
],
stream=True,
)
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta.content or ""
print(delta, end="", flush=True)
print()
和普通请求相比,只多了 stream=True。下面的循环先判断 chunk.choices 是否为空,避免在 usage chunk 上取下标越界。flush=True 让内容即时刷新,否则有些终端会攒到程序结束才成块输出。不要在这里改成手动解析 SSE 字符串,SDK 已经替你处理了 chunk 边界。
第二个扩展是多轮上下文。把 messages 从固定列表改成变量,每次收到助手回复后把它 append 回列表。漏掉这一行,第二轮提问时模型就看不到上一轮的答复,回答会突然失忆。改动很小,但用法和一次性请求差别很大。
排错
下面是这个豆包 api 调用教程在实测中最容易撞上的三种错误。看报错先看 HTTP 状态码,再看 error 对象里的 type 是否为 gateway_error。服务端返 4xx 时不会扣费,5xx 可以重试,但 4xx 重试没意义。
openai.AuthenticationError: Error code: 401 - {'error': {'message': 'Invalid API key', 'type': 'gateway_error', 'code': 'AUTH_FAILED'}}
直接原因:Key 没导出,或者粘贴时少了 sk_live_ 前缀,也或者旧终端读到了空白环境变量。修法:在当前终端确认环境变量输出是完整 Key;再把脚本里的 api_key 改为从环境变量读取,不要硬编码新的 Key 值。401 不要重试。
openai.NotFoundError: Error code: 404 - {'error': {'message': 'model not found', 'type': 'gateway_error', 'code': 'MODEL_NOT_FOUND'}}
直接原因:model 参数填了展示名或者自己拼的调用名。修法:到模型详情页复制调用名,优先用稳定 alias。示例用 doubao-seed-2.0-pro,不要想当然拼成 doubao-seed-2.0。404 属于参数错误,必须改参数,不要重试。
openai.APIConnectionError: Connection error.
直接原因:Base URL 写错。常见错误是把域名换成某个 api 开头的地址,或者少了 /api/v1 这段。修法:把 base_url 恢复成最小示例里的值,结尾只到 /api/v1,不要在末尾加 /chat/completions。确认没有挂系统代理拦截本地请求。顺手看一眼 X-Request-Id header 是否返回,排查时可以把它贴给服务端。
常见问题
问:豆包 api 能不能用 requests 直接调,不装 openai SDK?
答:可以。端点与 OpenAI 兼容,你按 /chat/completions 路径手动 POST,请求头里带 Authorization: Bearer <key> 和 Content-Type: application/json。只是你要自己处理流式 SSE、超时和重试。这篇教程用 SDK,是为了少写这些胶水代码。
问:为什么请求地址只写到 /api/v1,不写完整路径?
答:OpenAI SDK 的 chat.completions.create 会在 base_url 后拼接 /chat/completions。如果你在 base_url 里再写一次 /chat/completions,最终变成 /api/v1/chat/completions/chat/completions 这类错误路径,404 就来了。保留 /api/v1 结尾即可。
问:流式输出时最后一段总是打印不出来怎么办?
答:多数是 flush 或缓冲区问题。终端输出用 print(..., flush=True)。如果循环里还依赖 data: [DONE],最后一段也可能被跳过,因为 usage chunk 可能在它之后到达;改成迭代器自然结束判断最稳。
以上示例在千木SilvaMux的 OpenAI 兼容端点上验证,运行环境为 Python 3.10 + openai 1.x,模型调用名为 doubao-seed-2.0-pro。模型调用名和最新可用列表以 开发者文档 为准。
