在海量数据时代,传统的关键词搜索往往难以满足用户对信息精准、高效的需求。用户期望的是能够理解其搜索意图,并返回与之语义相关的结果。Elasticsearch 9 推出的语义检索功能,正是为了解决这一痛点,它利用深度学习模型,实现了对文本语义的理解和匹配,从而提供更智能、更人性化的搜索体验。
传统搜索的局限性
传统搜索主要依赖于关键词匹配,例如,用户搜索“苹果手机”,搜索系统会查找包含“苹果”和“手机”这两个关键词的文档。这种方式简单直接,但存在诸多局限性:
- 无法理解语义: 无法理解“苹果”是水果还是手机品牌,导致搜索结果不准确。
- 依赖精确匹配: 无法处理同义词、近义词等情况,例如搜索“智能手机”时,可能无法返回包含“苹果手机”的文档。
- 难以处理复杂查询: 无法理解复杂句子的含义,例如“拍照效果好的手机”这种模糊的描述。
这些局限性导致用户需要多次尝试不同的关键词组合,才能找到所需的信息,搜索效率低下。
Elasticsearch 9 语义检索的底层原理
Elasticsearch 9 的语义检索功能,通过集成先进的自然语言处理(NLP)技术,解决了传统搜索的局限性。其核心原理如下:
- 文本向量化: 使用预训练的深度学习模型(如 Transformer 模型)将文本转换为向量表示。这些向量能够捕捉文本的语义信息,将语义相近的文本映射到向量空间中相近的位置。
from transformers import AutoTokenizer, AutoModel
import torch
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-mpnet-base-v2")
model = AutoModel.from_pretrained("sentence-transformers/all-mpnet-base-v2")
def encode_text(text):
inputs = tokenizer(text, padding=True, truncation=True, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)
# 使用平均池化获得句子向量
return outputs.last_hidden_state.mean(dim=1)
text = "Elasticsearch 9 语义检索功能强大"
vector = encode_text(text)
print(vector.shape) # 输出:torch.Size([1, 768])
向量索引: 将文本向量存储在 Elasticsearch 的向量索引中。向量索引采用近似最近邻(ANN)搜索算法,如 HNSW(Hierarchical Navigable Small World),能够高效地查找与查询向量最相似的文档向量。

相似度计算: 当用户发起搜索时,系统将查询文本转换为向量,然后在向量索引中查找与查询向量最相似的文档向量。相似度通常使用余弦相似度或点积计算。
import numpy as np
def cosine_similarity(v1, v2):
# 计算余弦相似度
v1_norm = np.linalg.norm(v1)
v2_norm = np.linalg.norm(v2)
if v1_norm == 0 or v2_norm == 0:
return 0
return np.dot(v1, v2) / (v1_norm * v2_norm)
vector1 = np.random.rand(768) # 模拟文档向量
vector2 = np.random.rand(768) # 模拟查询向量
similarity = cosine_similarity(vector1, vector2)
print(f"相似度:{similarity}")
- 结果排序: 根据相似度对搜索结果进行排序,将与查询意图最相关的文档排在前面。
通过以上步骤,Elasticsearch 9 的语义检索能够理解用户搜索意图,并返回更精准的搜索结果,极大地提升了搜索效率和用户体验。
Elasticsearch 9 语义检索实战
要使用 Elasticsearch 9 的语义检索,需要安装相应的插件,并配置索引映射。以下是一个简单的示例:
安装
knn插件: 用于支持向量索引。
./bin/elasticsearch-plugin install knn-search创建索引映射: 定义向量字段的类型和维度。
PUT /my_index { "mappings": { "properties": { "text": { "type": "text" }, "text_vector": { "type": "knn_vector", "dimension": 768, // 根据使用的模型调整维度 "index": true, "store": true } } } }索引数据: 将文本转换为向量,并存储到 Elasticsearch 中。
from elasticsearch import Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) text1 = "Elasticsearch 9 语义检索功能强大" text2 = "Elasticsearch 9 新特性提升搜索体验" vector1 = encode_text(text1).tolist()[0] vector2 = encode_text(text2).tolist()[0] es.index(index='my_index', id=1, document={'text': text1, 'text_vector': vector1}) es.index(index='my_index', id=2, document={'text': text2, 'text_vector': vector2}) es.indices.refresh(index='my_index') # 刷新索引,使数据可见执行语义搜索: 使用
knn查询,查找与查询向量最相似的文档。query_text = "Elasticsearch 的搜索能力" query_vector = encode_text(query_text).tolist()[0] resp = es.search(index='my_index', knn={ "field": "text_vector", "query_vector": query_vector, "k": 2, "num_candidates": 10 }) for hit in resp['hits']['hits']: print(hit['_source']['text'], hit['_score'])
实战避坑经验总结
- 模型选择: 选择合适的预训练模型至关重要。应根据具体的应用场景和数据特点,选择能够有效捕捉语义信息的模型。
sentence-transformers库提供了多种预训练模型,可以根据需求进行选择。 - 维度设置: 向量的维度应与预训练模型的输出维度一致。如果维度不匹配,会导致向量索引失效。
- 性能优化: 向量索引的性能受到数据量和维度等因素的影响。可以通过调整索引参数,如
m和ef_construction,来优化性能。例如,增大m可以提高索引的准确率,但会增加索引的构建时间。可以使用宝塔面板等工具监控服务器资源使用情况,合理分配资源。 - 数据预处理: 对文本数据进行预处理,如去除停用词、标点符号等,可以提高语义检索的准确率。
- 冷热数据分离: 对于访问频率较低的历史数据,可以将其存储在成本较低的存储介质上,从而降低存储成本。
Elasticsearch 9 的语义检索功能为我们提供了一种全新的搜索方式,它能够理解用户意图,并返回更精准的搜索结果。通过合理的配置和优化,我们可以构建更智能、更高效的搜索应用。
冠军资讯
linuxer_zhao