[控场AI]
· 8 分钟阅读· 4,376 字

AI智能体成本核算:按运行定价,而非按Token计费

AI智能体成本核算:按运行定价,而非按Token计费

Token只是计费表,秒数才是截止日期真正读取的仪表,只限Token会延误交付。

文章指出,在AI智能体运行中,Token计费和墙上时钟是两套成本仪表。免费容量让重试在Token上免费,却忽略了排队时间成本,可能导致用户等待时间过长。每次重试都会重新发送整个上下文,使累计Token成本呈二次增长,墙上时钟还受排队等待影响。作者提出通过JSONL账本记录每次尝试的Token和时间双指标,并按已接受任务聚合出每任务Token数、秒数和尝试次数。重试上限应从上下文大小和Token天花板推导得出,而非凭感觉设定。当每任务尝试次数超过2时,提示词可能在猜测而非工作。免费容量适合夜间批处理等可接受抖动的场景,但不适合有人等待的交互界面或有硬性截止日期的任务。

核心观点: Token只是仪表盘上可见的计费表,而秒数才是截止日期真正读取的仪表。只限制Token而忽略时间,会在图表看起来健康时延误交付。


为什么免费容量会扭曲成本判断

免费Token让重试变得廉价,于是人们不再计算尝试次数。但尝试并非零时间成本。

每当涉及免费容量时,这种失败模式就会出现:重试在Token上免费,在墙上时钟上却昂贵。两次重试在共享免费层上可能是90秒的生成时间加4分钟排队等待。对于夜间批处理任务,这没问题;对于需要用户盯着进度条等待的任何任务,这是致命的。

运行成本核算示意图

每次重试都会重新购买上下文

重试不是从上一个好词继续播放。在大多数智能体循环中,你会追加失败信息或验证器输出,然后再次发送整个上下文。

  • 第一次尝试:消耗基础上下文
  • 第二次尝试:消耗上下文 + 第一个错误
  • 第三次尝试:消耗上下文 + 两个错误,以此类推

运行的总Token成本增长速度超过尝试次数本身,而墙上时钟成本还包含你无法控制的排队等待。

墙体时钟(Wall-clock) 是衡量现实世界时间流逝的指标,与CPU时间或Token消耗不同,它包含了排队、网络往返、速率限制退避等所有等待。在智能体工作流中,Token用量通常可见于API响应,但墙上时钟却常被忽略。免费容量下,每次重试可能触发速率限制,导致指数级退避,使墙上时钟成本远超Token成本。例如,两次重试可能仅消耗少量Token,但若在共享免费层排队4分钟,实际交付延迟会破坏用户体验。因此,墙上时钟才是截止日期的真实度量,需要在每次尝试中显式记录。

在每次尝试中记录两个仪表读数

最便宜的修复方案是记账。每次尝试写一行记录,在决定任何结果之前就写好。

# runledger.py — 每次模型尝试写入一行 JSONL
import json, time, pathlib, hashlib

LEDGER = pathlib.Path("runs/ledger.jsonl")
LEDGER.parent.mkdir(exist_ok=True)

def attempt(task_id, prompt, client, accept, **gen_kw):
    rec = {
        "task": task_id,
        "prompt_sha": hashlib.sha256(prompt.encode()).hexdigest()[:12],
        "prompt_chars": len(prompt),
    }
    started = time.monotonic()
    resp = client.generate(prompt, **gen_kw)
    gen_s = time.monotonic() - started
    ok = accept(resp)
    rec.update(
        gen_s=round(gen_s, 2),
        wall_s=round(time.monotonic() - started, 2),
        prompt_tokens=getattr(resp.usage, "prompt_tokens", None),
        completion_tokens=getattr(resp.usage, "completion_tokens", None),
        accepted=bool(ok),
    )
    with LEDGER.open("a") as fh:
        fh.write(json.dumps(rec) + "\n")
    return resp, ok

注意记录中没有模型输出。你记录的是成本而非内容。将输出保存在你自己的存储中,使账本保持足够小以便阅读。

让重试上限从算术中自然产生

多数团队凭感觉选择重试上限——三次、五次,或者上一个负责人随手写的数字。你其实可以推导出来。

如果每次失败向初始上下文 c 追加约 e 个Token,则 n 次尝试的累计Token成本为 n*c + e*n*(n-1)/2。将其对你的上限求反解即可。

def attempt_cap(context_tokens, error_tokens, ceiling_tokens):
    """在Token上限内可容纳多少次尝试(含重新发送)。"""
    spent = 0
    n = 0
    while True:
        spent += context_tokens + n * error_tokens
        if spent > ceiling_tokens:
            return n
        n += 1

