从 OpenAI 切换到 MiniMax,无需重写应用
如果你的服务已经在调用 OpenAI Chat Completions API,把它迁到 YiduoChan 上的 MiniMax 模型只是一次配置变更:换一个 Base URL、一个 API Key、一个模型 ID。本页给出 Python 与 Node.js 中的具体改法,说明哪些部分原样沿用、哪些差异需要处理,以及如何先在一小部分流量上灰度切换。
切换服务商实际涉及哪些改动
YiduoChan 通过 https://yiduochan.com/v1 上的 OpenAI 兼容 API 提供 MiniMax 模型,所以迁移现有集成是改配置,而不是重写。客户端库照常可用,发出去的仍是同样的 messages 数组,返回的仍是同样的 choices[0].message.content 路径,流式输出的循环也照常运行。变化的只有三样:请求发往哪里、用哪个凭证鉴权、请求哪个模型名。
本页假设你在生产环境中已经有一套可用的 OpenAI 兼容集成,想把其中一部分或全部指向 MiniMax。如果你是从空项目起步,更适合从 Python 与 Node.js 的 OpenAI SDK 指南入手;MiniMax 模型总览介绍了模型阵容和可用的接口。
需要改的三项配置
| 配置项 | 迁移前 | 迁移后 |
|---|---|---|
| Base URL | https://api.openai.com/v1 | https://yiduochan.com/v1 |
| API Key | 你现有服务商的 Key | 在 /register 注册后创建的 YiduoChan Key,以 Authorization: Bearer <your key> 的形式发送 |
| 模型 ID | 你当前使用的模型名 | MiniMax-M2.7、MiniMax-M2.7-highspeed 或 MiniMax-M3 |
调用签名中的其他部分都保持原样。你不需要新的 SDK、新的传输层、新的重试策略,也不需要新的响应解析器。大多数代码库本来就从环境变量读取这三个值,所以改动只涉及一个部署配置文件,可能再加一个常量。
Python:迁移前后对比
import os
from openai import OpenAI
# Before
client = OpenAI(
base_url="https://api.openai.com/v1",
api_key=os.environ["OPENAI_API_KEY"],
)
resp = client.chat.completions.create(
model="your-current-model",
messages=[{"role": "user", "content": "Summarise this changelog in three bullets."}],
)
print(resp.choices[0].message.content)
import os
from openai import OpenAI
# After
client = OpenAI(
base_url="https://yiduochan.com/v1",
api_key=os.environ["YIDUOCHAN_API_KEY"],
)
resp = client.chat.completions.create(
model="MiniMax-M2.7",
messages=[{"role": "user", "content": "Summarise this changelog in three bullets."}],
)
print(resp.choices[0].message.content)
Node.js:迁移前后对比
import OpenAI from "openai";
// Before
const client = new OpenAI({
baseURL: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
});
const resp = await client.chat.completions.create({
model: "your-current-model",
messages: [{ role: "user", content: "Summarise this changelog in three bullets." }],
});
console.log(resp.choices[0].message.content);
import OpenAI from "openai";
// After
const client = new OpenAI({
baseURL: "https://yiduochan.com/v1",
apiKey: process.env.YIDUOCHAN_API_KEY,
});
const resp = await client.chat.completions.create({
model: "MiniMax-M2.7",
messages: [{ role: "user", content: "Summarise this changelog in three bullets." }],
});
console.log(resp.choices[0].message.content);
同一份构建,两家服务商都能用
把新值硬编码进去,对个人小脚本来说没问题,但这样上线只能一刀切,回滚也得改代码。更稳妥的做法是把这三项配置都提升为环境变量,让同一个构建产物可以对接任一服务商,在部署时再选定。变量名要取得通用:关键在于让应用不再知道自己在和哪家厂商通信。
# .env.previous
LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=<your existing provider key>
LLM_MODEL=your-current-model
# .env.yiduochan
LLM_BASE_URL=https://yiduochan.com/v1
LLM_API_KEY=<your YiduoChan key>
LLM_MODEL=MiniMax-M2.7
import os
from openai import OpenAI
client = OpenAI(
base_url=os.environ.get("LLM_BASE_URL", "https://yiduochan.com/v1"),
api_key=os.environ["LLM_API_KEY"],
)
MODEL = os.environ.get("LLM_MODEL", "MiniMax-M2.7")
resp = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": "ping"}],
)
import OpenAI from "openai";
export const client = new OpenAI({
baseURL: process.env.LLM_BASE_URL ?? "https://yiduochan.com/v1",
apiKey: process.env.LLM_API_KEY,
});
export const MODEL = process.env.LLM_MODEL ?? "MiniMax-M2.7";
这三个变量要作为一组同时维护。迁移中常见的失误是只在一处改了 Base URL,却留下了旧 Key 或旧模型名,结果不是鉴权失败,就是因模型未知被拒绝;看起来像平台问题,其实是配置只改了一半。
如果你的技术栈是通过框架而不是直接用 SDK 调用,要改的同样只有这三项配置,见 LiteLLM、LangChain 与 Vercel AI SDK 的说明。使用 Anthropic 协议的 Agent 工具读取的是另一组变量:
ANTHROPIC_BASE_URL=https://yiduochan.com
ANTHROPIC_AUTH_TOKEN=<your YiduoChan key>
ANTHROPIC_MODEL=MiniMax-M2.7
ANTHROPIC_DEFAULT_HAIKU_MODEL=MiniMax-M2.7-highspeed
这条路径另有文档,见 Claude Code 配置指南。
原样沿用的部分
正因为下面这些行为保持不变,这次切换才只是机械性的改动,而不涉及架构调整。它们都使用标准的 OpenAI 兼容格式,现有代码路径不需要为新服务商增加条件分支。
对话补全(Chat Completions)
请求与响应的外层结构完全相同:角色、多轮消息数组、系统提示、temperature、max_tokens,以及返回的 choices 数组。你的提示模板、消息构造逻辑和响应解析器都不用改。
流式输出
stream = client.chat.completions.create(
model="MiniMax-M2.7",
messages=[{"role": "user", "content": "Explain the migration in three bullets."}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
工具调用与函数调用
tools = [{
"type": "function",
"function": {
"name": "get_invoice",
"description": "Look up an invoice by id.",
"parameters": {
"type": "object",
"properties": {"invoice_id": {"type": "string"}},
"required": ["invoice_id"],
},
},
}]
resp = client.chat.completions.create(
model="MiniMax-M2.7",
messages=[{"role": "user", "content": "Fetch invoice INV-2031."}],
tools=tools,
)
print(resp.choices[0].message.tool_calls)
JSON 模式
resp = client.chat.completions.create(
model="MiniMax-M2.7",
messages=[
{"role": "system", "content": "Reply with a single JSON object."},
{"role": "user", "content": "Country and capital of France."},
],
response_format={"type": "json_object"},
)
语音合成接口
/v1/audio/speech 沿用相同的参数名:model、input、voice 和 response_format(mp3、wav、flac 或 pcm,默认 mp3)。需要改的是音色标识:请使用 MiniMax 的音色 ID,例如 male-qn-qingse、female-shaonv 或 English_expressive_narrator。服务商特有的额外参数,例如 voice_setting.emotion 和 audio_setting.sample_rate,放在 metadata 对象中传递。
audio = client.audio.speech.create(
model="speech-2.8-turbo",
input="The migration is complete.",
voice="English_expressive_narrator",
response_format="mp3",
)
with open("out.mp3", "wb") as f:
f.write(audio.content)
目前没有公布单次请求的字符上限,所以长文稿请按句子或段落边界切分,再自行拼接音频。详细说明和按字符计费的价格见 speech-2.8 页面。
需要处理的差异
模型 ID 区分大小写
可接受的字符串只有 MiniMax-M2.7、MiniMax-M2.7-highspeed 和 MiniMax-M3。请严格按原样使用这些 ID,并从 /v1/models 复制,不要手敲。如果你的配置在链路中某处把模型名统一转成小写(路由层和缓存键里常有这种习惯),切换前先去掉这一步,否则灰度的每个请求都会失败,而失败原因与模型本身毫无关系。
试用额度只够测试
账号为预付制。新账号注册即送 $0.10 试用额度,刚创建的 Key 可以用它发几次测试请求;但要承接真实流量,账号必须先充值。最低充值 $5,预设档位有 $5、$10、$20、$50、$100、$200 和 $500,也可以自定义金额;额度有效期 12 个月,失败的请求从不计费。请把充值作为迁移的第一步,不要等灰度开始报错后再补。
count_tokens 不可用
Anthropic 兼容接口不提供 count_tokens。如果系统中有任何地方调用它,比如上下文预算检查、请求前的费用预估、截断辅助函数,请改用本地 tokenizer 估算,或者直接使用响应中返回的用量数据。切换前一定要排查一遍:这类调用往往藏在某个工具模块里,而不在你正在重点测试的请求路径上。
切换期间会遇到的报错
| 现象 | 可能原因 | 处理方法 |
|---|---|---|
| 401 未授权 | 环境中仍是旧服务商的 Key、请求头格式有误,或 Key 已被吊销 | 使用有效的 YiduoChan Key 发送 Authorization: Bearer <your key>,并确认部署确实读取到了新的密钥 |
| 余额不足 | 账号没有余额,或余额在灰度过程中耗尽 | 在控制台的钱包页面充值;首次充值同样适用 $5 的最低金额 |
| 模型未知或被拒绝 | 模型 ID 的大小写或拼写不匹配 | 从 /v1/models 复制准确的 ID |
切流量之前先验证
按顺序做两项检查。第一项确认 Key 和 Base URL 正确,并列出你的账号可以调用的准确模型 ID;第二项确认端到端的补全请求可以跑通。
curl -s https://yiduochan.com/v1/models \
-H "Authorization: Bearer $YIDUOCHAN_API_KEY"
curl https://yiduochan.com/v1/chat/completions \
-H "Authorization: Bearer $YIDUOCHAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MiniMax-M2.7",
"messages": [{"role": "user", "content": "Reply with the word: ok"}]
}'
第一条命令返回 401,说明凭证或请求头有误,没必要继续。第一条命令成功、第二条却报余额错误,说明 Key 有效,但账号余额不足。
迁移检查清单
- 在 /register 注册账号,并充值至少 $5。
- 把 Key 以新名称存入密钥管理系统,暂时不要覆盖现有服务商的密钥。
- 如果 Base URL、Key 和模型还不是环境变量,先把它们提升为环境变量。
- 在应用所在的同一网络环境中,运行上面的两条验证命令。
- 在代码库中搜索(grep)把模型名转成小写的逻辑,以及
count_tokens调用。 - 选定起步模型。MiniMax-M2.7 是通用的默认选择;
MiniMax-M2.7-highspeed模型质量相同、延迟更低;MiniMax-M3 用于长上下文任务,上限为 1,048,576 tokens,不可突破。各项取舍见模型对比。 - 在任何线上流量切过去之前,先用现有的评测集跑一遍新模型。
- 先按比例灰度放量,再逐步扩大。
MiniMax-H3 视频生成在本平台暂时不可用,因此目前不在迁移计划之内。
灰度发布
既然选用哪家服务商已经变成三个环境变量,灰度就只是一个路由决策,而不是业务逻辑里的分支。创建两个客户端实例,按请求在两者之间选择即可。
import os, random
from openai import OpenAI
primary = OpenAI(base_url=os.environ["LLM_BASE_URL"], api_key=os.environ["LLM_API_KEY"])
canary = OpenAI(base_url=os.environ["CANARY_BASE_URL"], api_key=os.environ["CANARY_API_KEY"])
CANARY_SHARE = float(os.environ.get("CANARY_PERCENT", "0")) / 100
def pick_client():
if random.random() < CANARY_SHARE:
return canary, os.environ["CANARY_MODEL"]
return primary, os.environ["LLM_MODEL"]
client, model = pick_client()
resp = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "ping"}],
)
| 阶段 | MiniMax 承接的流量 | 观察指标 | 进入下一阶段的条件 |
|---|---|---|---|
| 1 | 仅内部流量 | 鉴权、模型 ID、工具调用解析 | 一个完整部署周期内零配置错误 |
| 2 | 1% | 错误率、延迟分位数、余额消耗 | 连续 24 小时指标与基线无差别 |
| 3 | 10% | 真实提示下的输出质量、工具调用成功率 | 评测分数保持稳定,且没有质量回退的反馈 |
| 4 | 50% | 持续吞吐量、额度消耗与预测的对比 | 花费与预估相符,错误预算未被突破 |
| 5 | 100% | 以上全部 | 旧凭证再保留一个发布周期 |
CANARY_PERCENT 应该从配置系统中设置,而不是打进镜像,这样扩大或回退灰度都不需要重新构建。
价格参考
以下为刊例价,单位为美元 / 每百万 tokens;计费方式为预付、按量付费,无订阅。
| 模型 | 说明 | 输入 | 输出 | 缓存读取 |
|---|---|---|---|---|
MiniMax-M2.7 | 通用默认选择 | $0.30 | $1.20 | $0.06 |
MiniMax-M2.7-highspeed | 模型质量相同,延迟更低 | $0.60 | $2.40 | $0.06 |
MiniMax-M3,提示不超过 512K | 1,048,576 tokens 上下文,硬上限 | $0.30 | $1.20 | $0.06 |
MiniMax-M3,提示超过 512K | 提示在 512K 以上、1M 以内 | $0.60 | $2.40 | $0.12 |
MiniMax-M2.7 系列模型的缓存写入为每百万 tokens $0.375。语音按输入字符计费:speech-2.8-hd 为每百万字符 $100,speech-2.8-turbo 为每百万字符 $60,明细见语音定价页。
目前所有账号都在倍率为 0.95 的分组中,所以实际扣费比上表的刊例价低 5%。一次灰度如果通过 MiniMax-M2.7 发送 10M 输入 tokens 和 2M 输出 tokens,按刊例价为 10 × $0.30 + 2 × $1.20 = $5.40,按当前 5% 的分组折扣实际扣费 $5.13。请把这看作目前生效的分组设置,而不是永久承诺;你自己的用量可以用费用计算器估算。
回滚
服务商相关的信息都没有编译进应用,所以回滚只是一次配置操作。把 CANARY_PERCENT 设为 0,即可立即排空灰度流量;或者把 LLM_BASE_URL、LLM_API_KEY 和 LLM_MODEL 改回原来的值并重新部署。不用改代码,不用开发布分支,也不用迁移数据。在新服务商上以 100% 流量跑满至少一个完整发布周期之前,请让旧凭证保持有效、余额充足:把一个 Key 多留一周几乎没有成本,而在故障处理中才发现它已被删除,代价要大得多。
常见问题
从 OpenAI 切换到 MiniMax 需要改代码吗?
不需要。无论你是通过 OpenAI SDK 调用,还是直接用 HTTP 请求 /v1/chat/completions,只需更换 Base URL、API Key 和模型 ID,请求与响应的格式完全不变。
YiduoChan 上 MiniMax 的 OpenAI 兼容 Base URL 是什么?
是 https://yiduochan.com/v1,鉴权方式是在 Authorization: Bearer 请求头中携带你的 Key。可用接口包括 /v1/chat/completions、/v1/audio/speech 和 /v1/models。
MiniMax 的模型 ID 区分大小写吗?
区分。请严格按原样使用 MiniMax-M2.7、MiniMax-M2.7-highspeed 或 MiniMax-M3;小写形式不是别名,会被拒绝。
测试迁移时有免费额度可用吗?
新账号注册即送 $0.10 试用额度,够发几次测试请求;正式使用需预付充值,最低 $5。请在灰度流量切过来之前完成充值。
切换后流式输出、工具调用和 JSON 模式还能用吗?
能。三者都走标准的 OpenAI 兼容格式,流式输出同样使用 stream=True。唯一值得排查的例外是 Anthropic 兼容接口,因为那里不提供 count_tokens。
灰度效果不对时如何回滚?
把灰度比例设为 0;或者把 Base URL、Key 和模型这三个环境变量改回原服务商的值并重新部署。整个过程不涉及代码改动。