背景:为什么 100 万次调用会很容易失控?
很多团队第一次接 AI API 的时候,思路都差不多:先接上,能跑就行,后面再优化。结果往往也差不多:Demo 很顺,功能很酷,月底账单很吓人。
如果你的 AI 功能一个月调用 100 万次,哪怕单次只多花一点点,最后都会变成一笔很真实的钱。先说一个朴素事实:AI API 的成本,通常不是按请求次数收费,而是按 Token 收费。
你可以先粗暴理解成:
• 你发给模型的字 = 输入 Token
• 模型回给你的字 = 输出 Token 所以真正烧钱的,往往不是“用户问了多少次”,而是: • 每次请求带了多少无用上下文
• 输出是不是太长
• 同样的问题有没有重复请求
• 是否所有请求都用了最贵模型
• 是否做了缓存
说白了:成本爆炸,很多时候不是模型太贵,而是工程实现太粗糙。
一个典型架构: 前端 项目怎么接 AI 才不容易烧钱?
推荐结构:
Web App -> API Gateway / BFF -> Prompt Builder -> Cache Layer(Redis)-> Model Router -> LLM Provider
这一层级的核心意义是:前端只负责输入和展示,真正的成本控制放在服务端。因为只有服务端才能统一做缓存、模型分层、成本统计和请求熔断。 所以标准做法应该是:
| 前端 -> 你的 BFF / 网关 -> AI API |
|---|
| 别把模型当第三方 REST 接口瞎调,它更像一个高成本计算服务。 |
实战策略 1:先砍掉最没必要的请求
最容易烧钱的一类请求,不是复杂请求,而是高频误触发请求。比如搜索建议、输入联想、标题生成、Prompt 改写这类功能,如果不做防抖,用户输入一句话就可能触发十几次请求。 错误示例:
| inputEl.addEventListener('input', async (e) => { await fetch('/api/ai/suggest', { method: 'POST', body: JSON.stringify({ query: e.target.value }), }) }) |
|---|
| 正确示例: |
| function debounce(fn, delay = 500) { let timer = null return (...args) => { if (timer) clearTimeout(timer) timer = setTimeout(() => fn(...args), delay) } } |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 这一步看起来简单,但它会直接减少请求次数,对高频场景尤其值钱。 |
| 实战策略 2:做请求去重,别让同一个问题反复算 |
| 很多 AI 请求不是复杂,而是重复。尤其在 FAQ、内容总结、文案改写场景里,用户提的问题可能高度相似,甚至一模一样。这时候,最基础的一层就是请求指纹去重。 |
| 示例代码: |
| import crypto from 'node:crypto' export function createRequestFingerprint(input) { const normalized = JSON.stringify({ scene: input.scene, prompt: input.prompt.trim().toLowerCase(), model: input.model, temperature: input.temperature ?? 0, }) return crypto.createHash('sha256').update(normalized).digest('hex') } |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 这段代码的核心思路很简单:同一场景、同一请求、同一模型,就不要重新算。 |
实战策略 3:做语义 缓存 ,这是 AI 省钱王炸
普通缓存只能命中“完全相同”的请求。但 AI 场景里真正有价值的是:意思差不多,也尽量别重新算。FAQ、客服问答、规则解释、产品说明这类高重复场景特别适合做语义缓存。
适合优先做语义缓存的场景:
• FAQ
• 客服问答
• 规则解释
• 产品说明
• 高重复知识问答
实战策略 4:模型分层路由,不要“全员旗舰”
很多团队的默认逻辑是:这个模型效果最好,那就所有请求都给它。这不是优化,这是摆烂。更合理的做法是按场景分层:分类、改写、摘要用小模型;普通问答用中档模型;复杂推理和高价值请求再用强模型。
示例代码:
| function selectModel(scene, userTier) { if (scene === 'classify' || scene === 'rewrite' || scene === 'summary') { return 'cheap-model' } if (scene === 'qa' && userTier === 'free') { return 'mid-model' } if (scene === 'reasoning' || userTier === 'pro') { return 'strong-model' } return 'mid-model' } | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
核心思想就一句话:把贵的 Token 花在用户真的能感知价值的地方。
实战策略 5: Prompt 不要写成老太太的裹脚布
很多团队的 Prompt 越写越长,最后每次请求都背着几千 Token 上路。Prompt 优化不是文学创作,目标不是写得感人,而是让模型少吃点字。
• 少写废话
• 少堆规则
• 少放不必要 few-shot
• 历史上下文只保留必要部分
实战策略 6:限制输出长度,不要让模型说嗨了
很多时候,真正贵的不是输入,而是输出。你只想要一句结论,模型却给你写了一篇周报。控制输出长度,是最直接的降本动作之一。
代码示例:
| const response = await llm.chat.completions.create({ model: 'mid-model', messages, max_tokens: 300, temperature: 0.2, }) |
|---|
也可以直接在 Prompt 里限制:请用不超过 100 字回答;只输出 JSON,不要附加解释。
实战策略 7:流式输出时,一定要 支持 中断
很多前端做了流式输出体验,但忘了一个关键点:用户点了停止,前端停了,不代表后端和模型真的停了。如果后端没同步中断,上游模型还在继续生成,Token 也还在继续烧。
完整中断链路可以理解成:
| 用户点击停止 -> 前端 abort -> 服务端同步取消 -> 上游模型请求终止 -> Token 停止继续消耗 |
|---|
实战案例:月 100 万次调用,怎么从 100% 成本 打到最低?
假设一个 AI 产品的调用结构大概是这样:搜索建议 / 改写 / 标题生成占 35%,FAQ / 常见问答占 30%,文档总结占 20%,复杂推理 / 高价值任务占 15%。
一开始的常见做法通常是:全部走强模型,FAQ 每次重新生成,长文档整段直接喂模型,流式输出不做中断,也没有缓存。
改造后可以这样做:
• 搜索建议和标题生成改用小模型,前端加防抖
• FAQ 场景做缓存和语义缓存
• 长文档先切片,只把相关内容送给模型
•强模型只给复杂推理和高价值任务
• 输出长度统一限制
• 流式生成支持中断
真正省下来的,往往不是一两个参数,而是整条调用链被重新设计过了。
写在最后
很多人以为 AI API 成本优化是模型问题,其实大多数时候,它依然是工程问题。你熟悉的那套:缓存、去重、路由、限流、监控、分层设计,到了 AI 场景里照样成立。只不过以前你优化的是接口性能,现在你优化的是接口 + 钱包。
如果你们团队已经一周烧掉 1 亿 Token,别急着先换模型。先回头看看:有没有重复请求,有没有长 Prompt,有没有无脑上强模型,有没有缓存,有没有做流式中断,有没有做成本监控。这些地方,往往才是真正的省钱入口。