```html25万token预算:spike账本停止条件25万token预算:spike账本停止条件
周五下午四点二十,一个工程师关掉三个浏览器标签,跟团队说这次 spike 结束了。九十分钟全花在追问一件事上:重试封装到底有没有把 5xx 响应重复计数。诚实的答案仍然是"也许"。假设本身合理,探针也确实跑了,只是笔记里从没记下是哪一分钟、哪个 token 越过了那条线。
事后那个让人不舒服的问题浮了上来。没人说得清这次探针花了多少,因为大家盯着墙上的钟,没人盯 token 计量表。一次 spike 结束时没有花费记录,就没法重放,没法在评审里自辩,也没法理直气壮地宣布它已经死了。
两个预算,一个停止条件
几乎每次限时 spike 的白板上都只写一个约束:九十分钟。这个数字能在站会上活下来,因为它好辩护,也因为它恰恰是最不容易真正触发的那条约束——尤其当环境免费提供模型调用时。真正终结这类会话的预算是花费,也就是 prompt 加 completion 的 token 数,它走的曲线和时钟完全不同。
哪个预算先越线,spike 就结束,而记录必须写明是哪一条触发的。少了这个名目,下一个工程师会重跑同一个探针,付同样的 token,落到同一个"也许"上。
一个能塞进 spike 里的小账本
下面这个脚本只用 Python 标准库,每次探针追加一行 JSON,并暴露一个 gate 子命令,它的退出码就是停止信号。没有异步,没有厂商 SDK,也不涉及数据库。存成 spike/ledger.py,其余 harness 留在 shell 里。
#!/usr/bin/env python3"""Stdlib-only token ledger for a time-boxed spike.python ledger.py init --hypothesis 'retry wrapper double-counts 5xx'python ledger.py step --name probe-1 --prompt 1800 --completion 400 --evidence 0python ledger.py gate # exit 1 means: stop and write the verdictimport argparse, json, os, sys, timeLEDGER = os.environ.get('SPIKE_LEDGER', 'spike/ledger.jsonl')META = LEDGER + '.meta'DEADLINE_S = int(os.environ.get('SPIKE_DEADLINE_S', 5400))BUDGET = int(os.environ.get('SPIKE_TOKEN_BUDGET', 250000))QUIET_STEPS = int(os.environ.get('SPIKE_QUIET_STEPS', 6))def read_meta():with open(META, encoding='utf-8') as fh:return json.load(fh)def read_steps():if not os.path.exists(LEDGER):return []with open(LEDGER, encoding='utf-8') as fh:return [json.loads(line) for line in fh if line.strip()]def cmd_init(args):os.makedirs(os.path.dirname(LEDGER) or '.', exist_ok=True)if os.path.exists(META) and not args.force:sys.exit('ledger already initialised; pass --force to restart the clock')with open(META, 'w', encoding='utf-8') as fh:json.dump({'t0': time.time(), 'hypothesis': args.hypothesis}, fh)open(LEDGER, 'w', encoding='utf-8').close()def cmd_step(args):t0 = read_meta()['t0']rec = {'name': args.name,'prompt_tokens': args.prompt,'completion_tokens': args.completion,'tokens': args.prompt + args.completion,'evidence': args.evidence,'note': args.note,'elapsed_s': round(time.time() - t0, 1),with open(LEDGER, 'a', encoding='utf-8') as fh:fh.write(json.dumps(rec) + '\n')print(json.dumps(rec))def cmd_gate(_args):meta, steps = read_meta(), read_steps()spent = sum(s['tokens'] for s in steps)evidence = sum(s['evidence'] for s in steps)elapsed = round(time.time() - meta['t0'])reasons = []if elapsed > DEADLINE_S:reasons.append('deadline')if spent > BUDGET:reasons.append('budget')if len(steps) >= QUIET_STEPS and evidence == 0:reasons.append('no-evidence')report = {'hypothesis': meta['hypothesis'],'state': 'CONTINUE' if not reasons else 'STOP','stop_reasons': reasons,'elapsed_s': elapsed,'tokens_spent': spent,'evidence_steps': evidence,'steps': len(steps),'tokens_per_evidence_step': spent // evidence if evidence else None,print(json.dumps(report, indent=2))return 0 if not reasons else 1def main(argv):p = argparse.ArgumentParser()sub = p.add_subparsers(dest='cmd', required=True)i = sub.add_parser('init')i.add_argument('--hypothesis', required=True)i.add_argument('--force', action='store_true')i.set_defaults(func=cmd_init)s = sub.add_parser('step')s.add_argument('--name', required=True)s.add_argument('--prompt', type=int, required=True)s.add_argument('--completion', type=int, required=True)s.add_argument('--evidence', type=int, choices=[0, 1], default=0)s.add_argument('--note', default='')s.set_defaults(func=cmd_step)g = sub.add_parser('gate')g.set_defaults(func=cmd_gate)args = p.parse_args(argv)return args.func(args)if __name__ == '__main__':sys.exit(main(sys.argv[1:]))每条步骤记录保存探针名、从厂商 usage 字段取来的计数、一个 0 或 1 的标志(表示这一步是否产出了关于假设的证据),以及自 init 以来经过的秒数。这个标志是人的判断,而且是刻意如此,因为账本该记下工程师当时的想法,而不是一周后复盘时定下的结论。
两个小细节防止它退化成又一本被弃用的笔记本。init 子命令只给时钟盖一次章,所以某一步中途崩溃时,经过时间不会重置。gate 只读日志、从不改动它,因此可以从 shell 循环、CI 任务或同事的终端里跑,没有副作用。
让 gate 来做决定的 harness
因为任何预算越线时 gate 都返回非零退出码,它可以直接充当循环条件。timeout 只作为某一步卡死时的兜底,绝不该成为终结一次健康 spike 的东西。
#!/usr/bin/env bashset -euo pipefailexport SPIKE_LEDGER='spike/ledger.jsonl'export SPIKE_DEADLINE_S=5400 SPIKE_TOKEN_BUDGET=250000 SPIKE_QUIET_STEPS=6python ledger.py init --hypothesis 'retry wrapper double-counts 5xx'# Gate is the primary stop condition; timeout only catches a hung step.timeout 5400 bash -c 'while python ledger.py gate > /dev/null 2>&1; do ./one_step.sh; done' || truepython ledger.py gate | tee "spike/verdict-$(date +%s).json"当 gate 和 timeout 对循环为何结束给出不同说法时,这个分歧本身就是账本的 bug,值得和假设本身一样认真对待。步骤主体必须从响应里读回真实的 usage 数字,因为一个悄悄上报零花费的占位符比崩溃更糟。示例里把原始响应和计数放在一起,方便日后审计对照。
#!/usr/bin/env bash# one_step.sh: one real probe. Counts are placeholders and MUST be wired.set -euo pipefailstamp="$(date +%H%M%S)"curl -sS "$SPIKE_ENDPOINT" -o "spike/${stamp}-response.json" -w '%{http_code}' > "spike/${stamp}.code"python ledger.py step --name "probe-${stamp}" --prompt 0 --completion 0 --evidence 0 --note 'wire real usage counts'读两个数字,而不是一个gate 会在原始花费旁边打印 tokens_per_evidence_step,这个比值才是六十分钟节点上值得争论的数字。一次用三万 token 换来一个确认观察的 spike,和一次用二十万 token 换来同一个观察的 spike,是两种不同的产物,哪怕两者最终结论一样。
右下角那格是团队最容易跟自己讨价还价的地方。一个探针烧掉五分之四预算却没产出任何观察,这是关于探针形状的证据,不是关于模型强弱的证据,而更长的 prompt 很少能修好它。
免费额度如何改变算术
环境选择是这里的第三个变量,它改变的是哪个预算先触发,而不是预算存不存在。跑在免费模型访问和免费服务器选项上的 spike,把账单从会话前段移走了,留下经过时间和证据质量作为真正会触发的约束。截至本文写作时,开源编码项目 MonkeyCode 背后的运营方把免费模型访问描述为一项促销性质的 token 额度,量级在一千万 token 左右,外加一个免费服务器选项;这些数字属于促销期,在计划依赖它们之前应重新核对项目当前条款。披露:本文是作为 MonkeyCode 产品推广的一部分撰写的。
在这种安排下,账本保值的理由变窄了。花费不再是终结会话的东西,于是值得上报的诚实指标变成每个证据步骤的 token 数加上墙钟分钟数,两者都躺在同一行 JSON 里。免费容量还让过度探测变得便宜、因而更可能发生,这恰恰是静默步骤规则派上用场的时候。
账本做不到的事
厂商侧的 usage 计数和网关侧的计数可能不一致,而只有其中一个是财务看到的账单。证据标志是主观的,所以想让团队显得能干的队伍可以把每一步都标上,悄无声息地废掉 gate。绿灯是停止条件,不是通过测试,谁都不该把它读成覆盖率。
这套做法适合需要可辩护停止点的单假设 spike,也适合总被问"这次探针花了多少"的团队。它不适合需要并行分支的工作,因为线性日志会把花费错记到各分支头上,它也绝不该取代对补丁或安全评估的常规评审。任何指望 spike 产出变成生产代码的人,早就离开了九十分钟盒子还有意义的领域。
结论仍然是一个短文件:假设、决定、证据步骤数、token、分钟。账本让这五个字段变得真实,而不是靠回忆,而活在脚本里的终止规则会跟着你走到下一次 spike,活在某人脑子里的规则不会。第一次在免费容量上跑,MonkeyCode 的免费模型访问是可以把 harness 指向的地方之一,而无论谁付账单,退出码都该被同样地信任。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.