TLDR
GPTZero AI 检测模型 3.7b 判定本文完全为人类撰写。
大语言模型是大多数产品团队首次遇到的、每个请求都有可见边际成本的依赖项。这改变了规则:一个功能可能“工作正常”,但在生产环境中却因悄悄烧钱、重试导致费用激增,或提示词膨胀致使延迟和成本双双上升而失败。本文提供了一套实用蓝图,帮助在不将产品变成吝啬、低质量体验的前提下,保持 LLM 成本可预测。
将每次 LLM 调用视为计费依赖项
在多数服务中,依赖项消耗延迟和可靠性。LLM 每次请求还花费金钱,这意味着需要从第一天起就进行按路由的核算。
将每个 LLM 请求关联到具体路由,如 support_reply、doc_search、meeting_summary 或 policy_answer。记录模型、输入/输出令牌数、延迟、重试次数和预估成本。如果无法回答“哪个路由花了钱”,就无法控制成本。
成本不是财务工作,而是与错误率同级别的运营指标。
将令牌预算嵌入架构(而非电子表格)
预算必须存在于能够阻止失控行为的地方。
按路由定义:
- 最大输入令牌数(允许的上下文量)
- 最大输出令牌数(模型可回答的长度)
- 最大重试次数(尤其针对超时和 429 错误)
- 最大工具调用次数(若使用工具/函数调用)
预算同样保护质量。无限制的提示词往往因将信号淹没在过多“可能有用”的上下文中而降低相关性。
一个有用的思维模型:提示词就像一个打包好的行李箱,每件物品都需要有存在的理由。
通过更智能的检索控制上下文增长,而非塞入更多内容
一个常见的反模式是:“答案变差了,所以我们加了更多上下文。”这可能会增加成本但仍然失败,因为正确的证据并不存在,只是多了更多证据。
更好的模式是:
- 检索稍大的候选集
- 重排序以挑选最佳的几个片段
- 仅将最顶部的证据传递给生成步骤
这能保持令牌使用稳定并提高答案相关性,同时防止一种隐性的成本漂移:随着更多文档进入索引,上下文在数周内缓慢膨胀。
战略性缓存并衡量缓存命中率
缓存是最大的成本杠杆之一,且无需牺牲质量——但前提是缓存正确的层级并使用正确的键。
三种实用的缓存:
- 重复查询的检索结果(短 TTL)
- 重复文本的嵌入向量(长 TTL)
- 确定性路由的最终答案(短 TTL,严格键)
键的设计很重要。在缓存键中包含提示词模板版本、模型名称以及任何文档索引版本。否则可能返回为昨天的提示词或上周的索引生成的答案。
并且按路由使缓存命中率可见。如果命中率接近零,就是在为毫无收益的复杂性付出代价。
请求路由:并非每个任务都值得用同一个模型
对每个路由都使用同一个昂贵模型,是成本失控的最快途径之一。
按任务难度和风险路由:
- 分类/提取通常可在较小模型上完成
- 摘要通常可以比开放式推理更便宜
- 高风险路由可以证明更强模型加更严格护栏的合理性
也可以按证据强度路由。如果检索置信度低,更好的用户体验往往是提出澄清性问题,而非升级到更昂贵的模型去更华丽地产生幻觉。
设计保留信任的降级策略(而不仅仅是保住预算)
降低体验的成本控制措施会被绕过。目标是在保持支出可预测的同时保留信任。
好的降级策略包括:
- 当证据较弱时提出澄清性问题
- 生成简短的、带引用的答案而非长篇叙述
- 返回提取的段落而非生成的解释
- 在速率限制下优雅降级(排队、部分响应,或“请缩小查询范围后重试”)
最好的降级不是错误,而是安全的、部分有用的响应。
实施按路由预算并记录成本
以下是一个可适配到大多数技术栈的小模式:在运行时强制执行预算,并发出结构化使用日志用于仪表盘和告警。
PRICING = {
"small": {"in_per_1k": 0.0002, "out_per_1k": 0.0008},
"large": {"in_per_1k": 0.0025, "out_per_1k": 0.0100},
}
ROUTE_BUDGETS = {
"support_reply": {"tier": "small", "max_in": 2000, "max_out": 250, "max_retries": 1},
"policy_answer": {"tier": "large", "max_in": 3500, "max_out": 350, "max_retries": 2},
"meeting_summary": {"tier": "small", "max_in": 4000, "max_out": 300, "max_retries": 1},
}
def est_cost(tier, tokens_in, tokens_out):
p = PRICING[tier]
return (tokens_in/1000)*p["in_per_1k"] + (tokens_out/1000)*p["out_per_1k"]
def run_llm(route, llm_call, tokens_in_estimate):
b = ROUTE_BUDGETS[route]
if tokens_in_estimate > b["max_in"]:
return {"text": "上下文过多。请缩小请求范围。", "blocked": True}
# llm_call 应返回来自提供商的 tokens_in/tokens_out
resp = llm_call(tier=b["tier"], max_tokens=b["max_out"], max_retries=b["max_retries"])
cost = est_cost(b["tier"], resp["tokens_in"], resp["tokens_out"])
print({
"event": "llm_usage",
"route": route,
"tier": b["tier"],
"tokens_in": resp["tokens_in"],
"tokens_out": resp["tokens_out"],
"cost_est_usd": round(cost, 6),
})
return {"text": resp["text"], "blocked": False}
即使初始定价估算很粗糙,也能立即获得两样东西:防止明显的提示词失控,并创建可供分析的成本历史记录。
结语:预算是产品功能
如果推出 LLM 功能时没有预算,推出的不是一个功能,而是一个无上限的成本中心。
预算强制澄清:哪些证据重要、什么答案格式可接受、以及系统在不确定性下如何表现。其回报不仅是降低支出,更是得到一个更易操作、更易调试、更值得信赖的系统。FINISHED