数据自动同步
文档里的分组、模型和价格从哪来、什么时候刷新、出问题怎么办。
为什么要自动化
FluxToken 有 17 个分组 / 41 个模型 / 105 条模型记录,且分组倍率从 0.06 到 2 跨了 30 多倍。 这种规模的数据靠人手维护必然出错——漏掉一个模型、写错一个倍率, 用户就会拿着文档上的数字去对照账单,然后来问为什么对不上。
更糟的是静默失真:线上改了价,文档还写着旧数字,没人发现,直到用户投诉。 所以本站的设计是:价格和分组数据不落人手,全部构建时抓取。
数据来源
| 接口 | 提供什么 | 地址 |
|---|---|---|
| 模型广场 | 分组列表、基准价、分组说明、模型清单 | https://cn.fluxtoken.ai/api/v1/model-plaza |
| 价格接口 | 实付价(已乘分组倍率) | https://status.fluxtoken.ai/pricing/provider-pricing.json |
| 公开设置 | 站点版本、功能开关 | https://cn.fluxtoken.ai/api/v1/settings/public |
三者都是免认证的公开接口。
关键换算:基准价 × 倍率 = 实付价
这是整个数据管线最核心的一步,也是文档写作最容易搞错的地方:
- 模型广场返回的
input_price是基准价,不含分组倍率 - 价格接口返回的
input_price是实付价,已经乘过倍率 - 广场的数字以「每 token」为单位(极小的小数),需要 ×1,000,000 才是「每 1M tokens」的可读值
- 价格接口已经是「每 1M tokens」的最终值
build-facts.mjs 里的 buildGroup() 做这件事:
// 实付价以价格接口为准;缺失时用「基准价 × 倍率」兜底
const paid = providerModels.find(
(x) => x.model_name === m.name && x.group_name === group.name,
)
paidInput: paid ? paid.input_price : Number((baseIn * rate).toFixed(4)),已验证的例子:claude-opus-4-6 基准输入价 $5/1M,在三个 Claude 分组的实付价分别是:
| 分组 | 倍率 | 实付输入价 |
|---|---|---|
【Claude】Max · 惠享 | ×0.5 | $2.5 |
【Claude】Max · 稳享(主) | ×1 | $5 |
【Claude】Max · 顶享 | ×2 | $10 |
写文档时如果要举例说明倍率,用这个例子;其余价格一律挂组件。
⚠️ 公式有例外:基准价本身会随分组漂移
「实付 = 基准 × 倍率」是理解模型,不是计费规则本身。实测数据里存在反例:
| 模型 | 分组 | 倍率 | 基准输入价 | 实付输入价 |
|---|---|---|---|---|
claude-opus-5-5 | 【Claude】Max · 惠享 | ×0.5 | $5 | $2.5 |
claude-opus-5-5 | 【Claude】Max · 稳享(主) | ×1 | $4 | $4 |
claude-opus-5-5 | 【Claude】Max · 顶享 | ×2 | $4 | $8 |
同一个模型,基准价在惠享组是 $5、在稳享/顶享组是 $4。另外 claude-fable-5 与 claude-fable-5-1 的缓存读价也不是整齐的倍数(fable-5 三组为 0.5/1/2, fable-5-1 稳享 0.25 / 顶享 0.5)。
这对数据管线的意义:paidInput 必须始终优先取价格接口的值, baseIn * rate 只能作为该接口缺数据时的兜底(代码里就是这么写的)。 反过来用公式反推实付价会算错。
这对文档写作的意义:正文不要把这条公式说成计费规则,要标注它只用于理解倍率。 引导读者算钱一律去模型价格表,那张表取自计费接口,不是推算的。
想自查这个例外是否还存在:
cd fluxtoken-docsnode scripts/check-drift.mjs该脚本列出所有「同一模型在不同分组基准价不一致」的模型。见 scripts/check-drift.mjs。
输出
构建时生成两份内容完全相同的文件:
| 路径 | 用途 |
|---|---|
docs/.vitepress/data/groups.json | 供 Vue 组件 import,构建期静态打包进页面 |
docs/public/data/groups.json | 对外公开,部署后可通过 https://docs.fluxtoken.ai/data/groups.json 取用 |
结构:
{
"generatedAt": "2026-10-08T...",
"snapshotDate": "2026-10-08",
"siteVersion": "0.2.11",
"priceUnit": "USD per 1M tokens",
"upstreamDeclaredCurrency": "CNY",
"endpoints": {
"accelerate": "https://cn.fluxtoken.ai",
"global": "https://api.fluxtoken.ai"
},
"stats": { "groupCount": 17, "modelRowCount": 105, "uniqueModelCount": 41 },
"groups": [
{
"id": 7,
"name": "【Codex】反代 · 福利",
"rate": 0.06,
"platform": "openai",
"platformLabel": "OpenAI",
"description": "反代池 · 纯福利,不稳定时切换其他分组",
"priceFrom": 0.12,
"modelCount": 8,
"models": [
{
"name": "gpt-5.5",
"billing": "token",
"baseInput": 5, "baseOutput": 30,
"paidInput": 0.3, "paidOutput": 1.8, "paidCacheRead": null,
"perRequest": null,
"tiers": []
}
]
}
]
}容错设计
build-facts.mjs 不会因为线上接口抖动而让构建失败:
抓取成功 → 写入新数据
抓取失败 → 若已有 groups.json,沿用旧快照并打 warning,构建继续
若没有旧快照,报错退出这样上游接口临时不可用不会卡住文档发布。但代价是数据可能过期, 所以每页页尾的 <Provenance /> 会显示 snapshotDate——看到旧日期就知道该重新构建了。
已知问题:上游 currency 字段
价格接口返回的顶层字段:
{ "data": { "currency": "CNY", "price_unit": "per_1m_tokens" } }但这个 currency 字段是错的——同样的数值在模型广场那边是以美元为基准的, 且平台充值定价、控制台显示都以美元额度为准。这不是文档的判断,是两边数值对照后的结论: claude-opus-4-6 在稳享分组(×1)的 input_price 是 5, 而该模型官方定价就是输入 $5/1M——数值对上的是美元,不是人民币。
处理方式:
- 文档一律按 USD 表述
build-facts.mjs保留upstreamDeclaredCurrency字段仅供追溯,不作为展示依据- 构建时若该字段不是
USD,会打一条 warning 提醒
建议:修正上游价格接口的 currency 字段为 USD。修正后本管线无需改动, 只是 warning 会消失。
刷新时机
数据在每次 npm run build 时刷新。此外:
- 平台新增/下架分组、调整倍率 → 重新构建即可,文档自动跟上
- 上游接口格式变更 → 需改
build-facts.mjs - 条款文本更新 → 走
gen-legal.mjs,见文档站维护
可以只刷新数据不构建站点,用来快速查看线上有什么变化:
cd fluxtoken-docsnode scripts/build-facts.mjsgit diff --stat docs/.vitepress/data/groups.json _facts/fact-sheet.md排查
「构建时提示沿用旧快照」
线上接口拉取失败了。检查:
curl -sI https://cn.fluxtoken.ai/api/v1/model-plaza是否返回 200- 本机网络/代理是否正常
- 是否触发了上游限流(等待后重试)
数据没更新不影响构建成功,但页面上的快照日期会是旧的。
「数据看着不对,某个分组的模型少了」
对比三个来源:模型广场页面、/api/v1/model-plaza 接口、价格接口。 如果广场页面和接口一致但价格接口不一致,说明是价格接口那边的问题 (它由定时任务每约 2 分钟重新生成一轮,可能有延迟)。
以模型广场为准判断「这个分组有哪些模型」,以价格接口为准判断「实付多少钱」。
「分组名里有个奇怪的空格」
不是 bug,是原文如此。例如 【Grok】Heavy· 福利 里 Heavy 与 · 之间确实有一个空格, 【Codex】反代 · 福利 里 · 两侧都有空格。逐字照抄,不要「顺手修正」。