同一套文档处理业务,每天 5000 次请求,全部走 claude-opus-4-5-thinking 按次跑,一个月 ¥18000。把 70% 的请求降到 gemini-2.5-pro、25% 用 deepseek-v4-flash-thinking、只留 5% 升档,再加一层 35% 命中的缓存,账单落到 ¥3920。单价没变,代码只多了一张缓存表和一段分档函数。下面 7 个杠杆,每个都给能手算复现的数字。中文 1 个汉字按 1.2 个 token 折算,1 万 token 约合 8300 字;换别的比例,结论方向不变、临界点会挪。单价以各家模型官方页面的标价为准,本文仅作换算参考。
| 优化动作 | 动作前 | 动作后 | 月度差额 |
|---|---|---|---|
| 模型分档 70% / 25% / 5% | ¥18000 | ¥6030 | 省 ¥11970 |
| 结果缓存,命中率 35% | ¥6030 | ¥3920 | 省 ¥2110 |
| 上下文压缩与输出约束 | ¥10800 | ¥6525 | 省 ¥4275 |
加权均价 ¥0.0402 = 0.7 × 0.031 + 0.25 × 0.05 + 0.05 × 0.12。缓存那行是 0.0402 × 65%:35% 的请求被拦住。第三行只在按量口径下成立。
按量账单只有一项:输入 token 数 × 输入单价 + 输出 token 数 × 输出单价。主流旗舰参考价输入约 ¥3/百万 token、输出约 ¥15/百万 token,输出是输入的 5 倍,这是后面所有判断的起点。
输入 2 万 token、输出 800 token 的一次请求:20000 ÷ 100 万 × 3 + 800 ÷ 100 万 × 15 = 0.06 + 0.012 = ¥0.072。
用 gemini-2.5-pro 的 ¥0.031 去追平官方按量:输出 800 token 花掉 800 ÷ 100 万 × 15 = ¥0.012,输入只能吃掉剩下 0.031 - 0.012 = ¥0.019,也就是 0.019 ÷ 3 × 100 万 ≈ 6333 token。
输入超过约 6300 token(约 5200 字)时按次更省;几百 token 的短问句,按量更省。
| 负载形态 | 单次输入 | 单次输出 | 按量成本 | 按次成本 | 谁更省 |
|---|---|---|---|---|---|
| 短问句分类 | 500 token | 200 token | ¥0.0045 | ¥0.031 | 按量,便宜 6.9 倍 |
| 带上下文问答 | 6000 token | 800 token | ¥0.03 | ¥0.031 | 基本打平 |
| 长文档分析 | 10 万 token | 1000 token | ¥0.315 | ¥0.031 | 按次,便宜 10 倍 |
按次计费买的是请求次数,不是字数,所以长上下文任务里它是权重最高的杠杆。
| 档位 | 代表模型 | 元/次 | 该派什么活 |
|---|---|---|---|
| 走量档 | gemini-2.5-pro | 0.031 | 分类、抽取、改写、摘要 |
| 日常档 | deepseek-v3.2-thinking、deepseek-v4-flash-thinking、grok-4.1 | 0.05 | 需推理的问答、单文件改代码 |
| 主力档 | kimi-k2.5、claude-sonnet-4-5-thinking、gemini-3.1-pro-preview | 0.09 | 多轮工具调用、长链路 Agent |
| 攻坚档 | claude-opus-4-5-thinking | 0.12 | 复杂调试、跨文件重构 |
| 压轴档 | gpt-5.5、claude-opus-4-6-thinking、gpt-5.3-pro | 0.2 ~ 0.3 | 错一次代价高的关键任务 |
| 出图档 | gpt-image-2-pro、NanoBanana-Pro | 0.25 / 0.27 | 生图,按张计费 |
另外几档:deepseek-r1-thinking 0.049,gemini-3-pro-preview 0.05,grok-4.5、grok-4.6、kimi-k2.6、deepseek-v4-pro-thinking 0.09,claude-sonnet-4-6-thinking、gpt-5.5-pro-thinking 0.2,gpt-6-astra 按量输入 ¥3/百万 token、输出 ¥15/百万 token。单价以各家模型官方页面的标价为准,本文仅作换算参考。
升档代价:0.031 到 0.09 是 2.9 倍,到 0.3 是 9.7 倍。每天 5000 次里若有 20% 升到 gpt-5.3-pro:4000 × 0.031 + 1000 × 0.3 = ¥424/天,比全用走量档的 ¥155/天多花 ¥269,一个月多 ¥8070。
判断用通过率:抽 50 条真实请求,便宜档跑一遍人工判对错。高于 90% 留在便宜档;80% 到 90% 先加一轮自检再试;低于 80% 才升一档。
从线上请求里抽 100 条做固定评测集,覆盖长文、短句、空输入几类边界,人工标好答案存成 JSON。每次换档前跑一遍,通过率掉超过 3 个百分点就不换;只把出错的那几类样本单独回升档。
按量口径下输入长度直接等于钱。把第 2 轮之前的对话压成 200 字摘要,输入从 8000 token 降到 3000 token,一次省 5000 ÷ 100 万 × 3 = ¥0.015,每天 5000 次就是 ¥75/天、¥2250/月。
输出单价是输入的 5 倍,所以让模型少啰嗦比少喂资料更值钱。同样砍 500 token:砍输出省 500 ÷ 100 万 × 15 = ¥0.0075,砍输入只省 ¥0.0015。
在系统提示词里写明不要复述问题、不要重复原文、直接给结论和步骤,一次回复从 1500 token 降到 600 token,省 ¥0.0135,每天 5000 次是 ¥67.5/天、¥2025/月。
一次塞 5 个文件、每个 4000 token,输入 2 万 token,按量成本 ¥0.06。改成先检索再生成、只带 1 个命中文件(4000 token),成本 ¥0.012,一次省 ¥0.048。检索这一步用本地关键词或向量库,别调大模型。
这三件事在按次口径下一分钱都不省:写一千字和写一百字同价。它们省的是延迟和 Agent 循环轮数,轮数才是按次口径的计费单位。
公式只有一行:每月花费 = 月请求数 ×(1 - 命中率)× 加权单价。
月请求 15 万次(5000 × 30)、加权单价 ¥0.0402 时代进去:不缓存是 150000 × 0.0402 = ¥6030;命中率 35% 是 150000 × 0.65 × 0.0402 = ¥3919.5;命中率每提高 10 个百分点,省 ¥603/月。
键用 sha256(模型名 + 归一化后的 prompt + 关键参数)。归一化最容易漏:去首尾空白、统一换行、连续空格压成一个、去掉时间戳和随机串。同一句问话多打一个空格就是两次请求。过期时间:常见问题 30 天,报错解释 7 天,涉及价格的 1 天。
# cache.py —— 命中就直接返回,没命中才真的发请求
import hashlib
import time
def cache_key(model, prompt, extra=""):
raw = model + "|" + " ".join(prompt.split()) + "|" + extra
return hashlib.sha256(raw.encode("utf-8")).hexdigest()
def get_or_call(db, model, prompt, call_fn, price, ttl=7 * 86400):
key = cache_key(model, prompt)
row = db.execute("select answer, ts from cache where key = ?", (key,)).fetchone()
if row and time.time() - row[1] < ttl:
log(db, model, 0.0, hit=1) # 命中也要记一笔,命中率才算得出来
return row[0], True
answer = call_fn(model, prompt)
db.execute("insert or replace into cache values (?, ?, ?)", (key, answer, time.time()))
db.commit()
log(db, model, price, hit=0)
return answer, False
100 条短任务合并成 1 次请求:分开跑 100 × 0.031 = ¥3.1,合并后 ¥0.031,账面省 99%。这是按次计费才有的红利;按量口径下合并只省掉重复的系统提示词,量级完全不同。
合并省的是请求数,代价是三项新成本:解析失败重跑、串行等待、为合并而升档。四个条件同时成立收益才干净:单条输入 500 token 以内、输出格式固定可解析、可以离线跑、月度节省金额够大。
最后一条最容易忽略。一个月只有 50 条短任务时,合并只省 ¥1.5,为它写解析器和重跑逻辑是亏的。反过来每天 5000 条,分开是 ¥155/天即 ¥4650/月;每批 100 条则 50 批 × 0.031 = ¥46.5/月,省下 ¥4603。
会,而且藏得最深。按次计费算的是上游受理的请求数,不是你拿到结果的次数。读超时意味着上游大概率已把回答跑完并计费,重试一次就是两次的钱。按 ¥0.0402 算,每天 10% 的请求超时重试,就是 ¥20.1/天、一个月 ¥603。
状态未知的请求宁可人工看一眼,自动重发等于往账单上叠钱。
| 失败类型 | 是否重试 | 上限 | 说明 |
|---|---|---|---|
| 连接超时,没收到响应头 | 重试 | 2 次 | 上游大概率没受理 |
| 读超时,返回中断 | 先查缓存再重试 | 1 次 | 上游大概率已计费 |
| 429 限流 | 退避后重试 | 3 次 | 退避 1 秒、2 秒、4 秒 |
| 400、401、403 客户端错误 | 不重试 | 0 次 | 重试还是同样的错 |
| 5xx 上游错误 | 退避后重试 | 2 次 | 连续两次失败切备用域名 |
连续失败的兜底是切备用地址 https://xyuai.cc/v1,两边都失败就把任务挂起告警。
| 指标 | 口径 | 告警阈值 | 它在提示什么 |
|---|---|---|---|
| 当日请求数 | 成功 + 失败 | 超近 7 日均值 3 倍 | 循环调用在烧钱 |
| 当日花费 | 成功次数 × 单价求和 | 超月预算 ÷ 30 的 1.5 倍 | 今天出事了 |
| 失败率 | 失败 ÷ 总请求 | 超过 5% | 上游稳定性 |
| 重试率 | 重试 ÷ 首次请求 | 超过 15% | 超时时间设太短 |
| 缓存命中率 | 命中 ÷ 总请求 | 低于 20% | 去重键有问题 |
| 单次均价 | 花费 ÷ 请求数 | 超上月均值 20% | 悄悄升档了 |
最该盯的是单次均价和缓存命中率:前者涨说明模型结构变了,后者掉说明请求结构变了。
# daily_cost.py —— 统计用量与花费,超预算就告警
import json
from collections import defaultdict
from datetime import date, timedelta
# 元/次,以各家模型官方页面的标价为准,这里仅作换算参考
PRICE = {
"gemini-2.5-pro": 0.031,
"deepseek-v3.2-thinking": 0.049,
"deepseek-v4-flash-thinking": 0.05,
"claude-sonnet-4-5-thinking": 0.09,
"kimi-k2.5": 0.09,
"claude-opus-4-5-thinking": 0.12,
"gpt-5.5": 0.2,
"gpt-5.3-pro": 0.3,
}
DAILY_BUDGET = 200.0 # 每天预算上限(元)
LOG = "usage.jsonl" # 每行一条 {"ts":..,"model":..,"ok":..,"retry":..}
def load(path):
rows = []
with open(path, encoding="utf-8") as f:
for line in f:
line = line.strip()
if line:
rows.append(json.loads(line))
return rows
def summarize(rows, day):
stat = defaultdict(lambda: {"calls": 0, "cost": 0.0})
fail = retry = 0
for r in rows:
if not r["ts"].startswith(day):
continue
if r["model"] not in PRICE:
print(" [WARN] 未登记单价的模型:%s" % r["model"])
if r.get("ok"):
stat[r["model"]]["calls"] += 1
stat[r["model"]]["cost"] += PRICE.get(r["model"], 0.0)
else:
fail += 1
if r.get("retry"):
retry += 1
return stat, fail, retry
def main():
rows = load(LOG)
for i in range(7): # 看近 7 天
day = (date.today() - timedelta(days=i)).isoformat()
stat, fail, retry = summarize(rows, day)
calls = sum(v["calls"] for v in stat.values())
cost = sum(v["cost"] for v in stat.values())
print("%s 请求=%d 花费=%.3f 元 失败=%d 重试=%d" % (day, calls, cost, fail, retry))
if cost > DAILY_BUDGET:
print(" [ALERT] 当日 %.3f 元超预算 %.1f 元,查有没有循环调用" % (cost, DAILY_BUDGET))
if calls and cost / calls > 0.08:
print(" [ALERT] 单次均价 %.4f 元偏高,查高价档占比" % (cost / calls))
for model, v in sorted(stat.items(), key=lambda kv: -kv[1]["cost"]):
print(" %-32s 次数=%-6d 花费=%.3f 元" % (model, v["calls"], v["cost"]))
if __name__ == "__main__":
main()
脚本打印近 7 天每天的请求数、花费、失败数、重试数。均价阈值设 0.08 元:加权均价 0.0402 说明结构正常,涨到 0.08 以上多半是高价档占比失控。
# 1) 令牌写进环境变量
export KEY="sk-你的令牌"
# 2) 查余额与订阅信息,接口路径以平台文档为准
curl -s https://xyuapi.top/v1/dashboard/billing/subscription \
-H "Authorization: Bearer $KEY" | python -m json.tool
# 3) 查用量统计
curl -s "https://xyuapi.top/v1/dashboard/billing/usage?start_date=2026-01-01&end_date=2026-01-31" \
-H "Authorization: Bearer $KEY" | python -m json.tool
# 4) 发一次调用,模型名直接用短名,max_tokens 卡住输出长度
curl -s https://xyuapi.top/v1/chat/completions \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-pro",
"messages": [{"role": "user", "content": "把这段话压成 3 条要点"}],
"max_tokens": 256
}'
把 model 换成表里任意短名,就能对比同一段提示词在不同档位下的表现。
| 顺序 | 动作 | 一次性成本 | 月度收益 | 边界 |
|---|---|---|---|---|
| 1 | 模型分档 70% / 25% / 5% | 1 天 + 100 条评测集 | ¥11970 | 没评测集质量会悄悄掉 |
| 2 | 结果缓存,命中 35% | 半天 + 一张表 | ¥2110 | 只对可重复请求有效 |
| 3 | 每日花费告警 | 半天 + 一个脚本 | 止损 | 阈值按自己的量调 |
| 4 | Agent 循环轮数上限 | 2 天改造 | 每减 1 轮省 ¥155/天 | 只对 Agent 负载有效 |
| 5 | 上下文压缩与输出约束 | 半天 | 按量口径 ¥4275 | 按次口径只降超时 |
| 6 | 批量合并 | 1 天 + 重跑逻辑 | 高量场景 ¥4603 | 要离线跑且输出可解析 |
| 7 | 重试与幂等键 | 半天 | 减少重复计费 | 要一张本地请求表 |
base_url 换成 https://xyuapi.top/v1,备用 https://xyuai.cc/v1;OpenAI 兼容 SDK 只改 base_url 和 api_key 两行。模型名用短名,直接填表里的名字。最低充值 7 元起,先充 7 元跑通链路、验完一个真实任务再放量。分档规则做成配置表(任务类型对应模型名),换档改配置不改代码。