降低成本少花钱,模型调用量砍掉90%:缓存、分级、精简、批处理、流式,5个坑我全踩了一遍

先说数字,再讲坑。

日均调用 1,000 → 100,Token 消耗降 87%,P95 延迟从 8.2s 降到 1.4s,月账单从 4,832 降到 461。

做了五件事:缓存、模型分级、Prompt 精简、批处理、流式输出。

听着都是常规操作,但每个都踩了坑。这篇主要讲坑,代码放最后。


坑一:语义缓存的阈值,抄来的都是错的

网上讲语义缓存的文章,阈值清一色写 0.95。我一开始也是这么设的,跑了三天,命中率 41%,看着挺好。

然后客服反馈来了:用户问"写个快速排序",返回的是归并排序的代码。

我以为是模型抽风,查了日志才发现是缓存命中------两条 query 的 embedding 相似度 0.951,超过阈值,直接返回了缓存。

问题在于,0.95 这个数字跟你的业务无关。它是别人在自己数据上标定出来的,你抄过来就是赌博。

正确的做法是拿自己的数据标:

复制代码

我们的标定结果:

阈值 准确率 召回率
0.90 91.2% 67%
0.92 93.5% 58%
0.95 98.6% 41%
0.97 99.4% 28%

最后选 0.95。不是因为准确率高,是因为缓存的错误代价远大于未命中的代价。未命中无非多花点钱,命中错误是直接给用户错误答案。

这个道理跟 CDN 缓存不一样。CDN 缓存错了顶多内容旧一点,LLM 缓存错了是逻辑错误。

还有一点:TTL 一定要分级。我们一开始没设过期,公司改了报销制度,缓存还在返回旧答案,被财务找上门。现在制度类 7 天,操作类 30 天,实时数据不缓存。


坑二:模型分级,规则顺序能坑死人

我们 60% 的请求是意图分类、实体抽取、格式转换这类简单任务,全切到 mini 上,成本直接砍一半。

切之前我做了 A/B,抽 100 条对比两个模型的输出。人工看下来差异率 2% 左右,觉得没问题,上了。

上线一周,投诉集中在"代码生成"上。

我纳闷,代码生成明明没切啊。查日志才发现,问题出在分类器上。

有个需求是"帮我写个函数,把这段文本里的订单号提取出来",规则匹配到了 写.*函数,判成代码生成走 GPT-4o,没问题。

但另一个需求是"提取订单号并生成一个 JSON",规则先匹配到 提取.*订单,判成实体抽取走 mini,结果 mini 输出的 JSON 格式有问题,少了一层嵌套。

规则匹配是有顺序的,先匹配到的赢。 我的规则表里 entity_extract 排在 code_generation 前面,导致复合任务被误判。

改成按"任务复杂度"排序,复杂的规则优先:

改完之后差异率降到 0.8%。

教训:规则分类器看起来简单,但顺序设计是个真问题。要么按复杂度排,要么用打分制而不是首个匹配。

还有一个:max_tokens 也要跟着分级。很多团队只改模型不改输出上限,结果模型便宜了但输出还是那么长,省不了多少。意图分类的输出根本不需要 4096 token,128 够用。


坑三:Prompt 精简,删掉了一条安全指令

这条最不该犯。

我们的 prompt 模板里有这么一段:

复制代码
你是客服助手。回答用户关于产品的问题。
不得提供医疗、法律、投资方面的专业建议。
不确定时如实说明。

精简的时候,我判断"不得提供医疗建议"跟我们产品无关(我们是做企业协作工具的),删了。

测试环境跑了两天没事。上线第三天,有用户问"我最近头疼,你们这个软件能不能帮我记录症状",模型真的开始给建议了,还说"建议服用布洛芬"。

虽然最后没出事,但这是个严重问题。

Prompt 精简的边界在哪?

我的判断标准现在是:涉及"不能做什么"的指令,一律不删。 不管看起来多无关。

因为模型不知道你的业务边界在哪,它只知道 prompt 里写了什么。你觉得无关,是因为你懂业务;模型不懂。

现在我们的精简规则是:

  • 删:重复礼貌用语、空洞修饰词、冗余 few-shot
  • 保留:所有否定式指令(不得、禁止、避免)、所有格式要求、所有拒答逻辑
  • 加强:把保留的否定式指令移到 prompt 最前面

顺带说下精简的量:系统提示词从平均 420 token 压到 130 token,这一项单独贡献了约 12% 的成本下降。改一次永久生效,性价比最高。


坑四:批处理,不是所有任务都能批

Batch API 价格减半,看着很香。我们一开始把能批的都批了,包括一些"看起来是离线"的任务。

