使用Sentence-BERT和Elasticsearch构建跨语言搜索
本文详细介绍如何利用Sentence-BERT构建跨语言搜索
简介
使用 Elasticsearch 和 sentence-transformers 库可以实现多语言的向量化搜索功能。在该方案中,我们将使用 sentence-transformers 提供的模型将文本转化为向量,存储在 Elasticsearch 中,并通过向量相似度来进行搜索。
以下是一个实现多语言搜索功能的完整步骤。
1. 安装依赖
确保安装了 Elasticsearch、sentence-transformers 库以及 elasticsearch Python 客户端。
pip install sentence-transformers elasticsearch2. 准备 Elasticsearch 索引
我们需要在 Elasticsearch 中创建一个索引,并在其中定义一个向量字段,用于存储文本向量。为了简化操作,我们使用 dense_vector 字段,该字段可以直接用于计算相似度。
from elasticsearch import Elasticsearch
# 创建 Elasticsearch 连接
es = Elasticsearch(hosts=["http://localhost:9200"])
# 定义索引的映射
index_name = "multilingual_index"
mapping = {
"mappings": {
"properties": {
"text": {"type": "text"}, # 原始文本字段
"text_vector": {
"type": "dense_vector",
"dims": 768 # 假设模型输出768维向量
},
"language": {"type": "keyword"} # 语言字段
}
}
}
# 创建索引
if not es.indices.exists(index=index_name):
es.indices.create(index=index_name, body=mapping)
注意
text_vector字段用于存储向量(在此示例中,模型输出是 768 维向量)。
language字段用于存储语言信息,这样可以在查询时根据语言过滤数据。
3. 使用 sentence-transformers 进行文本向量化
sentence-transformers 提供了多种预训练模型支持多语言搜索,这里选择 paraphrase-multilingual-MiniLM-L12-v2,该模型支持 50 多种语言。
from sentence_transformers import SentenceTransformer
# 加载多语言模型
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
4. 插入数据
我们将文本转换成向量并插入到 Elasticsearch 中。插入时,Elasticsearch 将根据向量字段 text_vector 来存储文本的向量表示。
# 示例数据
data = [
{"text": "Python is a great programming language.", "language": "en"},
{"text": "Python 是一种很棒的编程语言。", "language": "zh"},
{"text": "Python es un gran lenguaje de programación.", "language": "es"}
]
# 插入数据
for i, doc in enumerate(data):
# 将文本转化为向量
vector = model.encode(doc["text"]).tolist()
# 插入到 Elasticsearch 中
es.index(index=index_name, id=i, document={
"text": doc["text"],
"language": doc["language"],
"text_vector": vector
})
注意
- 将向量转换为列表(
.tolist())以符合 Elasticsearch 的 JSON 格式。
- 使用
id可以控制插入的数据,确保每个文本对应的 ID 唯一。
5. 实现搜索功能
为了实现多语言的搜索功能,我们首先将查询文本转换为向量,并在 Elasticsearch 中使用 cosineSimilarity 或 l2Norm 来计算向量之间的相似度。
def search(query_text, language=None, top_k=5):
# 将查询文本转化为向量
query_vector = model.encode(query_text).tolist()
# 构建查询语句
query = {
"size": top_k,
"query": {
"bool": {
"must": [
{
"script_score": {
"query": {"match_all": {}},
"script": {
# 使用 cosineSimilarity 计算相似度
"source": "cosineSimilarity(params.query_vector, 'text_vector') + 1.0",
"params": {"query_vector": query_vector}
}
}
}
]
}
}
}
# 添加语言过滤(可选)
if language:
query["query"]["bool"]["filter"] = [{"term": {"language": language}}]
# 执行查询
response = es.search(index=index_name, body=query)
# 返回结果
results = [
{"text": hit["_source"]["text"], "score": hit["_score"]}
for hit in response["hits"]["hits"]
]
return results
参数说明
query_text:要搜索的文本。
language:语言过滤选项,例如en、zh,若为空则搜索所有语言。
top_k:返回的结果数量。
示例
# 搜索英文结果
results = search("Python programming language", language="en")
for result in results:
print(f"Text: {result['text']}, Score: {result['score']}")
6. 测试效果
可以尝试不同语言的查询,查看返回的多语言文本内容。模型会根据相似度排序,返回与查询最相关的文档。
示例查询
# 使用中文搜索
results = search("编程语言")
for result in results:
print(f"Text: {result['text']}, Score: {result['score']}")
# 使用西班牙语搜索
results = search("lenguaje de programación")
for result in results:
print(f"Text: {result['text']}, Score: {result['score']}")
注意事项
- 向量维度:确保
dense_vector字段的维度与sentence-transformers模型的输出维度一致。
- 性能优化:多语言模型较大,向量计算耗时,可以考虑缓存常用查询向量或使用更高效的近似向量计算方法(例如
ANN)。
- 分布式系统:若使用多节点 Elasticsearch 集群,建议合理规划分片和副本数,以提升查询速度和容错能力。
- 语言过滤:在查询时可指定语言过滤,以保证查询结果符合用户语言需求。
通过 sentence-transformers 将文本转化为语义向量,并借助 Elasticsearch 的 dense_vector 和脚本相似度计算,可以有效地实现一个支持多语言的语义搜索功能。
资料
不同类型的sentence_transformer有不同的效果,比如同义词近义词,跨语言,可以按需挑选:这里链接huggingface
除了语义检索,elasticsearch支持不同权重的文本字段匹配。参考这篇文章:点击这里