print(attempt_cap(context_tokens=8000, error_tokens=400, ceiling_tokens=120000))

用你真实的上下文大小运行这个函数,答案通常小于你正在使用的数字。上限是预算决策,不是性格特征。

按已接受任务聚合,而非按调用聚合

逐次调用的仪表盘会自我美化:每次调用都成功了,因此系统高效。但按任务分组并将失败尝试的成本计入任务,因为钱就花在那里。

import json, collections

runs = collections.defaultdict(lambda: {"tok": 0, "s": 0.0, "n": 0, "ok": False})
for line in open("runs/ledger.jsonl"):
    r = json.loads(line)
    g = runs[r["task"]]
    g["tok"] += (r["prompt_tokens"] or 0) + (r["completion_tokens"] or 0)
    g["s"] += r["wall_s"]
    g["n"] += 1
    g["ok"] = g["ok"] or r["accepted"]

done = [g for g in runs.values() if g["ok"]]
print("accepted:", len(done), "of", len(runs))
print("tokens/accepted:", sum(g["tok"] for g in done) // max(len(done), 1))
print("seconds/accepted:", round(sum(g["s"] for g in done) / max(len(done), 1), 1))
print("attempts/accepted:", round(sum(g["n"] for g in done) / max(len(done), 1), 2))

第三个数字告诉你应该提高验收测试标准还是降低上限。如果每个已接受任务的尝试次数漂移到2以上,你的提示词在猜测而非工作,再多的免费容量也无法修复一个猜测循环。

验收测试(Acceptance Test) 是判断一次模型输出是否可用的函数,例如格式校验、单元测试通过或人工审核。在智能体循环中,验收测试是决定是否重试的关口,其严格程度直接影响尝试次数和总成本。如果验收测试过于宽松,错误结果会被接受,下游修复成本更高;如果过于严格,重试次数上升,Token和时间成本激增。文章中的accepted字段正是基于验收测试的结果,聚合时只计入最终被接受的任务成本。因此,优化验收测试是平衡成本与质量的关键杠杆,也是判断“提示词在猜测而非工作”的核心依据。

免费容量何时是错误的选择

免费容量在以排队时间换取金钱时是合理的交易。一旦排队时间落在别人的关键路径上,它就变成糟糕的交易。

任务形态免费容量承诺容量
有人盯着进度条等待很少值得是
夜间批处理,早上交付是,需推导上限仅当截止日期是合同义务时
长上下文深度重试仅在强制执行上限时是,因为每次重试重发所有内容
一次性任务突发是,接受抖动是,如果抖动破坏下游SLA

仔细阅读第二列。这不是降级。用秒数换Token是正当的工程选择——只要你清楚花了哪种货币,并且记录在案。

此方法的局限

该账本仅测量传输层暴露的内容。如果缺少Token计数,你的总计是估算值,应如实标注。排队等待随一天中的时段变化,因此单个下午的样本会产生误导;至少收集一周数据再在生产中设定上限。数字属于你自己,不可转移——其他团队的每任务Token数对你的提示词毫无参考价值。

如果你有硬性外部截止日期、亚秒级交互界面,或要求提示词保留在自有网络内的合规规则,请勿使用此方法。如果你的验收测试是“看起来没问题”,那就完全跳过账本;没有真正的测试,accepted 就是常量,第三个指标变成噪声。

免费层的实际用途

有一个值得了解的项目:MonkeyCode是一个开源编码智能体项目,其运营方表示新账户在其免费模型上获得1000万Token额度以及免费服务器选项。请将此视为运营方提供的信息,在围绕其规划预算前检查当前项目页面,因为额度会变化。

披露:本文作为MonkeyCode产品推广的一部分撰写。

诚实的使用方式是将其作为测量环境而非生产答案。将账本指向免费模型,运行自己的任务集一周,你就能获得真实的每已接受任务Token数和每已接受任务秒数,而无需为观察付费。免费服务器选项意味着收集器和聚合器的定时任务可以托管在你的笔记本之外。

然后阅读你自己的表格。如果每已接受任务秒数对你的工作负载可接受,继续花费便宜货币。如果不可接受,你现在有了一个可以争论的数字而非感觉。关键从来不是提供商,而是为运行定价。

#AI智能体成本核算#Token计费#运行成本#重试上限#免费容量#LLM成本优化#智能体重试策略
分享:

相关推荐