作者:来自 Elastic Lily Adler

浏览地理和富文本数据是一项重大挑战,尤其是对于景点推荐服务而言。当数据是非结构化和多语言数据时,处理大量且多样化的数据(例如评论、评分、图像、位置、标签和营业时间)会变得很复杂。
Elasticsearch 的混合地理语义搜索(hybrird goe-semantic search)功能通过在单一平台内结合空间数据处理和高级向量文本分析,提供了实用的解决方案。无论你是在搜索地标还是适合家庭的景点,Elasticsearch 都能实现精确而高效的数据检索。
在此博客中,我们将指导你利用 Elasticsearch 搜索 200 万条 TripAdvisor 评论的数据集。该数据集包括地理坐标、多种语言的非结构化评论、结构化文本和数字数据。我们将演示如何无缝集成地理和语义搜索功能以实现个性化推荐。
通过遵循我们的分步方法,你将学习如何:
- 使用机器学习模型(包括用于标记 POI(例如“family-friendly - 适合家庭”、“value for money - 物有所值”)的多语言向量化和评论分类模型)为非结构化、多语言评论数据添加有意义的标签。
- 准备并映射索引以实现高效的全文搜索,以容纳多语言数据。
- 设置自定义采集管道来处理和转换数据,并在需要时集成外部推理服务。
- 根据地理和文本数据执行高级位置感知建议。
所有这些过程(数据采集、处理、推理、语义搜索、地理搜索和分析)都在 Elasticsearch 生态系统中处理。
用例
基于位置的搜索
在此用例中,我们将使用评论数据和坐标来改进我们的搜索结果。
通过关注地理边界,我们可以提供精确的结果。例如,如果你正在寻找 Chelsea 的儿童友好型公园(可能位于曼哈顿或伦敦),我们可以利用近似 KNN 搜索期间应用的地理过滤来确保你从正确的 Chelsea 获得结果。此功能可防止混淆并有助于避免不相关的结果。此外,通过规范化并使用距离作为排名指标,我们可以优先考虑距离用户较近的公园。这意味着,在所有其他因素相同的情况下,较近的公园将首先出现在结果中,以满足对附近位置的偏好并增强搜索的相关性。还可以结合基于较新评论的提升机制来提高最近结果的相关性。
然后汇总检索到的评论结果,以根据搜索结果突出显示相关兴趣点。作为其中的一部分,检索到的每个兴趣点的中位评分都是根据特定用户偏好量身定制的。例如,没有孩子的人对某个公园的评分较低,但有孩子的人可能会对其评价很高。通过提供基于相关评论数据汇总的中位数评论,我们可以生成专门针对该用户的评分,而不是依赖于所有用户的一般总体评分。
{
// k-nearest neighbors search
"knn": [
{
"field": "ml.inference.text.predicted_value",
"k": 30,
"num_candidates": 5000,
"query_vector_builder": {
"text_embedding": {
"model_id": ".multilingual-e5-small_linux-x86_64",
"model_text": "kid friendly parks in chelsea"
}
},
// Geo filter to limit results within 5km of specified coordinates
"filter": {
"geo_distance": {
"distance": "5km",
// Example User location in Chelsea, NYC
"coordenatesPOI": {
"lat": 40.7465,
"lon": -74.0014
}
}
}
}
],
"aggs": {
"poi": {
"terms": {
"field": "namePOI.enum",
"size": 3,
"order": {
"min_distance": "asc" // Order buckets by minimum distance, ascending
}
},
"aggs": {
"min_distance": {
"min": {
// Script to calculate minimum distance for each Point of intrest
"script": {
"source": "doc['coordenatesPOI'].arcDistance(params.lat, params.lon)",
"params": {
"lat": 40.7465,
"lon": -74.0014
}
}
}
},
"median_rating": {
"percentiles": {
"field": "rating",
"percents": [
50 // Calculate the median of reviews
]
}
}
}
}
}
}
汇总结果表明,Chelsea 地区 5 公里范围内的最佳游玩地点是 High Line,其与 KNN 查询相匹配的评论平均为 5 星:
"buckets": [
{
"key": "High Line",
"doc_count": 28,
"min_distance": {
"value": 955.5158543152841
},
"median_rating": {
"values": {
"50.0": 5
}
}
},
{
"key": "Bleecker Street Playground",
"doc_count": 1,
"min_distance": {
"value": 1170.3017470834366
},
"median_rating": {
"values": {
"50.0": 3
}
}
},
{
"key": "Hudson River Park",
"doc_count": 1,
"min_distance": {
"value": 2124.45926042765
},
"median_rating": {
"values": {
"50.0": 5
}
}
}
]
另一个例子是 “City of London - 伦敦市” 周边的艺术画廊。搜索 “Art galleries in City of London” 时,无需指定坐标,你就可以获得来自英国伦敦各地甚至加拿大伦敦的结果。
POST tripadvisor_reviews/_search
{
"knn": [
{
"field": "ml.inference.text.predicted_value",
"k": 20,
"num_candidates": 5000,
"query_vector_builder": {
"text_embedding": {
"model_id": ".multilingual-e5-small_linux-x86_64",
"model_text": "best art museums around city of london"
}
},
// city of London area
"filter": {
"geo_distance": {
"distance": "5km",
"coordenatesPOI": {
"lat": 51.514335,
"lon": -0.092892
}
}
}
}
],
"aggs": {
"poi": {
"terms": {
"field": "namePOI.enum",
"size": 3,
"order": {
"min_distance": "asc" // Order by minimum distance, ascending
}
},
"aggs": {
"min_distance": {
"min": {
// Script to calculate minimum distance to the user location
"script": {
"source": "doc['coordenatesPOI'].arcDistance(params.lat, params.lon)",
"params": {
"lat": 51.514335,
"lon": -0.092892
}
}
}
},
"median_rating": {
"percentiles": {
"field": "rating",
"percents": [
50 ]
}
}
}
}
}
}
由于结果包含多种语言,我们使用了多语言模型来确保不同语言的推荐具有相关性。包括国家美术馆、大英博物馆和泰特英国美术馆/泰特现代美术馆在内的推荐具有高度相关性。
"buckets": [
{
"key": "Tate Modern",
"doc_count": 1,
"min_distance": {
"value": 865.5634476538138
},
"median_rating": {
"values": {
"50.0": 5
}
}
},
{
"key": "Museo Británico",
"doc_count": 5,
"min_distance": {
"value": 2423.81215603332
},
"median_rating": {
"values": {
"50.0": 5
}
}
},
{
"key": "Galería Nacional",
"doc_count": 12,
"min_distance": {
"value": 2523.5104507076207
},
"median_rating": {
"values": {
"50.0": 5
}
}
}
]
用户评论分类,提供个性化推荐
上述查询的输入可以通过多种方式提供,例如:
- 用户在搜索过程中输入
- 用户在注册时直接输入(“What are the type of activities you are looking for? - 你正在寻找什么类型的活动?”)
- 从用户的评论数据中提取的洞察。
在这种情况下,我们将探索第三个选项;根据用户过去的评论对其兴趣进行分类。该方法可以对用户进行分析,而无需依赖训练模型或分析用户相似性。然后可以将这种洞察输入到查询中,以自动推广推荐,而无需用户搜索任何特定内容。
在提取过程中,多语言模型 MoritzLaurer/multilingual-MiniLMv2-L6-mnli-xnli 将对多种语言的评论进行分类。预测的类别将用于分析用户。
在下面的例子中,我们根据用户 “flyingtolive” 以前的评论提取他们最感兴趣的类别,并按类别正确的概率排序。

