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