AI 编程工具的成本,不能只看一次回答生成了多少 token。一个看似简短的输出,如果没有解决问题,开发者还要继续追问、重新生成、运行测试、修复错误,最终消耗的 token、时间和算力可能远高于一次较长但可直接采用的回答。
GitHub Copilot 讨论的核心正是这一点:降低 AI 编程成本,不应以牺牲任务质量为代价,而应减少整个编码任务中的无效工作。
短输出为什么可能更贵
假设有两个方案:
- 方案 A 生成 800 个输出 token,但代码一次通过测试。
- 方案 B 只生成 300 个输出 token,却需要三轮追问、两次重试和一次人工修复。
如果只统计单次响应,方案 B 看起来更便宜;如果统计完整任务,结论可能完全相反。真正应该关注的是:
完整任务成本 = 输入成本 + 输出成本 + 工具调用成本 + 重试成本 + 人工修复成本
这里的“人工修复成本”未必直接体现在模型账单中,却会影响开发团队的实际产出。工程师花在理解错误建议、补充上下文和验证结果上的时间,同样属于任务成本。
这也解释了一个常见现象:更短的回答不一定更高效。回答缺少必要的上下文、边界条件或测试说明时,后续工作会被推迟到下一轮交互中。
从单次响应转向完整任务
评价 AI 编程工具,可以从“这次回答用了多少 token”转向几个更接近工程结果的指标:
- 任务完成率:任务是否最终达到验收标准。
- 首次通过率:生成的代码是否能在第一次运行时通过测试或检查。
- 重试次数:为了完成同一个任务,开发者需要重新生成多少次。
- 无效输出比例:输出中有多少内容没有进入代码、测试或文档。
- 人工介入时间:开发者需要花多少时间修正或解释模型结果。
- 单位完成任务成本:完成一个可验收任务平均需要多少资源。
这些指标共同描述了“完成一项工作”到底花了什么,而不是只描述模型说了多少话。
可以这样理解:AI 编程的优化目标不是让每条消息尽可能短,而是让从需求到可交付结果的路径尽可能短。
一个可运行的成本估算示例
下面的 Python 示例使用假设价格,比较两个完成同一任务的过程。它没有代表任何特定模型的真实计费规则,适合改造成团队内部的粗略分析脚本。
from dataclasses import dataclass
@dataclass
class Attempt:
input_tokens: int
output_tokens: int
tool_calls: int = 0
human_minutes: int = 0
INPUT_PRICE_PER_MILLION = 3.0
OUTPUT_PRICE_PER_MILLION = 15.0
TOOL_CALL_PRICE = 0.02
HUMAN_COST_PER_MINUTE = 0.80
def estimate_cost(attempts: list[Attempt]) -> float:
input_tokens = sum(item.input_tokens for item in attempts)
output_tokens = sum(item.output_tokens for item in attempts)
tool_calls = sum(item.tool_calls for item in attempts)
human_minutes = sum(item.human_minutes for item in attempts)
model_cost = (
input_tokens / 1_000_000 * INPUT_PRICE_PER_MILLION
+ output_tokens / 1_000_000 * OUTPUT_PRICE_PER_MILLION
)
return model_cost + tool_calls * TOOL_CALL_PRICE + human_minutes * HUMAN_COST_PER_MINUTE
efficient = [
Attempt(input_tokens=2_000, output_tokens=300, tool_calls=2, human_minutes=12),
Attempt(input_tokens=2_500, output_tokens=300, tool_calls=2, human_minutes=10),
Attempt(input_tokens=2_500, output_tokens=300, tool_calls=1, human_minutes=8),
]
effective = [
Attempt(input_tokens=4_000, output_tokens=800, tool_calls=2, human_minutes=4),
]
print(f"短输出但多次重试: ${estimate_cost(efficient):.2f}")
print(f"一次较完整的输出: ${estimate_cost(effective):.2f}")
运行前可以调整四个变量:输入和输出 token 价格、工具调用价格,以及人工每分钟成本。这个模型的重点不是得到精确账单,而是提醒团队把重试、工具调用和人工时间纳入评估。
在真实项目中,还可以从 IDE 插件、CI 测试和任务系统收集以下事件:
任务开始 -> 模型请求 -> 代码修改 -> 测试运行 -> 失败/通过 -> 重试 -> 任务完成
将这些事件关联到同一个任务 ID,才能知道一次短回答是否把更多工作推给了后续步骤。
降低浪费,而不是简单压缩回答
围绕完整编码任务优化,通常有几条实践路径:
提供刚好够用的上下文
上下文太少,模型容易遗漏接口约束、测试要求或项目约定;上下文太多,又会增加输入成本并干扰重点。上下文选择应围绕当前任务组织,例如相关文件、调用方、失败测试和明确的验收条件。
让模型参与验证闭环
只生成代码而不运行测试,会把验证工作留给开发者。让工作流包含编译、测试、静态检查或类型检查,有助于更早发现错误,也能减少后续追问。
用任务结果衡量质量
输出长度、响应速度和单次价格都值得关注,但它们不能代替任务完成率。一个更便宜的响应,如果增加了两轮调试,未必降低了总成本。
把重试当作可观测信号
重复请求不是单纯的使用习惯问题,也可能说明上下文构造、代码编辑、测试反馈或任务拆解存在缺陷。统计重试原因,比单纯限制输出长度更有行动价值。
采用时需要留意的边界
“完整任务成本”也不能被简化成一个单一数字。不同任务的复杂度差异很大:补全一行代码、修改跨模块接口和排查生产问题,不应使用同一套基准直接比较。
团队可以按任务类型建立基线,并同时记录质量指标。例如,先选择一组有明确测试结果的任务,比较不同工作流的首次通过率、重试次数和人工耗时,再观察单位完成任务成本是否下降。
最终目标不是让 AI 尽量少输出,而是让更少的工作被浪费在无效生成、重复解释和人工返工上。只要评价范围覆盖从需求理解到验证交付的完整过程,成本与质量就不必被看成一对只能二选一的指标。