这是《LLM 应用开发 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 LLM 成本来自输入 token、输出 token、工具调用、检索和存储。成本优化的前提是不显著降低质量,并把预算、监控和限流纳入系统设计。
25.1 成本构成
总成本
= 模型输入 token
+ 模型输出 token
+ embedding
+ rerank
+ 向量存储
+ 工具和 API
+ 重试
+ 人工审核
常见问题:
- 历史消息无限累积;
- 检索上下文过长;
- 输出过度冗长;
- 重复问题没有缓存;
- 重试风暴;
- Agent 循环;
- 用大模型处理简单任务;
- 日志保存过多。
25.2 缓存层级
| 层 | 缓存对象 | 键 |
|---|---|---|
| 结果缓存 | 最终答案 | 规范化问题 + 权限 +版本 |
| 检索缓存 | chunk ID 和分数 | query + filter + index version |
| Embedding 缓存 | 查询向量 | text + model |
| 工具缓存 | 外部结果 | 参数 + 时间窗口 |
| 对象缓存 | 解析结果 | doc version |
缓存失效条件必须包含模型、Prompt、索引、策略和数据版本。
25.3 语义缓存
语义缓存用向量相似度判断问题是否相近。
Query
-> normalize
-> embedding
-> find similar cached question
-> threshold
|-- hit: return cached answer
+-- miss: run pipeline
风险:
- 相似问题条件不同;
- 时间敏感;
- 用户相关;
- 权限相关;
- 引用文档已更新。
适合缓存:
“如何修改登录密码?”
“公司的年假政策是什么?”
不适合缓存:
“我的订单什么时候到?”
“现在库存多少?”
“帮我总结这个文件。”
25.4 上下文压缩
def build_context(chunks, max_chars=12000):
parts = []
total = 0
for chunk in chunks:
text = f"[{chunk['id']}] {chunk['title']}\n{chunk['content']}"
if total + len(text) > max_chars:
break
parts.append(text)
total += len(text)
return "\n\n".join(parts)
压缩策略:
- 历史改摘要;
- 工具结果改摘要;
- 检索只保留 rerank 后片段;
- 表格保留必要列;
- 长文档分阶段处理;
- 引用正文按需读取。
25.5 输出控制
| 手段 | 示例 |
|---|---|
| max_tokens | 限制上限 |
| 格式约束 | JSON、要点 |
| 字数限制 | 不超过 200 字 |
| 拒答模板 | 固定话术 |
| 分段生成 | 先大纲后细节 |
| 缓存模板 | 常见答案 |
输出不能无限压缩。关键解释、引用和风险提示应保留。
25.6 模型分级
简单分类 -> 小模型 / 规则
普通问答 -> 中档模型
复杂推理 -> 高能力模型
低风险失败 -> 自动降级
路由判断:
- 任务类型;
- 输入长度;
- 风险等级;
- 用户价值;
- 历史成功率;
- 成本预算;
- 延迟要求。
不要让所有请求都走最强模型。
25.7 预算控制
class Budget:
def __init__(self, max_tokens=20000, max_money=0.20):
self.max_tokens = max_tokens
self.max_money = max_money
self.used_tokens = 0
self.used_money = 0.0
def spend(self, tokens=0, money=0.0):
self.used_tokens += tokens
self.used_money += money
if self.used_tokens > self.max_tokens or self.used_money > self.max_money:
raise RuntimeError("budget exceeded")
预算维度:
- 单请求;
- 单会话;
- 单任务;
- 单用户;
- 单租户;
- 全局服务;
- 每日成本。
25.8 成本观测
日志字段:
{
"trace_id": "t-1",
"model": "chat-mini",
"prompt_version": "v3",
"input_tokens": 2400,
"output_tokens": 180,
"cached_input_tokens": 1200,
"cost_usd": 0.0021,
"cache_hit": false,
"retry_count": 0
}
看板维度:
- 按业务场景;
- 按模型;
- 按租户;
- 按用户;
- 按成功失败;
- 按缓存命中;
- 按时间。
25.9 优化流程
统计成本分布
-> 找高成本低质量场景
-> 归因
-> 压缩 / 缓存 / 换模型
-> 评测
-> 灰度
-> 验证指标
避免只看单价,不看解决率。便宜但转人工率上升,总成本可能更高。
本章小结
成本控制要贯穿请求、上下文、输出、模型选择和重试。缓存必须绑定权限和版本,语义缓存要排除时间敏感和用户相关请求,所有优化都通过质量指标验证。
思考题
- 哪些问题不适合语义缓存?
- 上下文压缩会带来什么风险?
- 如何设计单任务预算?
- 模型降级时如何评估质量损失?
- 成本下降但转人工率上升说明什么?