就此用户而言,最相关的类别依次为 “Accessible”、“Couple-Friendly”、“Great View”。了解这些对用户而言是最重要的因素后,可以显著改善个性化推荐。
{
"query": {
"term": {
"userName": {
"value": "flyingtolive"
}
}
},
"aggs": {
"labels": {
"terms": {
"size": 3,
"field": "ml.inference.labels.predicted_value.enum",
"order": {
"probability": "desc"
}
},
"aggs": {
"probability": {
"sum": {
"field": "ml.inference.labels.prediction_probability"
}
}
}
}
}
}
分析
由于 Elastic 与 Kibana 捆绑在一起,可以用于聚合和语义搜索,因此可以通过多种方式分析数据并通过 Kibana Lens 生成报告。在评论数据场景中,这些信息可以与希望了解其业务趋势分析的企业共享。
例如,这些是多年来对 “Central Park” 的分类评论:

它还提供了可以可视化评论数据的地图服务,在此示例中,我们查看的是伦敦可到达的兴趣点:

数据准备
第一步:使用 eland 导入零样本分类模型
为了改进非结构化、多语言评论数据的推荐服务,我们可以用诸如教育价值、当地文化和历史、物有所值等标签来丰富评论。这些标签将帮助用户快速找到突出显示的信息,而无需搜索所有评论。
可以使用 eland 将分类模型上传到 Elastic,eland 是一个允许将机器学习模型集成到 Elasticsearch 中的客户端库。对于此用例,多语言模型 MoritzLaurer/multilingual-MiniLMv2-L6-mnli-xnli 将对多种语言的评论进行分类。在提取过程中,将向每个评论添加标签。标记数据还可以用作客户评论随时间变化的商业智能形式。
注意:建议针对特定标签对较小的预训练模型进行微调,以增强其与任务的相关性和性能。这种方法可使模型更贴近数据的细微差别。
MODEL_ID="multilingual-minilmv2-l6-mnli-xnl"
eland_import_hub_model \
--url $CLOUD_URL \
--es-username elastic \
--es-password $ELASTIC_PASSWORD \
--hub-model-id MoritzLaurer/multilingual-MiniLMv2-L6-mnli-xnli \\
--es-model-id $MODEL_ID \
--task-type zero_shot_classification \
--start
第二步:索引准备
在 Kibana 中,在 “Search” > “Indices” 下创建搜索索引。
此索引为全文搜索准备了关键部分,例如标记化和分析器。由于评论是多语言的,因此 Universal 分析器是处理不同语言的绝佳选择。但是,如果需要,你可以选择特定语言的分析器。

