AI 工具订阅管理:用一张 CSV 和一段 Python 算清三层成本、生成续费提醒日历
AI 工具的订阅账单失控根因在于计费模型从固定月费变成了固定 额度 按量三层而多数人的记账方式还停在第一层。解决办法是一张八字段的台账加一段每月跑一次的脚本输出三层预算、能力重复清单、僵尸订阅候选和一份续费提醒日历。扣款链路本身怎么排障我在这个专栏前两篇写过本篇不重复。七月底我把自己的订阅账单从头对了一遍。十一项在跑实际支出比我以为的多出接近四成。拆开看没有一项是被坑的两个工具功能重了一半一个首月优惠到期恢复原价还有一项按用量结算的服务赶上我那周跑批量任务账单翻倍。都是我自己点的确认。问题不在钱在于这三笔多出来的钱各属于不同的成本类型而我用同一种方式在记它们。一、AI 时代的订阅计费分三层别只记第一层以前的 SaaS 订阅好办页面标二十美元账单就是二十美元记一个数字就够了。现在至少要分三层。第一层 固定订阅fixed。每月一个数最容易预测也最容易被忽略因为它从不出错。第二层 套餐内额度quota。会员费只是门票。额度用超要买补充包有些高级功能另行计价。这一层的特征是有上限但会突刺正常月份等于固定费某个月赶上高强度使用就跳一档。第三层 纯按量usage。API、云服务、一部分 Agent 类工具按调用量、任务时长或资源消耗计费。这一层没有天然上限同一个月做个原型和跑一批任务能差出几倍。分不清某个工具落在哪一层有个不需要读文档的办法把它最近三期账单金额并排放着看。三期完全一致的是 fixed差几分几毛的是 fixed 叠加了税费与币种折算的浮动差出一截的是 quota 突刺或者 usage。对应到预算就不该写成一个数字本月预算 Σ固定订阅 Σ可变用量预留 (前两项之和 × 折算与税费余量比例)第三项是很多人漏掉的。跨币种结算时最终授权金额通常不等于页面标价按标价刚好准备资金容易差几毛钱。余量比例按自己历史账单回归一个值即可我用 3%。二、台账 schema八个字段不要再多字段设计的原则是每一个字段都要能驱动一个决策凑数的字段最后没人填。name,group,billing_model,fixed_usd,variable_est_usd,next_charge,capabilities,last_used_days ChatGPT Plus,core,fixed,20.00,0,2026-09-03,chat;code_assist,1Claude Pro,core,fixed,20.00,0,2026-09-11,chat;long_context,2Cursor Pro,core,quota,20.00,15.00,2026-08-28,code_assist;completion,1GitHub Copilot,trial,fixed,10.00,0,2026-09-05,completion,47Notion AI,core,fixed,10.00,0,2026-09-19,notes;chat,6Vercel Pro,infra,usage,20.00,35.00,2026-09-01,hosting,3OpenAI API,infra,usage,0,60.00,2026-09-01,api;chat,2Figma Pro,trial,fixed,15.00,0,2026-08-30,design,63几个字段的设计意图group分 core / trial / infra 三组对应三种处置策略核心生产工具优先保证扣款、试用工具到观察期做去留、基础设施按波动监控。billing_model决定这一项进预算公式的哪一层。capabilities是这张表里唯一非账务的字段用分号分隔的能力标签。加它的原因是重复订阅几乎全部发生在能力维度而不是工具维度光看工具名字永远看不出编辑器插件里已经带了补全、而你又在为另一个补全工具单独付费。last_used_days手填就行。真要自动化可以接各家的 usage API但为了一个每月跑一次的脚本去维护八套鉴权不划算。三、脚本四十行每月跑一次import csv, datetime, collections FX_BUFFER 0.03 # 折算与税费余量比例按自己历史账单调整 ZOMBIE_DAYS 30 # 超过这个天数未使用进僵尸候选 rows list(csv.DictReader(open(subscriptions.csv))) f lambda r, k: float(r[k] or 0) 1. 三层预算 fixed sum(f(r, fixed_usd) for r in rows) var sum(f(r, variable_est_usd) for r in rows) buf (fixed var) * FX_BUFFER print(f固定订阅 {fixed:8.2f}) print(f可变用量预留 {var:8.2f}) print(f折算与税费余量 {buf:8.2f}) print(f本月预算合计 {fixed var buf:8.2f}\n) 2. 按分组汇总看结构失衡 by_group collections.defaultdict(float) for r in rows: by_group[r[group]] f(r, fixed_usd) f(r, variable_est_usd) for g, v in sorted(by_group.items(), keylambda x: -x[1]): print(f {g:6s} {v:8.2f}) 3. 能力重复检出 cap collections.defaultdict(list) for r in rows: for c in r[capabilities].split(;): cap[c].append(r[name]) print(\n能力重复) for k, v in cap.items(): if len(v) 1: print(f {k}: {, .join(v)}) 4. 僵尸订阅候选 print(f\n僵尸候选超过 {ZOMBIE_DAYS} 天未用) for r in rows: if int(r[last_used_days]) ZOMBIE_DAYS: cost f(r, fixed_usd) f(r, variable_est_usd) print(f {r[name]:16s} {r[last_used_days]:3s} 天 月成本 {cost:.2f}) 5. 生成续费提醒日历 def ev(uid, dt, summary): return [BEGIN:VEVENT, fUID:{uid}, fDTSTART;VALUEDATE:{dt:%Y%m%d}, fSUMMARY:{summary}, END:VEVENT] lines [BEGIN:VCALENDAR, VERSION:2.0, PRODID:-//subs//CN] for i, r in enumerate(rows): d datetime.date.fromisoformat(r[next_charge]) lines ev(f{i}asubs, d - datetime.timedelta(days7), f[决策] {r[name]} 下月还续吗) lines ev(f{i}bsubs, d - datetime.timedelta(days2), f[检查] {r[name]} 卡片余额/套餐/账单地址) lines.append(END:VCALENDAR) open(renewals.ics, w).write(\r\n.join(lines)) print(f\n已写出 renewals.ics共 {len(rows) * 2} 条提醒)无第三方依赖标准库跑得动。上面那份示例 CSV 的真实输出固定订阅 115.00 可变用量预留 110.00 折算与税费余量 6.75 本月预算合计 231.75 infra 115.00 core 85.00 trial 25.00 能力重复 chat: ChatGPT Plus, Claude Pro, Notion AI, OpenAI API code_assist: ChatGPT Plus, Cursor Pro completion: Cursor Pro, GitHub Copilot 僵尸候选超过 30 天未用 GitHub Copilot 47 天 月成本 10.00 Figma Pro 63 天 月成本 15.00 已写出 renewals.ics共 16 条提醒四、输出怎么读可变用量占比。这份样例里 110 / 225接近一半的支出没有上限。这个比例超过三成说明你的月度成本已经跟工作强度绑死了预算要按峰值月准备不能按平均月。分组结构。infra 115 超过 core 85是个信号。基础设施的钱超过生产工具的钱通常意味着有测试环境忘了关或者某个服务的套餐档位买高了。能力重复要分真假。chat命中四项属于假重复同类模型能力本来就要横向对比着用。completion命中 Cursor Pro 和 GitHub Copilot 是真重复两者在补全这件事上高度替代留一个就够。脚本只负责把候选摆出来判断留给人。僵尸候选看的是绝对金额乘以时间。Figma Pro 63 天没打开一年就是 180 美元这笔钱换算成时薪够你做别的事了。五、扣款之前的最后一环账户分层与先划再付台账管的是该不该付还有一层管能不能付。我用的是储值型的卡先充值再消费不能透支手里这张是 MPChat 的。这类卡的账户通常分两层账户充值 ↓ 钱包账户 ← App 首页显示的那个数字通常是这个 ↓ 划转 卡片账户 ← 发卡方在授权时校验的是这一个 ↓ 商户发起扣款关键点是发卡方授权时校验的是卡片账户的可用余额钱包账户里的余额在这一步不参与计算。所以钱到账了不等于卡能扣。脚本生成的那条 T-2 提醒要检查的就是这一栏。我的做法是打开 MPChat 里承接订阅的那张卡只看可用余额判断它够不够覆盖本期金额加上税费与折算余量。够就关掉提醒不够就补整个动作十几秒。具体的账户层级、卡片数量与划转规则以 App 内实际显示为准。顺带一提自动续费在技术上属于持卡人不在场的场景跟你第一次手动订阅时的交互条件不同。这意味着续费失败的时候你没有机会临时补一次验证只能靠提前把余额和登记信息准备好。账单地址是同一类问题结账页填的信息要和卡片登记信息保持一致尤其是门牌号和邮编这些进入比对的数字部分。一次核准之后保持一致。六、真失败了按顺序查别连刷1. 钱在钱包账户还是已经到了卡片账户 2. 卡片可用余额是否覆盖本期金额、税费和折算余量 3. 账单地址是否与卡片登记信息一致 4. 结账时是否出现过额外验证自己关掉或错过了 5. 这是官网直订还是 Apple ID / Google Play 平台代扣顺序走完之前别在一分钟里连点十几次。各家平台对短时间重复尝试怎么处理规则不一样以实际结果为准。从我自己的经验看本来是余额或者地址的小问题连刷一轮之后往往更难收场。还有一个入口要分清给卡充值和给订阅续费是两个动作。同理往 Apple ID 或 Google Play 平台账户里充值也不等于给某个具体订阅续费删掉客户端更不等于退订退订要在工具官网的账单页或应用商店的订阅管理里完成。七、月度检查清单[ ] 新增工具已写入 subscriptions.csv八个字段填全 [ ] 脚本已跑三层预算与分组汇总已看过 [ ] 能力重复清单已人工判真假真重复的已处置 [ ] 僵尸候选已按金额乘时间排序连续两个月上榜的已退订 [ ] renewals.ics 已导入日历T-7 与 T-2 提醒生效 [ ] 卡片账户可用余额覆盖本期扣款并留有余量 [ ] 账单地址与卡片登记信息保持一致 [ ] 扣款异常先按五步定位不连续重试写在最后一个人做事最贵的资产是专注力。这套东西省下的钱其实不算什么值钱的地方在于把这个月账单会不会出事从一个悬着的问题变成一个每月跑一次脚本就有答案的问题。台账、三层预算、能力去重、续费提醒和账户分层合起来做的是同一件事让付款成功从一个靠临时想起来的结果变成一套可以复现的流程。脚本和示例 CSV 可以直接复制走改成自己的。如果你的capabilities标签体系跑出了更好的分类欢迎在评论区贴出来交流。讨论具体扣款故障时卡号、有效期、验证码和交易 ID 不要公开描述现象和报错原文就够定位。我在做 MPChat一款把私密聊天和跨境支付放在一起的工具平时在这个专栏整理海外订阅和付款故障的排查经验。App及卡的具体能力、费用与规则以官网说明为准 mp.net本文为个人订阅成本管理方法与脚本分享不构成财务或记账建议也不构成对付款结果的承诺。文中金额与工具组合为示例数据非任何产品的真实报价。