Skip to content

语义缓存 (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{
    // 【必填】嵌入模型配置 (若启用语义匹配)
    Provider:       schemas.OpenAI,
    Keys:          []schemas.Key{{Value: "sk-..."}},
    EmbeddingModel: "text-embedding-3-small",
    Dimension:     1536,
    
    // 缓存行为配置
    TTL:       5 * time.Minute,  // 缓存有效期
    Threshold: 0.8,              // 相似度阈值 (默认 0.8)
    CleanUpOnShutdown: true,     // 关闭时是否清空缓存
    
    // 对话处理配置
    ConversationHistoryThreshold: 5,        // 对话消息数超过该值则不缓存 (防误判)
    ExcludeSystemPrompt: bifrost.Ptr(false), // 是否排除系统提示词参与计算
    
    // 高级隔离选项
    CacheByModel:    bifrost.Ptr(true), // 按模型隔离缓存
    CacheByProvider: bifrost.Ptr(true), // 按提供商隔离缓存
}

plugin, err := semanticcache.Init(context.Background(), cacheConfig, logger, store)
if err != nil {
    log.Fatal("Failed to create semantic cache plugin:", err)
}

// 将插件加入 Bifrost 总配置
bifrostConfig := schemas.BifrostConfig{
    LLMPlugins: []schemas.LLMPlugin{plugin},
    // ... 其他配置
}

五、纯直接哈希模式 (无嵌入模型)

若不想调用任何嵌入 API(例如仅需精确去重、无外部网络环境),可启用纯哈希模式。

关键代码:纯直接哈希模式配置

go
cacheConfig := &semanticcache.Config{
    // 不提供 Provider、Keys、EmbeddingModel
    Dimension: 1, // 占位值,实际存储无向量,仅元数据
    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"

// 在上下文中设置缓存键,此请求将被缓存
ctx = context.WithValue(ctx, semanticcache.CacheKey, "session-123")
response, err := client.ChatCompletionRequest(schemas.NewBifrostContext(ctx, schemas.NoDeadline), request)

// 未设置缓存键的上下文 → 此请求不会触发缓存
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
// 强制仅用直接哈希匹配
ctx = context.WithValue(ctx, semanticcache.CacheTypeKey, semanticcache.CacheTypeDirect)

// 强制仅用语义相似匹配
ctx = context.WithValue(ctx, semanticcache.CacheTypeKey, semanticcache.CacheTypeSemantic)

3. 禁止存储本次响应 (只读不写)

go
ctx = context.WithValue(ctx, semanticcache.CacheNoStoreKey, true)

4. 手动清理缓存条目

go
// 按请求 ID 删除特定条目
err := plugin.ClearCacheForRequestID("550e8400-e29b-41d4-a716-446655440000")

// 按缓存键删除全部相关条目
err := plugin.ClearCacheForKey("support-session-456")

八、缓存命中后的调试信息

缓存命中后,响应对象的 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 可实现精确的缓存条目管理。