要将非文本字段(如 “Coordinates” 字段)适当地映射为地理点,你需要更新索引映射。以下是使用 curl 的示例,以及本博客的 github repo 中附带的映射示例:
curl -X POST "$CLOUD_URL/tripadvisor_reviews/_mapping" -H 'Content-Type: application/json' -u $ELASTIC_USER:$ELASTIC_PASSWORD -d "$(curl -s https://raw.githubusercontent.com/liladler/elastic-geo-search/main/mapping.json)"
步骤 3:设置采集管道
采集管道可以对数据执行推理、消除字段、解析字段,甚至包括用于灵活数据操作的脚本处理器。
对于大型文本,可以利用采集管道将内容分块为较小的部分,并利用嵌套对象数据类型。可以在此处找到一个示例。
为了采集评论数据,我们将生成一个自定义和推理管道,该管道自动链接到主管道,与索引共享相同的名称。
将设置的管道将:
- 对字段 “text”、“tagsPOI” 和 “namePOI” 运行多语言推理
- 对 “coordinatesPOI” 字段进行 gsub
- 对评论进行多语言分类
提示:通过利用推理管道,还可以将外部推理服务(如 Hugging Face 或 OpenAI)直接集成到数据提取过程中,从而确保高效、精简的数据处理。这种方法无需使用其他工具,尤其适用于开发和测试目的,因为它允许你在单个平台内测试不同的模型,而无需重新提取数据或依赖外部服务。
1)要将 e5 模型与采集管道集成,请导航到新创建的索引中的 “Pipelines”,部署并启动机器学习 (ML) 推理管道。本例中用于推理的文本字段为 “text”、“tagsPOI” 和 “namePOI”。



2)在此数据集中,我们需要调整 “CoordinatesPOI” 字段,使其适合 geopoint 映射格式。为了实现这一点,我们使用带有 gsub 处理器的自定义提取管道。它将坐标字段从字符串数组格式(如 “[1,2]”)更改为字符串格式(如 “1,2”)。

使用二次推理处理器对评论文本数据进行标记。为避免与向量字段冲突,请适当配置目标字段。标签(labels)列表如下。


第四步:数据采集
Elasticsearch 要求数据采用 JSON、CSV 或 XML 格式才能进行解释,但 TripAdvisor 评论数据集最初采用 pickle 格式。因此,需要进行一些操作。
本博客的采集 Python 脚本执行了几个任务来实现此目的:
- 它将文件从 pickle 格式转换为 CSV 格式。
- 它添加了一个 “_run_ml_inference”:true 字段来启动推理过程。
- 它使用批量 API 高效地将 CSV 数据加载到 Elasticsearch 中。
- 它利用具有相同索引名称的采集管道进行数据处理。
要运行 Elasticsearch 采集脚本,需要一个 .env 文件,其中包含 Elasticsearch 主机、用户名、密码的变量:
CLOUD_URL=<https://xxx.es.region.gcp.cloud.es.io>
ELASTIC_USER=user
ELASTIC_PASSWORD=xxx
运行脚本:
python ./es_ingest.py
脚本完成执行后,基础目录的结构将如下所示:
.
├── 5749846/
│ ├── barcelona
│ ├── barcelona.zip
│ ├── london
│ ├── london.zip
│ ├── madrid
│ ├── madrid.zip
│ ├── newyorkcity
│ ├── newyorkcity.zip
│ ├── paris
│ └── paris.zip
├── es_ingest.py
├── mapping.json
├── requirements.txt
├── .env
└── tripadvisor_reviews/
├── df_Barcelona.csv
├── df_London.csv
├── df_Madrid.csv
├── df_NYC.csv
└── df_Paris.csv
结论
利用 Elasticsearch 的混合地理语义搜索功能,可以为广泛用例中的非结构化和多语言数据提供强大的解决方案。通过集成机器学习模型、设置自定义提取管道和利用高级位置感知查询,你可以实现精确、高效和个性化的数据检索。这种方法增强了搜索相关性,并为企业和用户提供了有价值的见解。
准备好自己尝试一下了吗?开始免费试用。
Elasticsearch 集成了 LangChain、Cohere 等工具。加入我们的高级语义搜索网络研讨会,构建你的下一个 GenAI 应用程序!

1994

被折叠的 条评论
为什么被折叠?



