把大模型接进业务后,第一道现实暴击往往是账单:GPU 时长按小时计费、显存按卡计费、上下文越长越贵。很多人以为 大模型推理成本 只能靠“换更便宜的模型和更少调用”来降,其实服务侧的优化空间同样巨大。本文从吞吐、缓存、模型路由到量化,给出一套可落地的 降本 思路,配合 大模型 RAG 进阶:混合检索与重排序优化实战、本地大模型量化部署:GGUF 与 llama.cpp 调优 的既有实践,帮你把同样的预算服务更多流量。
一、成本到底花在哪:先算清这笔账
优化前先拆解。一次推理的花费主要由四块构成:GPU 算力时长(最贵)、显存占用(决定能开多少并发)、输入/输出 token 数(长上下文是隐形杀手)、以及调用频次。很多团队只盯着“模型单价”,却忽略了“一张卡大部分时间在空转等 I/O”——后者才是吞吐优化的主战场。
| 成本项 | 放大因素 | 优化抓手 |
|---|---|---|
| GPU 算力时长 | 低并发、空隙多 | 连续批处理、提升利用率 |
| 显存占用 | 长上下文、K/V 缓存大 | KV Cache 量化、上下文裁剪 |
| Token 数 | 啰嗦 prompt、长输出 | 提示词压缩、输出长度上限 |
| 调用频次 | 重复问题反复推理 | 语义缓存、模型路由 |
二、吞吐优化:让一张卡服务更多人
传统“来一个请求跑完再接下一个”的调度,GPU 在解码每一步都在等前一个请求的尾段,利用率可能只有 30%。连续批处理(continuous batching)的做法是:每个解码步都从等待中的请求里重新凑一批一起前向,哪个先结束就先 freeing 它的显存,新请求随时插入。vLLM、TGI 等推理框架的核心卖点正是这个。
# 伪代码:连续批处理(continuous batching)的核心循环
while True:
# 不再等一个请求跑完才接下一个,
# 而是每个解码步都从“等待中的请求”里凑一批
batch = scheduler.pick_waiting_requests(max_tokens_budget=8192)
if not batch:
continue
logits = model.forward(batch) # 一次前向,服务整批
for req in batch:
if req.is_finished(logits[req]):
scheduler.free(req)
else:
scheduler.append_token(req, logits[req])
效果立竿见影:在对话场景里,连续批处理常把吞吐提升 2–5 倍,相当于同样的卡多服务几倍流量,单位请求成本同比例下降。这与 MCP 与 A2A:2026 AI Agent 协议选型指南 强调的“把 Agent 编排开销压到最低”是同一个工程直觉——少空转、多复用。
三、语义缓存:砍掉重复推理
线上流量里“相似问题”极多:同一份文档的问答、同一类售后话术、同一段代码的解释。如果每次都真去调大模型,是纯粹的浪费。语义缓存的思路是:把问题的向量化表示存起来,新问题的 embedding 与历史命中(余弦相似度超过阈值)就直接复用历史答案,不再推理。
import hashlib, numpy as np
def semantic_cache_get(query_emb, cache, threshold=0.92):
# 用归一化余弦相似度判断“语义是否重复”
for item in cache:
sim = np.dot(query_emb, item["emb"]) / (
np.linalg.norm(query_emb) * np.linalg.norm(item["emb"]) + 1e-9)
if sim >= threshold:
return item["answer"] # 命中,直接复用历史推理结果
return None # 未命中,才真正调用大模型
注意阈值别定太高(>0.95 容易漏缓存)也别太低(<0.85 会把不同问题当相同)。命中率每提升 10 个百分点,推理量就实打实少 10%。对 FAQ、文档问答这类高重复场景,语义缓存往往是最快回本的优化。
四、模型路由:小事用小模型
不是每个请求都值得上 70B 旗舰模型。事实性短问答、分类、抽取这类“小事”,0.5B–8B 小模型就能做对,成本和延迟都低一个数量级。模型路由就是在大模型之前加一个轻量分类器,按复杂度把请求分发给不同档位的模型。
def route(question: str) -> str:
# 路由器:先判复杂度,小事交给小模型,大事才上大模型
if is_simple_fact(question) or len(question) < 20:
return "mini-model-0.5b" # 便宜、快
if needs_tool_call(question):
return "pro-model-70b" # 复杂推理/工具编排
return "mid-model-8b" # 常规对话
路由器的判断可以很简单:长度、是否要工具调用、是否涉及多步推理。经验上,30%–50% 的流量都能下沉到小模型,整体账单直接砍掉一大截。这也呼应 大模型工具调用:Function Calling 实战 里工具调用的分层思想——能确定性解决的,就别麻烦大模型。
五、上下文与量化:省显存也省钱
长上下文是成本的隐形放大器:KV Cache 随序列长度近似线性增长,一个 32K 的对话可能吃掉小模型整张卡的显存。对策有三:一是开启 KV Cache 量化(FP16→INT8/INT4),显存腰斩;二是上下文裁剪与摘要,把早期无关轮次压缩;三是对吞吐敏感的服务,直接采用 本地大模型量化部署:GGUF 与 llama.cpp 调优 提到的量化权重(GGUF/Q4),用更少显存跑同等效果。端侧与边缘场景更要把 端侧大模型部署实战:2026 边缘推理落地指南 的部署经验用上——把模型推到离用户更近的地方,省下的不只是显存,还有跨区带宽。
六、可观测:把每次调用的成本摊开
不度量就无法优化。建议给推理服务埋三类指标:单次请求的 token 数(输入/输出分别计)、端到端延迟与吞吐(req/s)、以及缓存命中率与模型路由分布。把它们做成看板,你才能回答“这周账单涨了是因为流量、上下文变长、还是路由失效”。很多团队降本失败,根因就是从来没把成本拆到单次调用这一层。
小结
大模型推理成本 不是只能靠“少调用”来降。服务侧四板斧——连续批处理提吞吐、语义缓存挡重复、模型路由分轻重、量化与上下文裁剪省显存——往往比换模型更立竿见影。落地顺序建议:先上可观测把账算清,再做语义缓存(回本最快),接着模型路由,最后才动批处理与量化这类底层改造。把这套组合拳打顺,同等预算服务 2–5 倍流量并不夸张。




