No.375
降低大模型调用成本有哪些办法?
一句话回答
先测量钱花在哪,再对症下手。主要手段有:按任务难度把请求路由到不同大小的模型;缓存(相同请求的响应缓存、语义缓存、提示缓存);精简上下文(压缩历史、只放相关的检索片段、精简工具定义);限制输出长度;离线任务用批处理接口;减少不必要的重试;按用户设置配额并监控异常消耗。每项改动都要用评测集确认效果没有明显下降。
详细解析
先测量
成本 = 调用次数 × 每次的 token 数 × 单价,三项都可以优化。先按功能、用户、模型统计用量,再把输入拆开,看系统提示、历史消息、检索内容、工具定义各占多少(估算方法见一次调用的成本怎么估算)。
手段一览
| 手段 | 做法 | 代价和风险 |
|---|---|---|
| 模型路由 | 简单任务(分类、抽取、改写)用小模型,复杂推理用大模型;或者先用小模型,校验不通过再升级 | 路由判断错误会影响效果;升级时等于付了两次钱 |
| 响应缓存 | 完全相同的请求(归一化后算哈希)直接返回缓存的结果 | 只适合答案稳定、与用户无关的请求 |
| 语义缓存 | 意思相近的问题复用答案(见语义缓存) | 可能答非所问,要控制阈值和适用范围 |
| 提示缓存 | 固定前缀放在最前面,命中后输入按折扣价计算(见 Prompt Caching) | 要调整 Prompt 的组织方式 |
| 精简上下文 | 历史消息截断和摘要;检索结果重排后只取最相关的几条;按场景只提供需要的工具 | 删多了会丢信息 |
| 限制输出 | 设置 max_tokens;Prompt 里要求简洁;用结构化输出代替长篇说明 |
被截断的回答不完整,要检查结束原因 |
| 批处理接口 | 评测、数据标注、批量总结等离线任务,用供应商的批处理接口,通常有折扣 | 不保证实时返回 |
| 减少重试 | 只重试可恢复的错误;格式问题优先在本地修复,而不是整段重新生成 | 本地修复的规则要维护 |
| 配额和监控 | 按用户、租户设置每日 token 配额;用量突增时告警 | 配额太紧会影响正常用户 |
模型路由的几种方式
- 规则:按功能固定。意图分类用小模型,写代码用大模型。简单可靠,但覆盖不了同一个功能内部的难度差异
- 分类器:先用小模型或分类模型判断难度,再选择模型。分类本身也有成本,也会误判
- 级联:先让小模型回答,用规则或校验判断结果是否可用(JSON 是否合法、是否回答了"不知道"),不可用再交给大模型。适合结果能自动校验的任务
防止异常消耗
- 接口必须鉴权,Key 不能出现在前端代码里(见 API Key 怎么安全管理)
- 单次请求限制输入长度和
max_tokens;Agent 限制最大步数 - 按用户、租户做配额和限流;按小时监控用量,突增时告警,必要时自动熔断
代码示例
级联:先用小模型,校验不通过再交给大模型(llm.chat 是通用写法,各家 SDK 不同):
JavaScript
import { z } from 'zod'
const Invoice = z.object({
number: z.string(),
amount: z.number(),
date: z.string(),
})
async function extractInvoice(text) {
for (const model of [SMALL_MODEL, LARGE_MODEL]) {
const res = await llm.chat({
model,
messages: [
{ role: 'system', content: '从发票文本中提取 number、amount、date,只输出 JSON。' },
{ role: 'user', content: text },
],
maxTokens: 300, // 输出本来就短,限制上限防止跑偏时浪费
})
const parsed = Invoice.safeParse(tryParseJson(res.content))
if (parsed.success) return parsed.data // 小模型成功就到此为止;记录各模型的通过率
}
throw new Error('提取失败,转人工处理')
}
function tryParseJson(text) {
try {
return JSON.parse(text)
} catch {
return null
}
}
面试官可能追问
降本会不会影响效果?怎么确认?
有风险,所以每项改动都要验证:换小模型、删减上下文、限制输出之后,用固定的评测集跑一遍,对比新旧版本的得分,重点看变差的样本(见改了 Prompt 或换了模型怎么做回归测试)。上线后再看业务指标,比如用户点踩和重试有没有增加。
级联方案什么时候反而更贵?
小模型的失败率高的时候:失败的请求要付两次钱,延迟也叠加了两次。级联划算的前提是大部分请求小模型就能搞定,而且结果能可靠地自动校验。要统计小模型的通过率:通过率低,就直接用大模型,或者改用分类器路由。
怎么发现有人在刷接口?
看用量分布:单个用户或 IP 的调用量、token 消耗明显高于正常用户;请求内容高度重复,或者是明显的批量模式;在深夜等非高峰时段持续大量调用。配合每个用户的配额和限流,发现异常时自动降级或封禁,并通知人工核查。
易错点
- 没有测量就动手,花大力气优化了只占一小部分的成本
- 只盯着单价,忽略了调用次数:去掉一次多余的模型调用,可能比换模型省得更多
- 限制了
max_tokens却不检查结束原因,被截断的 JSON 或回答被当成了完整结果 - 缓存了和用户相关的回答,把 A 的数据返回给了 B
AI 模拟面试官
用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮
登录后就可以和 AI 面试官对练,面试记录也会保存下来。登录
这道题你掌握了吗?
选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。
学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。