📖 本章预览
本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。
第25章 性能优化:AI 响应从 3 秒压到 500 毫秒
本章基于 Spring AI 1.1.2,所有优化策略均可在生产环境落地
25.1 先搞清楚:AI 应用的延迟到底花在哪
25.1.1 一次 AI 请求的时间分解
用户发起请求到收到完整回复,时间花在这几个阶段:
┌──────────────────────────────────────────────────────────────────┐
│ 一次 AI 请求的时间线 │
├──────┬──────────┬──────────┬──────────────────┬─────────────────┤
│网络RTT│ Advisor链 │ RAG检索 │ LLM推理(主要瓶颈) │ 后处理+网络RTT │
│ ~5ms │ ~10ms │ ~50ms │ 500ms ~ 30s │ ~5ms │
└──────┴──────────┴──────────┴──────────────────┴─────────────────┘
关键发现:
1. LLM 推理占 90%+ 的时间 → 你优化代码层再多,也绕不开模型本身的速度
2. LLM 延迟 = TTFT + 生成时间
- TTFT(Time To First Token):模型吐出第一个字的时间,通常 200ms~2s
- 生成时间:和输出长度成正比,每个 Token 约 20~50ms
3. Token 数量直接影响延迟和成本 → 输入越长,推理越慢,花钱越多
25.1.2 优化策略全景图
性能优化策略
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
减少调用次数 减少单次延迟 提升用户体验
┌─────────┐ ┌──────────────┐ ┌──────────┐
│精确缓存 │ │Prompt精简 │ │流式响应 │
│语义缓存 │ │模型选择 │ │SSE推送 │
│批量合并 │ │并行化 │ │渐进渲染 │
└─────────┘ │异步非阻塞 │ └──────────┘
└──────────────┘
核心原则:
- 能不调模型就不调(缓存)
- 必须调就让它快(精简Prompt、选对模型)
- 快不了就让用户感觉快(流式响应)
25.2 缓存:最暴力也最有效的优化
25.2.1 精确缓存
原理:相同输入 → 相同输出。对 input 做 MD5 作为 key,命中直接返回,零延迟。适合 FAQ、固定查询等确定性场景。
/**
* 精确缓存(25.2.1节)
*
* 原理:input 的 MD5 作为 Redis key,命中直接返回
* 适用场景:FAQ、固定查询、确定性问答
* 命中率:取决于用户输入的重复度,FAQ 场景可达 60%+
*
* 注意:temperature > 0 时,相同输入可能产生不同输出
* 所以缓存更适合 temperature=0 的确定性场景
*/
@Service
public class ExactCacheService {
private final ChatClient chatClient;
private final StringRedisTemplate redisTemplate;
private static final Duration CACHE_TTL = Duration.ofHours(1);
public ExactCacheService(ChatClient.Builder builder, StringRedisTemplate redisTemplate) {
this.chatClient = builder.build();
this.redisTemplate = redisTemplate;
}
public String cachedChat(String input) {
// 1. 查缓存(O(1),亚毫秒级)
String cacheKey = "ai:cache:" + DigestUtils.md5Hex(input);
String cached = redisTemplate.opsForValue().get(cacheKey);
if (cached != null && !cached.isBlank()) {
return cached;
}
// 2. 未命中,调用模型(500ms~10s)
String result = chatClient.prompt().user(input).call().content();
// 3. 写入缓存
redisTemplate.opsForValue().set(cacheKey, result, CACHE_TTL);
return result;
}
}
25.2.2 语义缓存
原理:用户不会每次都用完全相同的措辞。"北京天气怎么样"和"北京今天天气如何"语义相同,应该命中同一缓存。做法是把问题向量化后在向量库中检索,相似度超过阈值就算命中。
/**
🔒 解锁完整内容
本章剩余内容需要解锁后查看
以上仅为本章部分预览内容,完整内容包含更多深度源码解析、实战代码和面试要点。
加入知识星球你将获得:
- ✅ 全部 26 章完整内容 + 持续更新
- ✅ 配套源码 + 实战项目
- ✅ 一对一答疑 + 面试辅导
- ✅ 简历优化 + 内推机会
📚 本章完整目录
以下为本章完整目录结构,加入知识星球即可解锁全部内容。