结果出问题了:有个功能是用户上传文档后生成摘要,我们判断这是异步任务,走了批处理。但用户上传完就在页面上等着,24 小时内出结果等于不可用。

判断能不能批,标准不是"是不是异步",是"结果晚 24 小时出来,业务能不能接受"。

我们的实际分类:

任务 能否批处理 原因
夜间文档摘要 能 用户第二天才看
商品批量打标签 能 后台任务,无用户等待
历史对话质检 能 周报用,不急
用户上传文档摘要 不能 用户在页面上等
客服实时回复 不能 秒级响应
合同条款提取 不能 用户等结果

真正能批的只占 30% 左右,但省下来的钱是实打实的。

还有个更划算的做法:把多次调用合成一次。

我们有个合同字段提取的需求,20 个字段,之前调 20 次。改成一次让它输出 JSON:

复制代码

调用次数降到 1/20,准确率反而更高------因为模型能看到全局上下文,不会出现字段之间矛盾的情况。


坑五:流式输出,省的不是 token

流式输出本身不省 token,一分钱都不省。

但它解决了一个隐藏成本:用户等不及刷新页面导致的重复请求。

我们之前非流式调用,P95 延迟 8.2 秒。日志里能看到大量这样的记录:同一个 user_id,同一个 prompt,间隔 3-5 秒连续发两次、三次。

用户等 3 秒没反应,以为卡了,刷新页面,前端重新发请求。

改成流式之后,首 token 时间 0.8 秒,用户能立刻看到内容在往外蹦,没人刷新了。重复请求从 8% 降到 0.3%。

复制代码

关键在 finally 里 close。用户关掉页面,生成立刻停,不再继续烧 token。

顺带一提,流式还能配合 max_tokens 做提前截断。有些场景用户根本看不完长回答,设个上限既省钱又提升体验。


两个没做成的尝试

尝试一:把 temperature 调到 0 提升缓存命中率。

想法是让输出确定,同样输入必然同样输出。实际效果一般,因为我们本来 temperature 就设的 0.3,调到 0 之后回答变得很死板,用户投诉变多,又调回去了。而且命中率只从 34% 涨到 37%。

尝试二:自建小模型替代部分调用。

部署了个 7B 的模型处理意图分类,理论上能省更多。实际跑下来,准确率比 mini 低 6 个点,而且 GPU 成本加上运维人力,算总账并不划算。最后放弃了,还是用 API。

API 的规模效应不是自建能比的。除非你的调用量大到能摊薄 GPU 成本,否则别折腾。


完整代码

五件事的实现,整合成一个模块:

复制代码

最后

五件事的贡献度:

动作 降幅 难度
缓存(精确+语义) 35% 中
模型分级 28% 低
Prompt 精简 12% 低
批处理 8% 中
流式输出 4% 低

有重叠,实际总降幅 90.5%。

说个反直觉的:这五件事里,没有一件是"换个更便宜的模型"。

我见过太多团队,成本高了第一反应是换模型。换一圈下来,账单没降多少,效果还掉了。

真正的大头在架构层面。我们那次梳理,1,000 次调用里 190 多次是前端重复触发的,120 多次是缓存该拦住没拦住的,70 多次是参数错误。光这三类就占 38%。

先看清楚钱花在哪,再想怎么省。顺序反了,白忙。


所有代码都在生产环境跑过,参数按我们业务调的,你用的时候记得拿自己数据重新标定。

相关推荐
玩泥巴的2 小时前
MAF + 飞书:让大模型干活,但别让它乱干
ai·c#·.net·飞书·agent
桃西西呀2 小时前
我把网关限流配置成每秒 100 请求,大促一来照样被打挂,还把别人也拖垮了
人工智能·llm·ai编程
武子康2 小时前
Agent 偏好记忆怎样确认写入:范围、版本与撤销的一个最小例
人工智能·后端·agent
王中阳Go3 小时前
质保期第 90 天我翻了一遍日志目录:交付后真正会坏的 3 处
人工智能·后端·agent
桃西西呀3 小时前
我把整本接口文档塞进 system prompt,前 3 轮答得准,第 8 轮开始胡说,账单还翻了 4 倍
人工智能·llm·ai编程
sbjdhjd5 小时前
从签名重放到 Agent Harness:一堂安全课程如何把前端逆向、MCP 与工程约束串起来
网络安全·ai·github·agent·webshell·mcp·harness
用户837133200765 小时前
感觉终于把复杂的 RAG 技术整理明白了
人工智能·llm
Points5 小时前
我用 Codex 从零做了一个 Agent:让大模型的运行过程看得见、查得清
agent
自养Agent5 小时前
Agent Harness 从用到会造:Skill 不是一次 API 调用,是一段会复用的行为
人工智能·llm