【AI】利用语义缓存,优化AI Agent性能

文章目录

    • [一、Redis 语义缓存](#一、Redis 语义缓存)
      • [1.1 传统缓存的问题](#1.1 传统缓存的问题)
      • [1.2 语义缓存的定义](#1.2 语义缓存的定义)
    • [二、Redis 发展史与为什么它能做语义缓存](#二、Redis 发展史与为什么它能做语义缓存)
      • [2.1 Redis 版本演进(关键节点)](#2.1 Redis 版本演进(关键节点))
        • [Redis 7.x + Redis Stack 支持语义检索(2022--至今)](#Redis 7.x + Redis Stack 支持语义检索(2022–至今))
      • [什么是Redis Stack](#什么是Redis Stack)
        • [Redis 内核(Redis OSS)](#Redis 内核(Redis OSS))
        • [Redis Stack 包含哪些组件(核心)](#Redis Stack 包含哪些组件(核心))
          • [1️⃣ RediSearch](#1️⃣ RediSearch)
          • [2️⃣ RedisJSON](#2️⃣ RedisJSON)
          • [3️⃣ RedisTimeSeries(可选)](#3️⃣ RedisTimeSeries(可选))
          • [4️⃣ RedisBloom(可选)](#4️⃣ RedisBloom(可选))
    • [三、Redis 底层数据结构](#三、Redis 底层数据结构)
      • [3.1 Redis 对象模型](#3.1 Redis 对象模型)
      • [3.2 向量在 Redis 中的存储](#3.2 向量在 Redis 中的存储)
    • 四、Redis中向量检索算法
    • [五、Redis 语义缓存整体架构](#五、Redis 语义缓存整体架构)
    • [七、Go 语言实现语义缓存(工程示例)](#七、Go 语言实现语义缓存(工程示例))
      • [7.0 创建索引(Redis Stack)](#7.0 创建索引(Redis Stack))
      • [7.1 数据结构设计](#7.1 数据结构设计)
      • [7.2 向量写入 Redis](#7.2 向量写入 Redis)
      • [7.3 向量检索(KNN)](#7.3 向量检索(KNN))
      • [7.4 命中策略(工程关键)](#7.4 命中策略(工程关键))
    • [八、语义缓存 vs 向量数据库](#八、语义缓存 vs 向量数据库)
    • 九、常见工程坑

在传统缓存体系中,Redis 的核心价值是 Key 精确命中

但在 大模型 / RAG / 智能问答 场景下,问题的本质已经发生变化:

用户的问题不是"是否完全一样",而是"语义是否相近"。

这催生了一种新的缓存形态:语义缓存(Semantic Cache)


一、Redis 语义缓存

1.1 传统缓存的问题

text 复制代码
Q1: 更换轮胎需要多少钱?
Q2: 汽车换一个轮胎大概费用?

在 Key-Value 缓存里:

text 复制代码
key1 != key2 → cache miss

但在语义上:

text 复制代码
sim(Q1, Q2) ≈ 0.95 → 应该命中

1.2 语义缓存的定义

语义缓存 = 向量化 + 相似度检索 + Redis 高速存储

基本流程:

复制代码
Query
 ↓ embedding
Vector
 ↓ ANN search
TopK 相似问题
 ↓ 阈值判断
命中 → 直接返回
未命中 → LLM 推理 + 写入缓存

二、Redis 发展史与为什么它能做语义缓存

2.1 Redis 版本演进(关键节点)

版本 时间 关键能力
Redis 2.x 2012 单线程 KV,引入基础数据结构
Redis 3.x 2015 Cluster,分片与高可用
Redis 4.x 2017 Modules API(模块化能力基石)
Redis 6.x 2020 IO 多线程,提升网络吞吐
Redis 7.x 2022 内存 / 协议 / Cluster 优化
Redis 8.x 2024+ 核心性能与内存模型持续优化(未引入原生向量能力)
Redis Stack 2023 Search / JSON / Vector(语义检索实际落地形态)

真正让 Redis 能做语义缓存的,是:

Redis Modules + Vector Similarity Search

Redis 从 RediSearch 2.4(2022)开始支持向量相似度检索(FLAT / HNSW),这才真正具备"语义检索"能力。

Redis 7.x + Redis Stack 支持语义检索(2022--至今)
  • Redis 核心版本:7.x

  • 通过 Redis Stack 统一集成:

    • RediSearch
    • RedisJSON
    • Vector Search

工程上我们通常说:

"Redis 7 + Redis Stack = 可用的语义检索 Redis"

什么是Redis Stack

Redis Stack 是 Redis 官方推出的"能力集合发行版",在不修改 Redis 内核的前提下,通过官方模块,把搜索、JSON、向量检索等高级能力标准化、产品化。

它不是一个新 Redis,也不是一个新版本。

Redis Stack 为什么出现?

过去 Redis 生态是这样的:

  • 模块版本碎片化
  • 编译复杂
  • 线上环境难以维护

Redis Stack 的目标是:

把"可用于生产的模块组合"标准化

Redis 内核(Redis OSS)
分类 内容
负责 - 内存管理 - 网络 IO - 数据结构(String / Hash / ZSet ...)
目标 - 极致性能 - 核心最小化
不直接做 - 搜索 - 向量索引 - JSON 查询
Redis Stack 包含哪些组件(核心)
1️⃣ RediSearch

最重要的模块

  • 全文检索
  • 二级索引
  • 聚合查询
  • 向量相似度检索(FLAT / HNSW)
text 复制代码
FT.CREATE
FT.SEARCH
FT.AGGREGATE

语义检索能力 = 100% 来自 RediSearch


2️⃣ RedisJSON
  • 原生 JSON 存储

  • 支持:

    • JSONPath
    • 局部更新
  • 解决 Hash 表达能力不足的问题

适合:

  • RAG 元数据
  • 结构化 Prompt
  • 会话状态

3️⃣ RedisTimeSeries(可选)
  • 高性能时序数据

  • 常用于:

    • 监控
    • 指标
    • 特征统计

4️⃣ RedisBloom(可选)
  • Bloom / Cuckoo Filter
  • HyperLogLog
  • TopK

常用于:

  • 去重
  • 防缓存穿透
  • 热点统计

三、Redis 底层数据结构

3.1 Redis 对象模型

text 复制代码
redisObject
 ├── type   (string / hash / zset / module)
 ├── encoding (int / embstr / ziplist / skiplist)
 └── ptr

Vector 本质是:

text 复制代码
module 类型对象

3.2 向量在 Redis 中的存储

在 Redis Stack(Search 模块)中:

  • 向量字段并非 String

  • 而是 专用 Vector Index

  • 支持:

    • FLAT(暴力)
    • HNSW(近似)

四、Redis中向量检索算法

一、FLAT:暴力但准确的向量搜索

对于Flat索引,我们引入查询向量 xq,并将其与索引中所有向量进行比较,即计算 xq 到每个向量的距离。

在计算完所有这些距离后,我们将返回其中最接近的 k 个作为我们最接近的匹配项。即进行一次k最近邻 (kNN) 搜索。

维度 说明
算法本质 对所有向量逐一计算距离,排序后取 TopK(Brute Force)
时间复杂度 O(N × D) N:向量数量 D:向量维度
距离计算 L2(欧氏距离) IP(内积) COSINE(语义检索最常用)
精度 100% 精确
构建成本 无需构建索引
参数调优 不需要
性能特点 ❌ 性能差 ❌ 无法扩展 ❌ N 稍大就不可用
适用规模 < 10k:可用 10k ~ 100k:勉强 > 100k:不现实
Redis 支持 VECTOR FLAT 768
典型场景 调试验证 小规模语义缓存 召回精度基准(Baseline)

二、HNSW:分层可导航小世界图

HNSW 是什么

HNSW(Hierarchical Navigable Small World):

层次化可导航小世界(HNSW)图是向量相似性搜索中表现最佳的索引之一。HNSW 技术以其超级快速的搜索速度和出色的召回率,在近似最近邻(ANN)搜索中表现卓越。

HNSW的基础

我们可以将ANN算法分为三个不同的类别;树、哈希和图。HNSW属于图类别。更具体地说,它是一个基于接近度的图,其中两个顶点根据它们的接近度(更接近的顶点被连接)连接------通常在欧几里得距离中定义。

从"接近度"图到"层次可导航的小世界"图的复杂度有显著的飞跃,将描述两种对HNSW贡献最大的基本技术:概率跳表和可导航的小世界图。

概率跳表

概率跳表由William Pugh在1990年引入,它结合了排序数组的快速搜索能力和链表的便捷插入操作。

跳表通过构建多个层的链表来工作。在最高层,链接能够跳过许多中间节点。在较低层,链接的"跳跃"数量逐渐减少。

要在跳表中进行搜索,从最高层开始,沿着边缘向右移动。如果发现当前节点的"键"大于目标键,表示已经超出目标,于是向下移动到下一层继续搜索。

NSW: 可导航的小世界图

NSW: Navigable Small World Graphs

NSW是一种图结构,其中包含通过边连接到最近邻居的顶点。HNSW是对可导航小世界(NSW)图的进一步改进。

在NSW图中,每个节点(或称为顶点)都与若干其他节点相连,这些相连的节点被称为"朋友"。每个节点维护着一个朋友列表,共同构成了整个图的结构。

进行NSW图搜索时,搜索过程遵循以下步骤:

  • 从预定义的起点出发:选择一个起点,该点与多个相邻节点相连。
  • 局部邻近性识别:在这些相邻节点中,识别出与查询向量最为接近的一个节点。
  • 逐步逼近目标:移动到该节点,并重复上述过程,逐步缩小搜索范围,直至找到最接近查询向量的节点。
HNSW:分层导航小世界图

分层导航小世界图(Hierarchical Navigable Small World Graphs,简称HNSW)是可导航小世界图(NSW)的高级演变,它引入了概率跳表结构中的概率多层次概念。

HNSW通过向NSW添加层次化结构,创建一个在不同层级间具有不同链接长度的图。这种结构在最高层拥有最长的链接,在最低层则拥有最短的链接。

数据结构

  • 多层图结构
  • 每个节点连接有限邻居
  • 高层稀疏,低层密集

从"接近度"图到"层次可导航的小世界"图的复杂度有显著的飞跃,将描述两种对HNSW贡献最大的基本技术:概率跳表和可导航的小世界图。

HNSW特点
维度 说明
算法全称 HNSW(Hierarchical Navigable Small World)
算法类型 近似最近邻搜索(ANN)
核心思想 基于"小世界网络",通过多层图结构实现快速导航
图结构 分层图(Layered Graph) 高层稀疏、低层密集
节点连接 每个节点只连接有限数量的近邻(由 M 控制)
索引结构特点 高层用于快速定位区域 底层用于精细搜索
搜索起点 最高层的入口节点
搜索策略 贪心搜索(Greedy Search)逐层下降
查询流程 高层快速收敛 → 逐层下探 → 底层精搜返回 TopK
插入流程 新节点随机分配最高层级 → 自顶向下查找邻居 → 逐层建立连接
查询时间复杂度 近似 O(log N)
插入时间复杂度 近似 O(log N)
扩展能力 可支撑百万、千万级向量规模
精度特点 非 100% 精确,但可通过参数逼近精确结果
实时性 支持在线插入与查询
工程优势 查询稳定、延迟可控、适合在线系统
典型应用 语义缓存 向量数据库 RAG 粗排召回
Redis 支持 RediSearch Vector(HNSW)

结构示意

复制代码
Level 3:   o────o
            │
Level 2: o──o──o──o
          │     │
Level 1: o─o─o─o─o─o

3️⃣ 搜索流程

text 复制代码
从最高层入口节点开始
↓
贪心搜索,快速接近目标区域
↓
逐层下降
↓
底层精搜,返回 TopK
HNSW算法 参数含义

HNSW性能

在深入了解了HNSW(分层导航小世界图)的理论基础和Faiss库的实现细节后,现在转向评估不同参数对HNSW索引性能的具体影响。将重点分析召回率、搜索时间、构建时间以及内存使用情况。

将调整以下三个关键参数:M、efSearch和efConstruction,并在Sift1M数据集上测试它们的影响。

  • M 控制每个节点的最大连接数量,影响图的密度和搜索精度。
  • efSearch 控制查询过程中候选列表的大小,影响查询时间和精度。
  • efConstruction 控制索引构建过程中候选列表的大小,影响索引构建时间和质量。
参数 含义 作用阶段 调大后的影响 常见取值
M 每个节点的最大邻居数 构建 精度 ↑,内存 ↑,构建变慢 8 / 16 / 32
EF_CONSTRUCTION 构建阶段候选集大小 构建 索引质量 ↑,构建时间 ↑ 100 ~ 400
EF_RUNTIME(EF_SEARCH) 查询阶段候选集大小 查询 召回率 ↑,查询延迟 ↑ 20 ~ 100
K 返回的最近邻数量 查询 结果更多,后处理成本 ↑ 1 ~ 20

五、Redis 语义缓存整体架构

复制代码
              ┌────────────┐
User Query →  │ Embedding  │
              └─────┬──────┘
                    │
              ┌─────▼──────┐
              │ Redis ANN  │
              │  HNSW     │
              └─────┬──────┘
            hit?     │ miss
              │      ▼
         ┌────▼───┐  LLM
         │ Answer │   ↓
         └────────┘ 写入缓存

七、Go 语言实现语义缓存(工程示例)

7.0 创建索引(Redis Stack)

bash 复制代码
FT.CREATE semantic_cache
ON HASH
PREFIX 1 "qa:"
SCHEMA
question VECTOR HNSW 768 TYPE FLOAT32 DISTANCE_METRIC COSINE
answer TEXT

7.1 数据结构设计

go 复制代码
type CacheItem struct {
	ID       string
	Vector   []float32
	Question string
	Answer   string
}

7.2 向量写入 Redis

go 复制代码
func Store(ctx context.Context, rdb *redis.Client, item CacheItem) error {
	vecBytes := floatsToBytes(item.Vector)

	key := "qa:" + item.ID
	return rdb.HSet(ctx, key, map[string]interface{}{
		"question": item.Question,
		"answer":   item.Answer,
		"vector":   vecBytes,
	}).Err()
}
go 复制代码
func floatsToBytes(vec []float32) []byte {
	buf := new(bytes.Buffer)
	for _, v := range vec {
		_ = binary.Write(buf, binary.LittleEndian, v)
	}
	return buf.Bytes()
}

7.3 向量检索(KNN)

go 复制代码
func Search(ctx context.Context, rdb *redis.Client, vector []float32) (string, float64, error) {
	vecBytes := floatsToBytes(vector)

	cmd := []interface{}{
		"FT.SEARCH", "semantic_cache",
		"*=>[KNN 1 @question $vec AS score]",
		"PARAMS", 2, "vec", vecBytes,
		"SORTBY", "score",
		"RETURN", 2, "answer", "score",
		"DIALECT", 2,
	}

	res, err := rdb.Do(ctx, cmd...).Result()
	if err != nil {
		return "", 0, err
	}

	// 解析结果(略)
	return answer, score, nil
}

7.4 命中策略(工程关键)

go 复制代码
const HitThreshold = 0.85

if score >= HitThreshold {
	return cachedAnswer
}

// fallback to LLM

实践经验:

  • 技术问答:0.85~0.9
  • 闲聊类:0.75~0.8
  • 汽修 / 医疗:宁高勿低

八、语义缓存 vs 向量数据库

维度 Redis 语义缓存 专用向量库
延迟 极低(<5ms)
数据规模 百万级 千万~亿
事务 支持
运维 简单 偏复杂
适合场景 热问题 冷知识

结论:

Redis 语义缓存 ≠ 向量数据库

它是 RAG 架构里的第一层"语义 L1 Cache"


九、常见工程坑

向量版本漂移:

embedding 模型升级 → 缓存需失效,或者维护embedding模型版本。

缓存污染:

低质量回答进入缓存

阈值静态:

不同业务应动态调整

并发写入:

建议异步写缓存

命中率忽高忽低/相同问题结果不稳定

原因 90% 是:

text 复制代码
EF_RUNTIME 太小

EF_RUNTIME 是 HNSW 算法的一个关键参数,它控制查询时的搜索精度与延迟之间的权衡。 查询阶段 EF 小,等于"搜索半途就停了"

相关推荐
DuanPenghao2 小时前
RISCV实战:实现基于Verilator模拟蜂鸟E203的加法器和卷积神经网络仿真
人工智能·嵌入式硬件·神经网络·cnn·risc-v
一水鉴天2 小时前
整体设计 定稿 之31 拼语言统筹表 - “归” 档位属 多轴联动(codebuddy)
人工智能·架构
智算菩萨2 小时前
Gemini 3 Flash深度解析:Google推出的最新一代快速高效AI模型详尽性能评测报告
人工智能·aigc·gemini
智算菩萨2 小时前
【理论讲解】深度多任务学习:概念体系、方法谱系与跨领域建模逻辑
人工智能·机器学习·多任务学习
张彦峰ZYF2 小时前
借助DeepSeek思考产业落地:蒸馏、小模型微调
人工智能·ai·deepseek-v3·deepseek-r1·蒸馏-小模型微调
蓝鲨硬科技2 小时前
五一视界与摩尔线程深度合作,释放物理AI进化潜能
人工智能
过河卒_zh15667662 小时前
网信发布2025年“人工智能+政务”规范应用案例拟入选名单公示
人工智能·大模型·aigc·政务·算法备案
540_5402 小时前
ADVANCE Day26
人工智能·python·机器学习
IT_陈寒2 小时前
Redis 性能优化实战:5个被低估的配置项让我节省了40%内存成本
前端·人工智能·后端