主题
成本与延迟优化:让 AI 应用跑得起
本文是 AI 应用系统学习系列的 L3 实战篇。前置:34. RAG 全链路、35. Agent 系统:ReAct、工具与记忆。 学完可以配合面试题食用:27. 长上下文压缩、24. 模型蒸馏
为什么 AI 应用的成本和延迟是"隐形负债"
大模型 API 按 token 计费,一个常规 RAG 问答每次约 2000 token(输入)+ 500 token(输出)。如果每天 10 万次请求,仅 GPT-4o 级别的输入就花掉 60 美元/天。Agent 更夸张——一次多步决策可能消耗 5000+ token,而且每一步都翻倍累积上下文。
成本不是上线后才算的,从架构选型那天就决定了。
延迟同理。用户等 15 秒才看到输出流,再好的 RAG 效果也白搭。首 token 时间(TTFT)和生成速度(tok/s)是两个独立指标,需要分别优化。
成本结构:钱烧在哪三样东西上
1. Token 单价差异大
同一家模型的输入/输出 token 价格可以差 4 倍(DeepSeek-V2 输入 0.14 元/百万 token,输出 0.28 元/百万 token)。不同模型之间差距更大——Claude Sonnet 比 Haiku 贵 5 倍,GPT-4o 比 GPT-4o-mini 贵 20 倍。
容易忽略的: 缓存命中 token 价格通常只有常规的 10%。所以大量命中缓存的请求,成本可以压到原先的 1/10。
2. Agent 的 token 爆炸
一个 Agent 单轮对话包含:系统 prompt + 一路对话历史 + 工具描述 + 本轮思考 + 工具调用 + 工具返回。如果 Agent 循环 5 次,每次把之前的全部上下文带进去,第 5 轮的上下文可能已经是第 1 轮的 5-10 倍。
量化例子: 系统 prompt 2000 token,工具描述 1500 token,每轮输入 500 token、输出 300 token、工具返回 800 token。5 轮后的输入 = 2000 + 1500 + 5 × (500 + 300 + 800) = 11500 token,是第 1 轮的 3.3 倍。
3. 输出 token 比输入贵
输出 token 定价通常是输入的 2-4 倍。所以不是"少让模型输出"就能省钱,而是减少不必要的输出长度——比如在指令里明确要求 100 字以内、不做无意义扩写。
降本五板斧:从易到难
第一板斧:模型分级路由
把请求按复杂度分到不同模型。简单分类-> 4o-mini,复杂推理-> GPT-4o,代码生成-> Claude Sonnet。路由层判断逻辑可以是:关键词匹配、Tiny 分类器、或者直接让一个廉价模型先判断"这个问题要不要升级"。
下面是一个极简的 Python 网关示例:
python
from typing import Dict, Any
import json
class ModelRouter:
def __init__(self):
self.routes = [
# 优先级从高到低,匹配第一个就返回
("code_gen", self._is_code_gen, "claude-sonnet-4"),
("complex_reasoning", self._is_complex, "gpt-4o"),
("simple_qa", self._is_simple, "gpt-4o-mini"),
]
self.default = "gpt-4o-mini"
def route(self, messages: list) -> str:
for name, matcher, model in self.routes:
if matcher(messages):
return model
return self.default
def _is_simple(self, msgs: list) -> bool:
# 最后一条用户消息短于 50 字且不包含"代码"时认为是简单问题
last = msgs[-1]["content"]
return len(last) < 50 and "代码" not in last
def _is_code_gen(self, msgs: list) -> bool:
last = msgs[-1]["content"]
return "代码" in last or "实现" in last
def _is_complex(self, msgs: list) -> bool:
last = msgs[-1]["content"]
return len(last) > 200 or "为什么" in last
# 成本打点:每次路由记录到数据库
# cost_logs 表结构见下方成本打点表结构(MySQL):
sql
CREATE TABLE cost_logs (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
request_id VARCHAR(64) NOT NULL,
model VARCHAR(64) NOT NULL,
input_tokens INT NOT NULL,
output_tokens INT NOT NULL,
cache_hit_tokens INT DEFAULT 0,
cost_usd DECIMAL(10,6) NOT NULL,
latency_ms INT NOT NULL,
route_name VARCHAR(32),
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_date (created_at),
INDEX idx_model (model)
);第二板斧:Prompt 压缩
把用户输入的冗余内容去掉。比如 RAG 里检索出来的 10 个 chunk,可能只有 3 个有用。在送入 LLM 前做一次相关性过滤——用 embedding 相似度或者一个轻量模型打分,去掉低于阈值的 chunk。
第三板斧:缓存
三种缓存粒度:
- 精确缓存:完全一样的 prompt 直接命中,成本 0,延迟 < 10ms
- 前缀缓存:长 prompt 的前面部分(系统指令、工具描述)被缓存,输入 token 只付 10%
- 语义缓存:相似问题命中同一份答案,适合 FAQ 场景。需要 embedding 相似度阈值,精度与召回需要调
第四板斧:批处理
异步任务(批量翻译、文档处理)可以等一批请求攒够再一起送。模型 API 对 batch 请求通常有 50% 折扣,延迟从 1 秒变成 10 分钟,但成本砍半。
第五板斧:蒸馏
用大模型生成 10 万条高质量问答对,训练一个小模型(如 7B -> 1.5B)来替代大模型做简单推理。蒸馏是一次性投入,换取长期输出成本降到 1/5。
延迟拆解:TTFT 和生成速度是两回事
TTFT(Time to First Token):从发送请求到收到第一个 token 的时间。主要由网络、模型 Prefill(处理输入 token)决定。优化手段:
- 流式输出(SSE):用户最早在 500ms 就看到第一个字,而不是等全量生成完
- 就近部署:把模型实例部署在与用户同区域,减少网络跳数
- KV Cache 复用:相同前缀的请求复用已有的 KV Cache,跳过 Prefill 阶段。比如系统 prompt 2000 token 可以直接命中缓存
生成速度(tok/s):从第一个 token 到最后一个 token 的速率。主要由模型大小、硬件、解码策略决定。优化手段:
- 并行工具调用:Agent 需要调 3 个工具时,让模型一次输出 3 个 function call,而不是轮询 3 次
- 投机采样(Speculative Decoding):用一个草稿模型先快速生成候选 token,大模型只需要验证,速度提升 2-3 倍
- 减少输出长度:指令里明确限制输出长度,不要等模型自己决定说多少
动手实操:模型分级路由的网关实现
上面已经给出了 ModelRouter 的 Python 代码和 cost_logs 表结构。把它接入生产环境的流程是:
- 每次调用前先
router.route(messages)拿到模型名 - 调用对应模型 API
- 调用后把 token 用量、模型名、延迟写入
cost_logs - 每天跑一个 SQL 统计:
SELECT model, SUM(ROUND(cost_usd, 4)) AS daily_cost FROM cost_logs WHERE created_at >= CURDATE() GROUP BY model ORDER BY daily_cost DESC
做完这一步,你就能每天看到每个模型花了多少钱,哪类请求走了贵的模型——然后优化路由规则,把不必要的"升级"砍掉。
常见误区与小结
- 误区 1:所有请求都用最强模型。80% 的请求其实不需要 GPT-4o 级别的能力,分级路由可以省 60% 以上成本,效果几乎不变
- 误区 2:只关注生成速度,忽略 TTFT。TTFT 决定了用户"感觉"上的第一次响应,TTFT > 3s 用户体验就很差,即使后续生成很快
- 误区 3:Agent 上下文满了就加轮次。每次 Agent 循环都翻倍上下文,成本指数增长。应该主动压缩或丢弃旧轮次
- 误区 4:缓存只看 Exact Match。前缀缓存和语义缓存能覆盖 60% 以上的重复请求,而 Exact Match 只能覆盖 10-20%
- 误区 5:优化完不看监控大盘。没有量化就不知道优化有没有效果。先建好
cost_logs表,再动手优化,每改一个规则看两天数据
小结:成本优化的核心是"量化 -> 分级 -> 缓存 -> 压缩 -> 蒸馏"五步走,每步都可以独立落地。延迟优化的核心是把 TTFT 和生成速度分开看待,各自用不同的手段。下一篇是最后一篇 38. 生产级 Agent 架构,把 LangGraph、MCP 和多 Agent 串起来,做一个完整的生产级 Agent 系统。
参考
参考:OpenAI Token 定价页、Anthropic 缓存文档、LangChain 批处理最佳实践