在简单的知识库检索中,使用 contains() 判断关键词虽然直观,却很容易漏掉表达不同但含义相近的问题。例如用户没有直接说出 Redis,系统就可能无法找到相关知识。要让检索从比较文字升级为比较语义,需要理解 Embedding、向量相似度以及 Top-K 召回如何共同工作。
Day4 下半场的核心问题:
为什么 contains() 不够?Embedding 到底解决了什么问题?
上一部分,我们实现了一个简单的关键词检索系统。
例如:
知识:
Redis 是基于内存的高性能 Key-Value 数据库。
用户问:
Redis 为什么这么快?
因为包含:
Redis
所以可以命中。
但是换一个问题:
为什么这种内存数据库性能这么高?
这时候:
question.contains("Redis")
结果:
false
检索失败。
但从人的角度来看:
“这种内存数据库”
很可能就是:
Redis
所以真正的问题不是程序不会搜索,而是:
程序只能看到文字,没有理解文字背后的语义。
可以把两种方式简单理解成:
关键词检索:
“文字一样不一样?”
VS
Embedding:
“意思像不像?”
例如:
A:
Redis 为什么这么快?
B:
为什么这种内存数据库性能这么高?
虽然两个句子使用的词并不完全相同:
Redis
为什么这么快
VS
内存数据库
性能这么高
但是语义非常接近。
这就是 Embedding 要解决的问题。
Embedding 可以简单理解成:
把文本转换成一个能够表达其语义特征的向量。
例如:
Redis 是基于内存的高性能数据库。
经过 Embedding 模型:
Embedding
↓
Vector
得到一个向量:
[0.12, -0.83, 0.41, ...]
这里的数字只是示意。
真实 Embedding 通常会有很多维。
重要的不是:
0.12
-0.83
0.41
这些数字本身有什么含义。
而是:
整个向量可以作为这段文本的“语义表示”。
这里有一个非常容易混淆的地方。
Embedding 并不是只处理用户问题。
知识库中的文本也需要向量化。
例如知识库:
Redis 是基于内存的高性能 Key-Value 数据库。
MySQL 是一种关系型数据库。
Spring Boot 用于快速开发 Java 应用。
需要提前进行:
Redis知识
↓
Embedding
↓
Redis Vector
MySQL知识
↓
Embedding
↓
MySQL Vector
Spring Boot知识
↓
Embedding
↓
Spring Boot Vector
而用户问题:
为什么这种内存数据库性能这么高?
也需要:
用户问题
↓
Embedding
↓
Question Vector
最终才能进行比较。
假设:
Redis知识
↓
Vector A
用户问题:
为什么这种内存数据库性能这么高?
↓
Vector B
接下来比较:
Vector A
↕
Vector B
如果两个向量在“向量空间”中比较接近,就说明:
语义相似
如果距离很远:
语义不太相关
因此:
文本
↓
Embedding
↓
Vector
↓
Similarity
这就是语义检索的核心。
比较两个向量时,可以使用很多方法。
RAG 中一个非常常见的方法是:
Cosine Similarity(余弦相似度)
不需要一开始就死记数学公式。
先建立直觉:
两个向量方向越接近
↓
余弦相似度越高
↓
语义越相似
例如:
问题:
Redis 为什么这么快?
和:
知识:
Redis 是基于内存的高性能 Key-Value 数据库。
可能得到:
Similarity = 0.91
而:
知识:
Spring Boot 用于快速开发 Java 应用。
可能:
Similarity = 0.05
那么系统就可以判断:
Redis知识
↓
高度相关
Spring Boot知识
↓
基本无关
这时候就可以把上一部分的 TopK 接起来。
之前我们使用:
关键词命中数量
计算:
score
现在改成:
Cosine Similarity
计算:
score
整个流程实际上没有变化:
Day4上
关键词命中数量
↓
Score
↓
Sort
↓
TopK
Day4下
Embedding
↓
Vector Similarity
↓
Score
↓
Sort
↓
TopK
这就是非常重要的一个理解:
Embedding 并没有改变 RAG 的整体结构,只是改变了“相关度 Score 怎么计算”。
知识库:
Redis 是基于内存的高性能 Key-Value 数据库。
Redis 支持持久化机制。
Redis 常用于缓存。
MySQL 是一种关系型数据库。
Spring Boot 用于快速开发 Java 应用。
用户问题:
这种内存数据库为什么性能这么高?
注意:
问题里面甚至没有出现 Redis。
首先对问题做 Embedding:
Question
↓
Embedding
↓
Question Vector
知识也已经提前做过 Embedding:
Redis知识
↓
Redis Vector
然后计算相似度:
Redis 是基于内存的高性能 Key-Value 数据库
Similarity = 0.91
Redis 支持持久化机制
Similarity = 0.76
Redis 常用于缓存
Similarity = 0.72
MySQL 是一种关系型数据库
Similarity = 0.18
Spring Boot 用于快速开发 Java 应用
Similarity = 0.05
排序:
0.91
0.76
0.72
0.18
0.05
如果:
K = 3
那么:
TOP 1
Redis 是基于内存的高性能 Key-Value 数据库。
TOP 2
Redis 支持持久化机制。
TOP 3
Redis 常用于缓存。
这就是:
Semantic Search(语义检索)
这是 TopK 的另一个重要意义。
如果只取:
Top1
得到:
Redis 是基于内存的高性能 Key-Value 数据库。
它已经比较相关。
但是用户的问题是:
为什么这种内存数据库性能这么高?
如果还有其他相关知识:
Redis 常用于缓存。
Redis 支持持久化机制。
这些信息也可能帮助 LLM 更完整地回答问题。
因此可以取:
Top3
把多个相关知识一起放入 Context:
Context:
Redis 是基于内存的高性能 Key-Value 数据库。
Redis 支持持久化机制。
Redis 常用于缓存。
然后:
Context
+
Question
↓
Prompt
↓
LLM
所以 TopK 并不是简单地:
“取更多结果。”
更准确地说:
在保证相关性的前提下,为 LLM 提供足够的上下文信息。
如果 K 太小:
可能遗漏相关知识
如果 K 太大:
Context 太长
噪音增加
Token 消耗增加
模型可能受到无关信息干扰
因此真实 RAG 中的 K 并不是越大越好。
常见的思路是:
Top3
Top5
Top10
再根据具体业务调整。
现在我们可以把整个过程串起来。
Question
↓
关键词匹配
↓
命中数量
↓
Score
↓
Sort
↓
TopK
Question
↓
Embedding
↓
Question Vector
↓
Similarity
↓
Score
↓
Sort
↓
TopK
知识库:
Knowledge
↓
Embedding
↓
Document Vector
所以完整系统:
Knowledge Base
↓
Embedding
↓
Document Vectors
↑
│
Question → Embedding
↓
Question Vector
↓
Cosine Similarity
↓
Score
↓
Sort
↓
TopK
↓
Context
↓
Prompt
↓
LLM
↓
Answer
这就是一个真正的:
Embedding-based RAG
Day4 最重要的不是记住:
Embedding
Cosine Similarity
TopK
而是理解为什么这些东西存在。
最开始:
contains()
因为它只能匹配文字:
“Redis”
和:
“内存数据库”
无法建立联系。
于是我们需要:
Embedding
把文本转换成:
Vector
然后通过:
Similarity
判断两个文本在语义上是否接近。
最后通过:
TopK
选择最相关的知识。
今天完整经历了一次 RAG 检索能力的升级:
固定知识
↓
关键词检索
↓
多知识召回
↓
Score
↓
Ranking
↓
TopK
↓
发现关键词检索的局限
↓
Embedding
↓
Vector
↓
Similarity
↓
Semantic Search
可以把今天浓缩成一句话:
关键词检索比较“词”,Embedding 检索比较“语义”。
而整个 RAG 的检索骨架依然是:
Question
↓
Retrieve
↓
Score
↓
Ranking
↓
TopK
↓
Context
↓
LLM
只是:
Score 的计算方式
从:
关键词命中数量
升级成了:
向量语义相似度
下一阶段不再停留在概念。
Day5 将真正动手:
文本
↓
Embedding API
↓
真实 Vector
↓
Cosine Similarity
↓
Score
↓
TopK
最终完成一个关键实验:
问题:
为什么这种内存数据库性能这么高?
问题中不出现 Redis,但是系统仍然能够:
TOP 1
Redis 是基于内存的高性能 Key-Value 数据库。
如果这个实验跑通,就意味着真正完成了从:
关键词 RAG → 语义 RAG
的第一次升级。