为什么需要缓存?
用户问"今天天气怎么样",Agent调用天气API。十分钟后,另一个用户问同样的问题。再调一次API?浪费钱、浪费时间。缓存就是答案:记住之前的答案,下次直接用。
💰 成本对比:
- 无缓存:每次请求$0.01 API费用 + 2秒延迟
- 有缓存:直接返回,$0费用 + 50ms延迟
- 节省:90%成本、95%延迟
四种缓存类型
1. 精确缓存(Exact Cache)
完全相同的请求直接返回缓存结果:
agent.setCache({
type: 'exact',
enabled: true,
// 缓存键生成
keyGenerator: (request) => {
return `${request.model}:${hash(request.prompt)}`;
},
// 缓存配置
ttl: 3600, // 1小时过期
maxSize: 1000, // 最大1000条
storage: 'memory' // 或 'redis', 'file'
});
2. 语义缓存(Semantic Cache)
语义相近的请求也能命中缓存:
agent.setCache({
type: 'semantic',
enabled: true,
// 语义相似度阈值
similarityThreshold: 0.95, // 95%相似即认为相同
// 嵌入模型配置
embeddingModel: 'text-embedding-3-small',
embeddingDimensions: 512,
// 向量存储
vectorStore: {
type: 'pinecone', // 或 'chroma', 'milvus'
index: 'agent-cache'
}
});
💡 语义缓存示例:
- "北京天气怎么样" → 缓存命中
- "北京现在天气如何" → 缓存命中(语义相近)
- "上海天气怎么样" → 缓存未命中
3. 工具结果缓存
缓存工具执行结果,避免重复调用外部API:
agent.setToolCache({
enabled: true,
// 按工具配置缓存策略
policies: {
'get_weather': {
ttl: 1800, // 30分钟(天气变化快)
cacheable: true
},
'get_stock_price': {
ttl: 60, // 1分钟(股价变化更快)
cacheable: true
},
'search_web': {
ttl: 86400, // 24小时(搜索结果相对稳定)
cacheable: true
},
'send_email': {
cacheable: false // 不缓存
}
}
});
4. 嵌入缓存
缓存文本嵌入向量,避免重复调用嵌入API:
agent.setEmbeddingCache({
enabled: true,
storage: 'redis',
ttl: 7 * 24 * 3600, // 7天
// 嵌入缓存键
keyGenerator: (text, model) => {
return `embed:${model}:${hash(text)}`;
}
});
缓存策略选择
| 场景 | 推荐缓存 | TTL建议 |
|---|---|---|
| FAQ问答 | 精确缓存 | 24小时+ |
| 知识查询 | 语义缓存 | 12小时 |
| 实时数据 | 工具缓存(短TTL) | 1-5分钟 |
| 个性化回复 | 不缓存 | - |
缓存失效策略
时间失效(TTL)
// 按数据类型设置不同TTL
const ttlConfig = {
'static_data': 86400, // 静态数据24小时
'dynamic_data': 300, // 动态数据5分钟
'user_specific': 0 // 用户特定数据不缓存
};
主动失效
// 数据更新时主动清除缓存
agent.on('data_updated', (dataKey) => {
cache.invalidateByTag(dataKey);
});
// 用户反馈错误时清除
agent.on('feedback_negative', (responseId) => {
cache.invalidate(responseId);
});
LRU淘汰
agent.setCache({
maxSize: 10000, // 最大10000条
evictionPolicy: 'LRU', // 最近最少使用淘汰
// 内存阈值淘汰
memoryThreshold: '500MB',
onEviction: (key, reason) => {
console.log(`缓存淘汰: ${key}, 原因: ${reason}`);
}
});
缓存穿透与雪崩防护
防止缓存穿透
⚠️ 穿透问题:大量不存在的缓存键导致请求全部穿透到后端API。
agent.setCache({
// 空结果也缓存
cacheNullResults: true,
nullTTL: 60, // 空结果缓存60秒
// 布隆过滤器
bloomFilter: {
enabled: true,
expectedItems: 100000,
falsePositiveRate: 0.01
}
});
防止缓存雪崩
agent.setCache({
// TTL随机偏移
ttlJitter: {
enabled: true,
range: 0.1 // TTL ±10%随机
},
// 请求合并
requestCoalescing: {
enabled: true,
window: 100 // 100ms内的相同请求合并为一个
}
});
缓存监控
命中率监控
agent.monitorCache({
metrics: ['hit_rate', 'miss_rate', 'eviction_rate'],
// 告警阈值
alerts: {
hitRateBelow: 0.5, // 命中率低于50%告警
missRateAbove: 0.3 // 未命中率高于30%告警
},
// 实时统计
onMetrics: (stats) => {
console.log(`缓存命中率: ${stats.hitRate * 100}%`);
console.log(`平均响应时间: ${stats.avgLatency}ms`);
console.log(`成本节省: $${stats.costSaved}`);
}
});
最佳实践
- ✅ 根据数据特性设置合理的TTL
- ✅ 使用语义缓存处理相似请求
- ✅ 工具结果缓存要区分可变性
- ✅ 监控命中率并持续优化
- ✅ 防止穿透和雪崩问题
- ✅ 用户隐私数据不缓存
- ✅ 设置合理的缓存大小上限
常见问题
Q: 缓存会不会影响个性化?
会的。对于个性化回复,应该禁用缓存或使用用户ID作为缓存键的一部分。
Q: 语义缓存准确吗?
设置95%相似度阈值时,准确率通常在90%以上。可以根据业务需求调整阈值。
Q: 缓存存储选内存还是Redis?
单机小规模用内存,分布式大规模用Redis。语义缓存建议用专业向量数据库。