摘要/前言
你是否经历过这样的搜索绝望?
用户在你的电商APP里搜索“西红柿”,
结果搜不到任何商品,
只因为你的数据库里存的是“番茄”。
或者用户搜索“怎么去北京”,
系统却给他推荐了“北京去哪里玩”的游记,
完全无视了用户的真实意图。
在 GPT-5.2 和 Sora2 已经能够理解人类复杂情感的今天,
如果我们还在用上个世纪的“倒排索引”和“关键词匹配”技术,
那无异于在用算盘去跑深度学习。
传统的搜索技术,
已经到了它的天花板。
它不懂语义,
不懂上下文,
更不懂“苹果”到底是水果还是手机。
但是,
作为技术人的我们,
并不需要推翻一切重来。
那个我们最熟悉的中间件——Elasticsearch,
已经悄悄进化了。
它不再仅仅是一个文本检索引擎,
它已经变身为一个强大的向量数据库。
今天,
我要带你深入 Elasticsearch 的心脏,
去探索它的向量引擎(Vector Engine) 。
这不仅仅是一篇教程,
更是一次从数学原理到工程落地的深度奇幻漂流。
我们将揭开高维空间的神秘面纱,
解析 HNSW 算法如何在大海捞针中实现毫秒级响应,
并手把手教你构建一个能够听懂人话的语义搜索系统。
坐稳了,
我们要进入高维空间了。
第一章: 认知革命——为什么我们需要向量搜索?
1.1 从“字面匹配”到“思维共鸣”
在传统的搜索世界里,
计算机其实是个“文盲”。
它并不认识字,
它只是在做字符的搬运工。
你输入“Java”,
它就去数据库里找包含“J-a-v-a”这四个字母的文档。
它根本不知道 Java 是一门编程语言,
还是印尼的一个岛,
亦或是一杯香浓的咖啡。
这就是**关键词搜索(Keyword Search)**的局限性。
它依赖分词器,
依赖同义词词典,
依赖人工维护的规则。
一旦用户输入的词汇超出了你的词典范围,
搜索结果就是零。
1.2 向量:万物的数学指纹
那么,
AI 是怎么理解世界的呢?
答案是:向量(Vector) 。
在数学家眼里,
万物皆可向量化。
我们可以把一段文本、一张图片、甚至一段视频,
通过深度学习模型(如 BERT, GPT-5.2-pro, Veo3),
压缩成一串固定长度的数字数组。
这串数字,
就是这个对象的“数学指纹”。
举个通俗的例子:
假设我们用一个二维坐标系来描述水果。
X轴代表“甜度”,
Y轴代表“水分”。
“西瓜”的坐标可能是 [0.9, 0.9](又甜又多水)。
“柠檬”的坐标可能是 [0.1, 0.8](不甜但多水)。
“番茄”的坐标可能是 [0.4, 0.8]。
这时候,
虽然“西红柿”和“番茄”这三个字完全不同,
但在高维语义空间里,
它们的坐标距离是非常非常近的。
这就是向量搜索(Vector Search)的魔力。
它不看字面,
它看位置。
它计算的是两个向量之间的距离。
距离越近,
语义越相似。
1.3 降维打击:AI 时代的搜索新范式
现在的热门应用,
无论是 RAG(检索增强生成),
还是以图搜图,
或者是视频内容检索,
底层逻辑全都是向量搜索。
当你问 GPT-5.2 一个问题时,
它首先会将你的问题向量化,
然后在海量的知识库向量中,
找到最相似的那几段知识,
最后再组织语言回答你。
如果你掌握了向量搜索技术,
你就掌握了通往 AGI 应用开发的钥匙。
第二章: 深入内核——Elasticsearch 向量引擎的数学原理
2.1 密集向量(Dense Vector):信息的压缩胶囊
在 Elasticsearch 中,
承载向量数据的核心字段类型叫做 dense_vector。
这里的“Dense”是稠密的意思。
与之相对的是“Sparse”(稀疏)向量。
在 BERT-base 模型中,
一个句子通常会被转换成 768 维 的向量。
而在更强大的 GPT-5.2-pro 模型中,
这个维度可能高达 1536 维 甚至 3072 维。
维度越高,
能表达的语义细节就越丰富。
但是,
维度越高,
计算量也是指数级增长的。
这就需要在精度和性能之间做一个权衡。
ES 的 dense_vector 字段,
就像是一个能够无限扩展的容器,
专门用来存储这些高维的数学胶囊。
2.2 相似度算法:衡量灵魂契合度的尺子
有了向量,
我们怎么判断两个向量是不是“亲兄弟”呢?
ES 提供了三种核心算法,
它们就像三种不同的尺子。
1. 余弦相似度(Cosine Similarity):
这是最常用的算法,
尤其是在 NLP(自然语言处理)领域。
它计算的是两个向量在空间中夹角的余弦值。
想象一下,
两个箭头从原点出发。
如果它们重合,夹角为 0 度,余弦值为 1,代表完全相同。
如果它们背道而驰,夹角为 180 度,余弦值为 -1,代表完全相反。
它的核心优势是:
它不关心向量的长度(模长),只关心方向。
这对于文本搜索非常重要,
因为长文本和短文本生成的向量长度可能不同,
但我们只在乎它们说的是不是同一件事。
2. 欧氏距离(L2 Norm):
这是我们在初中几何里学过的距离公式。
计算两个点在空间中的直线距离。
距离越小,
相似度越高。
它对向量的数值大小非常敏感。
通常用于图像检索或推荐系统。
比如在推荐商品时,
我们希望找到价格、销量、评分都非常接近的商品,
这时候欧氏距离就比余弦相似度更管用。
3. 点积(Dot Product):
这是计算最快的一种方式。
它计算的是两个向量对应维度的乘积之和。
但是它有一个前提:
向量必须经过归一化(Normalized)处理。
也就是说,向量的模长必须为 1。
在这种情况下,
点积的结果等价于余弦相似度。
如果你追求极致的性能,
并且能够保证写入的数据都是归一化的,
那么点积是首选。
2.3 HNSW 算法:高维空间的高速公路
如果我们要在一个包含 1 亿个向量的数据库里,
找到和目标向量最相似的 10 个向量。
最笨的办法是暴力搜索(Brute Force) 。
也就是把目标向量和数据库里的 1 亿个向量,
一个个算距离,
然后排序。
这在计算上是不可接受的,
可能一次查询要几秒钟甚至几分钟。
为了解决这个问题,
Elasticsearch 引入了 HNSW(Hierarchical Navigable Small World) 算法。
中文名叫“分层导航小世界图”。
听起来很玄乎,
其实原理很简单。
想象一下你要从北京开车去上海的一个小村庄。
你不会一开始就盯着地图上的小路找。
你会先上高速公路(顶层图),
快速跨越几百公里,到达上海周边。
然后切换到省道(中层图),
缩小范围到县城。
最后切换到乡道(底层图),
精准找到那个村庄。
HNSW 就是在向量空间里构建了这样一套多层级的交通网络。
它通过牺牲一点点精度(近似搜索),
换取了成百上千倍的性能提升。
这就是为什么 ES 可以在毫秒级完成亿级向量检索的秘密。
第三章: 实战演练——构建你的第一个语义搜索引擎
3.1 环境准备与依赖安装
光说不练假把式。
接下来,我们将使用 Ruby 语言,
配合 Elasticsearch 8.0+,
从零开始搭建一个语义搜索 Demo。
首先,你需要一个 ES 集群。
如果你不想自己搭建,
可以使用云服务。
然后,安装必要的客户端库。
bash
gem install elasticsearch
gem install numpy # 虽然Ruby不用numpy,但理解向量计算需要数学思维
3.2 索引映射(Mapping)设计
这是最关键的一步。
我们需要告诉 ES,
哪个字段是存文本的,
哪个字段是存向量的。
ruby
require 'elasticsearch/client'
client = Elasticsearch::Client.new(
hosts: 'http://localhost:9200',
log: true
)
# 创建索引
client.indices.create(
index: 'vector_knowledge_base',
body: {
mappings: {
properties: {
# 原始文本字段,用于展示
content: { type: 'text' },
# 向量字段,用于计算
content_vector: {
type: 'dense_vector',
dims: 768, # 对应BERT-base的维度
index: true, # 开启索引,支持kNN搜索
similarity: 'cosine' # 使用余弦相似度
}
}
}
}
)
这里有两个参数要特别注意:
dims: 必须和你使用的 Embedding 模型输出维度完全一致。多一维少一维都会报错。
index: 必须设置为 true。否则 ES 只会把向量存下来,而不会构建 HNSW 索引,你就只能做慢速的暴力搜索了。
3.3 数据向量化与入库
在真实场景中,
你需要调用 Python 的 sentence-transformers 库,
或者直接调用 OpenAI 的 API,
将文本转化为向量。
这里为了演示,
我们假设你已经拿到了向量数据。
ruby
# 模拟一个将文本转化为768维向量的函数
# 在实际生产中,这里是调用AI模型的API
def text_to_vector(text)
# 这里仅返回随机向量作为示例
Array.new(768) { rand - 0.5 }
end
# 写入数据
docs = [
"Elasticsearch是一个分布式的RESTful风格的搜索和数据分析引擎",
"机器学习是人工智能的一个子集",
"深度学习利用神经网络模拟人脑进行分析学习"
]
docs.each do |doc|
vector = text_to_vector(doc)
client.index(
index: 'vector_knowledge_base',
body: {
content: doc,
content_vector: vector
}
)
end
3.4 发起 kNN 向量搜索
数据进去了,
怎么查出来呢?
ES 8.0 引入了全新的 knn 搜索语法。
ruby
# 用户查询
query_text = "AI是如何进行学习的?"
query_vector = text_to_vector(query_text)
response = client.search(
index: 'vector_knowledge_base',
body: {
knn: {
field: 'content_vector',
query_vector: query_vector,
k: 10, # 返回最相似的10个结果
num_candidates: 100 # 在每个分片上搜索100个候选者
},
_source: ['content'] # 只返回文本内容,不返回向量数据(太大了)
}
)
response['hits']['hits'].each do |hit|
puts "相关度得分: #{hit['_score']}"
puts "内容: #{hit['_source']['content']}"
puts "-------------------"
end
当你运行这段代码时,
神奇的事情发生了。
虽然你的查询语句里没有“机器学习”这四个字,
但系统依然会把“机器学习是人工智能的一个子集”这条数据排在前面。
因为在向量空间里,
“AI”和“人工智能”是紧紧挨在一起的。
这就是语义搜索的威力。
官方资源插播
在进入更深度的性能调优之前,
如果你想获取更强大的向量处理能力,
或者需要现成的企业级向量服务,
请务必关注以下资源。
| 官方注册地址(含福利):api.vectorengine.ai/register?af… |
|---|
保姆级使用教程: www.yuque.com/nailao-zvxv…
兑换码:
b40171057366403387bfc2cb27a0af08
87f9955f973449dd99375e147cc8ab00
87f0ec91e74e44ecb1a324238252583d
29323e3f06f845ec8480ef9339df6434
b0cfbf4a1f9b4436960daead0416b39a
特别提醒: 现在注册并登录控制台, 在钱包页面使用兑换码, 即可获得免费测试额度! 你可以用它来测试不同 Embeddings 模型的向量效果。
第四章: 性能优化——如何让大象跳舞?
4.1 内存管理的艺术
向量搜索是内存密集型的操作。
HNSW 索引需要常驻内存,
才能保证高速跳转。
计算公式如下:
HNSW 内存占用 ≈ 向量数量 * (4 * 维度 + 8 * M)
其中 M 是 HNSW 算法中的每个节点的最大连接数。
如果你的数据量达到亿级,
内存开销是惊人的。
所以,
一定要监控 ES 节点的堆外内存(Off-heap Memory)。
确保给操作系统留足空间。
4.2 量化技术(Quantization):空间换时间
为了解决内存不够用的问题,
ES 引入了量化技术。
最常用的是 Int8 量化。
原本每个维度是一个 32 位的浮点数(4字节)。
通过量化,
我们可以把它压缩成一个 8 位的整数(1字节)。
内存占用直接砍掉 75%!
虽然精度会有极其微小的损失,
但在大多数业务场景下,
这种损失是完全可以忽略不计的。
配置方法极其简单:
json
PUT my_index/_settings
{
"index.knn.quantization": "int8"
}
4.3 混合检索(Hybrid Search):成年人全都要
向量搜索虽然好,
但它不是万能的。
比如用户搜索具体的型号“iPhone 15 Pro Max”,
向量搜索可能会把“iPhone 14”也找出来,
因为它们太像了。
这时候,
我们需要关键词匹配的精确性。
混合检索,
就是把“关键词搜索”和“向量搜索”结合起来。
先用关键词过滤器(Filter),
把不相关的数据(比如价格区间不对、品牌不对)直接过滤掉。
然后在剩下的数据里,
用向量搜索进行语义排序。
这才是企业级搜索的最佳实践。
第五章: 选型风云——Elasticsearch vs 专用向量数据库
5.1 为什么有了 Milvus 还要用 ES?
市面上有很多专用的向量数据库,
比如 Milvus, Pinecone, Qdrant。
它们在纯向量搜索的性能上,
确实比 ES 要强。
但是,
ES 有一个它们无法比拟的优势:
全栈能力。
你的业务数据(订单、用户、日志)本来就在 ES 里。
如果你引入 Milvus,
你需要维护两套系统,
不仅增加了运维成本,
还带来了数据一致性的噩梦。
如果你的数据量在千万级以下,
或者你需要强依赖混合检索(既要搜文本又要搜向量),
那么 ES 是绝对的首选。
5.2 什么时候该用 Milvus?
如果你的数据量达到了亿级甚至十亿级。
或者你的场景是纯粹的以图搜图、生物特征识别,
不需要复杂的关键词过滤。
那么,
请毫不犹豫地选择 Milvus 等专用向量数据库。
或者采用 ES + Milvus 的双剑合璧方案:
ES 负责元数据存储和粗筛,
Milvus 负责向量计算。
结语: 搜索的终局是理解
从倒排索引到 HNSW 图,
从关键词匹配到语义理解,
搜索技术的进化史,
就是人类试图让机器理解自己的奋斗史。
Elasticsearch 向量引擎的出现,
填补了传统搜索和深度学习之间的鸿沟。
它让普通的开发者,
也能以极低的成本,
构建出媲美科技巨头的智能应用。
不要被那些高大上的数学名词吓倒。
动手去写第一行代码,
去创建第一个索引,
去插入第一个向量。
当你看到搜索结果精准地命中了你心里的那个答案时,
你会发现,
这一切的折腾,
都是值得的。
最后再啰嗦一句:
技术在变, 但解决问题的核心逻辑不变。 想要真正掌握向量搜索, 光看文章是不够的。
| 去这里获取你的武器库:api.vectorengine.ai/register?af… |
|---|
去这里修炼你的内功: www.yuque.com/nailao-zvxv…
愿你的每一次搜索, 都能直达灵魂深处。