要点
- 该标签覆盖 URL 路径、JSON 请求和响应结构、Bearer 认证和 SSE 流式输出。
- 它未说明哪个模型回答、其行为方式或价格。
- 切换通常意味着更改两个值:基础 URL 和 API 密钥。
- 在依赖提供商之前,测试流式输出、工具、JSON 模式和错误代码。
简短回答
当提供商称其 API 为 OpenAI 兼容时,意味着它接受 OpenAI 客户端库发送的相同 HTTP 请求,并以相同的结构返回响应。你保留代码,更改基础 URL 和密钥,调用将发往不同的服务器。
这就是全部承诺。它是关于接口的声明,就像说两个充电器使用相同的插头。它未告诉你电缆另一端的实际情况。模型、安全规则、价格和限制均由提供商决定,且差异很大。
该标签实际覆盖的内容
实际上,OpenAI 兼容性是一系列具体的事项。如果提供商支持所有这些,大多数客户端代码可以无需更改即可运行。
- 路径。 聊天请求发送至
POST /v1/chat/completions,模型列表来自GET /v1/models。 - 认证。 密钥通过
Authorization: Bearer头传输。 - 请求体。 包含
model字符串、带有role和content的对象数组messages,以及可选采样字段如temperature、top_p、stop和seed。 - 响应体。 包含助手消息的
choices数组、finish_reason,以及包含 token 计数的usage对象。 - 流式输出。 使用
stream: true时,服务器发送服务器发送事件(SSE),每个事件携带一个小的 JSON 增量,以最终标记结束。 - 可选功能。 函数调用、JSON 模式及类似字段,由提供商选择支持。
由于许多工具针对此格式编写,它成为了共同目标。编辑器、代理框架、角色扮演前端和脚本均允许输入自定义 Base URL,这正是它们所需的全部。
为何一种格式成为共同目标
聊天补全格式因其简单且出现较早而传播。支持该格式的工具作者可以触及许多后端,支持该格式的后端作者可以触及许多工具。这对双方都是好交易,因此该格式得以保留,即使在与设计它的公司无关的服务中也是如此。
对于你作为开发者而言,这具有实际意义。你的代码无需为每个提供商进行不同的集成。你可以在一个下午内在不同接口间移动原型,在同一提示词下比较两个模型,或在第一个提供商较慢时将第二个提供商作为后备。改变主意的成本很低,这使得在不承诺的情况下更容易尝试新服务。
另一方面,共享的表面掩盖了真正的差异。由于切换非常容易,人们容易假设 URL 背后的所有内容都是等效的。事实并非如此,以下部分展示了差距通常出现在哪里。
它未告知你的内容
这里人们会感到惊讶。该标签省略了决定 API 是否对你的工作有用的所有内容。
其背后的模型
兼容的接口可以服务任何模型。有些服务开放权重模型,有些路由到多个供应商,有些则封装专有模型。兼容性并不意味着该服务由 OpenAI 运营,也不意味着模型的行为像它们的一样。你在 model 中传入的模型名称只是提供商定义的一个字符串。
拒绝行为
内容规则属于模型和提供商,而非协议。两个兼容的 API 可能对相同的提示词给出相反的回答。如果你的用例是小说、角色扮演或其他合法的成人内容,请在连接之前检查提供商关于拒绝的说明。
功能深度
一些提供商仅实现聊天。其他添加工具、JSON 模式、对数概率或额外接口。如果客户端发送服务器忽略的字段,不一定会明显失败,因此可能出现静默不匹配。
限制、定价和错误
速率限制、上下文长度、最大主体大小和每 token 价格均为提供商选择。错误体的细节也各不相同,即使 HTTP 状态码匹配,因此重试逻辑应基于状态码和头,而非消息文本。
快速兼容性测试
你可以通过三个请求在几分钟内验证提供商。替换为你自己的密钥。此示例使用本站的 Base URL。
curl https://api.kimicode.top/v1/models \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kimicode.top/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [{"role": "user", "content": "Reply with the word ready."}]
}'
第一次调用确认密钥并列出模型 ID。第二次检查聊天结构。然后测试应用程序依赖的部分:添加 "stream": true 并观察增量块,如果使用函数调用则传递 tools 数组,如果需要可解析输出则设置 response_format 为 {"type":"json_object"}。
还要故意触发错误,例如使用错误的密钥。你希望看到清晰的 HTTP 状态和客户端可处理的 JSON 错误体。
Node 中的相同调用
JavaScript SDK 采用相同的两个值。这是一个流式调用,这是大多数聊天接口使用的结构。
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.kimicode.top/v1",
apiKey: process.env.API_KEY,
});
const stream = await client.chat.completions.create({
model: "uncensored",
stream: true,
messages: [{ role: "user", content: "Name three uses of SSE." }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
如果此代码逐字打印文本,则流式路径端到端工作。相同的循环适用于任何兼容的提供商,这正是该格式的全部意义所在。
代码中的切换方式
使用官方 Python SDK,更改涉及两个构造函数参数。程序的其余部分保持不变。
from openai import OpenAI
client = OpenAI(
base_url="https://api.kimicode.top/v1",
api_key="YOUR_API_KEY",
)
resp = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Summarize SSE in one sentence."}],
)
print(resp.choices[0].message.content)
Node SDK 采用相同的思路,使用 baseURL 和 apiKey 选项。许多工具从环境变量读取 OPENAI_BASE_URL 和 OPENAI_API_KEY,因此有时无需修改代码即可切换。
记得也要更改模型字符串。请求指定新服务器未托管的模型将会失败,这是最常见的第一个错误。
本站 API 的定位
此服务是一个遵循 OpenAI 格式的托管纯文本 API。它运行一个 开放权重模型,由独立提供商运营,并针对无内容拒绝的合法成人用途进行优化。它不是任何模型供应商的官方 API,也不在供应商之间路由。模型 ID 为 uncensored。
它支持通过 SSE 进行流式输出,并在结束时报告使用情况,支持函数调用、JSON 模式,并传递 temperature、top_p、stop、seed 和惩罚。上下文窗口为 100,000 tokens,包含提示词和补全。它不生成图像或音频,也不提供嵌入或微调。一条规则是固定的:禁止涉及未成年人的性内容。
计费为预付且按量计费:输入 token 每 1M 个 $0.15,输出 token 每 1M 个 $0.50,无订阅。你可以在 定价页面 查看数字,文档 将引导你完成第一次请求。如果你想免费试用,新账户可以在 API 密钥页面 一键领取 $0.50 免费试用额度。
常见的兼容性问题
- 基础 URL 错误。 URL 应结束于
/v1。客户端会自行追加/chat/completions,因此若基础 URL 中已包含该路径,将导致 404 错误。 - 不支持的参数。如果库发送了服务器未知的字段,请检查该字段是被拒绝还是被静默丢弃,然后将其移除。
- 流式输出与并发。流式请求会占用一个并发槽位,直到流结束。如果你的应用打开了多个流,即使每分钟请求数较低,也可能触发 429 错误,错误代码为
concurrency。 - 429 重试。将 429 视为等待信号。如果存在
Retry-After头,请遵守该头部的指示。 - Token 计数。不要假设其他提供商的分词器与此匹配。请查看响应中的
usage对象,以获取你计费所用的数字。
一旦你知道要查找这些内容,修复它们都不难,大多数问题归结为仔细阅读第一条错误消息。
