语义缓存 (Semantic Cache)
一、什么是语义缓存?
语义缓存利用向量相似性搜索,对 AI 响应进行智能缓存。即使两次请求的文字表述不完全相同,只要语义相似,就能直接返回缓存结果,从而大幅降低重复调用大模型的成本和延迟。
四大核心优势
- 降低成本:避免为相似请求重复调用昂贵的 LLM API
- 性能提升:亚毫秒级缓存读取 vs. 秒级 API 调用
- 智能匹配:超越精确文本匹配,实现语义相似识别
- 流式支持:完整支持流式响应的缓存与顺序还原
二、核心机制:双层缓存 (Dual-Layer Caching)
语义缓存包含两种匹配策略:
| 模式 | 机制 | 说明 |
|---|---|---|
| 直接哈希模式 (Exact Hash) | 对请求内容计算确定性哈希 | 完全相同请求 → 立即命中,最快速度,无需嵌入模型 |
| 语义相似模式 (Semantic) | 生成向量嵌入进行相似度搜索 | 文字不同但语义相近 → 命中缓存,需配置嵌入模型 |
默认行为:先尝试直接哈希匹配,若未命中则回退到语义相似搜索。
三、必须的组件:向量数据库 (Vector Store)
语义缓存必须配置向量数据库作为存储后端。支持的类型包括:
- Weaviate (生产级 gRPC 支持)
- Redis / Valkey (高性能内存存储,推荐用于纯哈希模式)
- Qdrant (Rust 编写,支持高级过滤)
- Pinecone (托管服务,支持 Serverless)
关键代码:初始化向量存储 (以 Weaviate 为例)
go
import (
"context"
"github.com/maximhq/bifrost/framework/vectorstore"
)
vectorConfig := &vectorstore.Config{
Enabled: true,
Type: vectorstore.VectorStoreTypeWeaviate,
Config: vectorstore.WeaviateConfig{
Scheme: "http",
Host: "localhost:8080",
},
}
store, err := vectorstore.NewVectorStore(context.Background(), vectorConfig, logger)
if err != nil {
log.Fatal("Failed to create vector store:", err)
}四、核心配置:启用语义缓存
关键代码:创建并配置语义缓存插件 (Go SDK)
go
import (
"time"
"github.com/maximhq/bifrost/plugins/semanticcache"
"github.com/maximhq/bifrost/core/schemas"
)
cacheConfig := &semanticcache.Config{
// [Required] Embedding model config (if semantic matching is enabled)
Provider: schemas.OpenAI,
Keys: []schemas.Key{{Value: "sk-..."}},
EmbeddingModel: "text-embedding-3-small",
Dimension: 1536,
// Cache behavior config
TTL: 5 * time.Minute, // Cache TTL (time-to-live)
Threshold: 0.8, // Similarity threshold (default 0.8)
CleanUpOnShutdown: true, // Whether to clear the cache on shutdown
// Conversation handling config
ConversationHistoryThreshold: 5, // Skip caching when conversation message count exceeds this value (prevents false matches)
ExcludeSystemPrompt: bifrost.Ptr(false), // Whether to exclude the system prompt from the computation
// Advanced isolation options
CacheByModel: bifrost.Ptr(true), // Isolate cache by model
CacheByProvider: bifrost.Ptr(true), // Isolate cache by provider
}
plugin, err := semanticcache.Init(context.Background(), cacheConfig, logger, store)
if err != nil {
log.Fatal("Failed to create semantic cache plugin:", err)
}
// Add the plugin to the Bifrost master config
bifrostConfig := schemas.BifrostConfig{
LLMPlugins: []schemas.LLMPlugin{plugin},
// ... other config
}五、纯直接哈希模式 (无嵌入模型)
若不想调用任何嵌入 API(例如仅需精确去重、无外部网络环境),可启用纯哈希模式。
关键代码:纯直接哈希模式配置
go
cacheConfig := &semanticcache.Config{
// Do not provide Provider, Keys, or EmbeddingModel
Dimension: 1, // Placeholder value; no vectors are actually stored, only metadata
TTL: 5 * time.Minute,
CleanUpOnShutdown: true,
CacheByModel: bifrost.Ptr(true),
CacheByProvider: bifrost.Ptr(true),
}
plugin, err := semanticcache.Init(ctx, cacheConfig, logger, store)注意
纯哈希模式下仍需要向量数据库,推荐使用 Redis / Valkey(无需真实向量字段)。
六、必须触发的条件:设置缓存键 (Cache Key)
语义缓存仅在请求上下文中提供了缓存键时才会生效。无缓存键的请求将完全绕过缓存。
关键代码:在请求中注入缓存键
go
import "github.com/maximhq/bifrost/plugins/semanticcache"
// Set the cache key in the context; this request will be cached
ctx = context.WithValue(ctx, semanticcache.CacheKey, "session-123")
response, err := client.ChatCompletionRequest(schemas.NewBifrostContext(ctx, schemas.NoDeadline), request)
// A context without a cache key -> this request will not trigger caching
response, err := client.ChatCompletionRequest(schemas.NewBifrostContext(context.Background(), schemas.NoDeadline), request)七、高级控制选项
1. 单次请求动态覆盖 TTL 和阈值
go
ctx = context.WithValue(ctx, semanticcache.CacheKey, "session-123")
ctx = context.WithValue(ctx, semanticcache.CacheTTLKey, 30*time.Second)
ctx = context.WithValue(ctx, semanticcache.CacheThresholdKey, 0.9)2. 强制指定缓存类型 (仅双模式有效)
go
// Force direct-hash matching only
ctx = context.WithValue(ctx, semanticcache.CacheTypeKey, semanticcache.CacheTypeDirect)
// Force semantic-similarity matching only
ctx = context.WithValue(ctx, semanticcache.CacheTypeKey, semanticcache.CacheTypeSemantic)3. 禁止存储本次响应 (只读不写)
go
ctx = context.WithValue(ctx, semanticcache.CacheNoStoreKey, true)4. 手动清理缓存条目
go
// Delete a specific entry by request ID
err := plugin.ClearCacheForRequestID("550e8400-e29b-41d4-a716-446655440000")
// Delete all related entries by cache key
err := plugin.ClearCacheForKey("support-session-456")八、缓存命中后的调试信息
git 缓存命中后,响应对象的 ExtraFields.CacheDebug 字段会包含一个 JSON 对象,其中关键字段如下:
直接哈希命中
json
{
"cache_hit": true,
"hit_type": "direct",
"cache_id": "550e8500-e29b-41d4-a725-446655440001"
}语义相似命中
json
{
"cache_hit": true,
"hit_type": "semantic",
"cache_id": "550e8500-e29b-41d4-a725-446655440001",
"threshold": 0.8,
"similarity": 0.95,
"provider_used": "openai",
"model_used": "gpt-4o-mini",
"input_tokens": 100
}提示
利用 cache_id 可实现精确的缓存条目管理。
