使用 Elasticsearch 构建食谱搜索(一)
作者:来自 Elastic Andre Luiz
了解如何使用 Elasticsearch 构建基于语义搜索的食谱搜索。
简介
许多电子商务网站都希望增强其食谱搜索体验。正确使用语义搜索可以让客户根据更自然的查询(例如 “something for Valentine's Day - 情人节的礼物” 或 “Thanksgiving meals. - 感恩节大餐”)快速找到所需的食材。
在本文中,我们将演示如何使用 Elasticsearch 实现支持此类查询的语义搜索。我们将配置一个索引来存储超市的食材和产品目录,并演示如何使用此索引来改进食谱搜索。在整篇文章中,我们将解释如何创建此数据结构并应用自然语言处理技术来提供与客户意图一致的相关结果。
本文中介绍的所有代码都是用 Python 开发的,可在 GitHub 上找到。你可以访问存储库以查看源代码、根据需要进行调整并直接在你的开发环境中实施解决方案。
开始实施语义搜索
要开始实施语义搜索,我们首先需要定义自然语言模型。Elastic 提供自己的模型 ELSER,但也支持集成来自各种提供商(例如 Hugging Face)的 NLP 模型。这种灵活性使你可以选择最适合你需求的选项。
在本文中,我们将使用 ELSER,它降低了部署和管理 NLP 模型的复杂性。此外,Elastic 还提供 semantic_text 功能,大大简化了流程。使用 semantic_text,整个嵌入生成过程变得简单而自动化。你只需定义一个推理点并指定将接收索引映射中的嵌入的字段。在文档索引期间,将生成嵌入并自动与指定字段相关联。
设置步骤
以下是创建具有语义搜索支持的索引的步骤。按照这些说明,你将拥有一个配置好并准备好进行语义搜索的索引:
- 创建 inference point。
- 创建索引,将描述字段设置为 semantic_text,以便它可以接收嵌入。
- 将数据编入杂货目录索引,该索引将存储产品目录。此目录是从此处提供的数据集获得的。
语义搜索在杂货店中的应用
现在我们已经用杂货店产品数据填充了索引,我们正在测试和验证查询以使用语义搜索改进搜索结果。我们的目标是提供更智能的搜索体验,了解上下文和用户意图,提供更相关和准确的结果。
语义搜索解决的挑战
基于产品目录,让我们探索语义搜索如何通过解决传统词汇搜索经常遇到的词汇和上下文问题来改变杂货店的搜索体验。
1. 烹饪意图的解释
问题 01:客户可能会搜索 “seafood for grilling - 烧烤海鲜”,但词汇搜索系统可能无法完全理解查询背后的意图。它可能无法识别所有适合烧烤的海鲜产品,而只会返回产品标题中带有确切术语 “seafood - 海鲜” 或 “grill - 烧烤” 的产品。
首先,我们将执行词汇搜索并分析结果。然后,我们将使用语义搜索执行相同操作,比较相同搜索词的结果。
查询词汇搜索
response = client.search(index="grocery-catalog",size=5,source_excludes="description_embedding",query={"multi_match": {"query": "seafood for grilling","fields": ["name","description"]}})
结果:
Search Type | Name | Score |
---|---|---|
Lexical | Northwest Fish Alaskan Bairdi Snow Crab | 10.453125 |
Lexical | Mr. Yoshida's, Sauce Original Gourmet | 7.2289705 |
Lexical | Premium Seafood Variety Pack - 20 pcs | 7.1924105 |
Lexical | American Red Snapper - Whole, Head-On, Cleaned | 6.998647 |
Lexical | Lobster Claws & Arms, Sustainable Wild Caught | 6.438654 |
词汇搜索返回了一些适合烧烤的海鲜,例如 American Red Snapper 和 Northwest Fish Alaskan Bairdi Snow Crab。然而,词汇搜索返回的列表顶部有一些相关性较低的产品,例如 Mr. Yoshida sauce,它不是海鲜而是肉酱,这表明词汇算法很难完全理解 “for grilling - 烧烤” 的上下文。
语义搜索解决方案
我们使用将术语 “seafood” 与 “grilling” 等准备上下文相结合的查询来返回全面的选项列表,例如鱼片/fish fillets、虾/shrimp 和扇贝/scallops,这些都非常适合烧烤 - 即使 “grill - 烧烤” 或 “seafood - 海鲜” 字样没有直接出现在产品名称中。这可确保搜索结果与客户的意图更加一致。
查询语义搜索:
es_client.search(index="grocery-catalog-elser",size=size,source_excludes="description_embedding",query={"semantic": {"field": "description_embedding","query": "seafood for grilling"}})
Search Type | Name | Score |
---|---|---|
Semantic | Whole Head On, Cleaned Branzino Fish | 16.175909 |
Semantic | Alaska Black Cod (Sable Fish) | 15.855331 |
Semantic | American Red Snapper - Whole, Head-On | 15.454779 |
Semantic | Northwest Fish Alaskan Bairdi Snow Crab | 15.855331 |
Semantic | American Red Snapper - Whole, Head-On | 15.3892355 |
语义搜索不仅返回与 “seafood - 海鲜”一词直接相关的产品,而且还理解 “grilling - 烧烤” 的上下文,显示适合烧烤的整条鱼和鱼片。这里的关键是结果的精确度,其中包括 Branzino 和阿拉斯加黑鳕鱼等整条鱼,这两种鱼都常用于烧烤。
问题 02:许多顾客在工作了一整天后会搜索快速简便的晚餐解决方案,使用 “easy weeknight meals” 等术语。传统的词汇搜索可能无法完全捕捉快餐的概念,通常只关注名称中包含 “easy - 简单”一词的产品。
正如我们在上一个问题中所做的那样,我们将首先执行词汇搜索。之后,我们将使用语义搜索应用解决方案。
查询词汇搜索
response = client.search(index="grocery-catalog",size=5, source_excludes="description_embedding",query={"multi_match": {"query": "easy weeknight meals","fields": ["name","description"]}})
结果:
Search Type | Name | Score |
---|---|---|
Lexical | Avery Easy Peel Address Labels, 4200-count | 8.017723 |
Lexical | Omeals Self Heating Emergency/Portable Meals 32 | 6.592727 |
Lexical | Coastal Seafood Yellowfin Tuna Cubed Poke | 5.836883 |
Lexical | Hefty Super Weight 12 oz Foam | 5.8116536 |
Lexical | Vanity Fair Everyday Napkin, 2-Ply, 110-count | 5.752989 |
词汇搜索返回的结果相关性要低得多,包括与餐食完全无关的商品,例如 Avery Easy Peel Address Labels 和 Vanity Fair Everyday Napkins。这些产品无法满足用户对快餐的需求。虽然词汇搜索确实返回了一款有用的产品(Omeals Self Heating Emergency Meals),但餐巾纸和标签等其他结果的描述中只匹配了 “easy” 或 “weeknight” 等字词,并没有真正满足用户对快餐解决方案的需求。
语义搜索解决方案
我们实施了一个查询,以了解快速简便的餐食背后的意图。它会关联可以快速准备的产品,例如预煮肉类、冷冻意大利面或餐食套装,即使它们的名称中没有明确包含 “easy” 一词。这种方法可确保客户找到最适合快速晚餐的选择,满足对便利的需求。
查询语义搜索
es_client.search(index="grocery-catalog-elser",size=size,source_excludes="description_embedding",query={"semantic": {"field": "description_embedding","query": "easy weeknight meals"}})
结果:
Search Type | Name | Score |
---|---|---|
Semantic | Omeals Self Heating Emergency/Portable Meals 32 | 14.610006 |
Semantic | Nissin, Cup Noodles, Shrimp, 2.5 oz | 13.751424 |
Semantic | Namaste Gluten Free Waffle & Pancake Mix | 13.73376 |
Semantic | Idaho Spuds, Golden Grill Hashbrown Potatoes | 12.549422 |
Semantic | Nissin, Cup Noodles, Chicken, 24-Count | 12.034527 |
语义搜索返回的产品明显与快捷方便的餐食有关,例如方便面(Cup Noodles)、pre-cooked potatoes 和 pancake mixes,这些都是简单的平日晚餐的典型选择。这表明语义搜索可以掌握短语“简单的平日晚餐”背后的概念,捕捉用户寻找快捷方便餐食的意图。有趣的是,如果与上下文相关(例如,佐餐饮料),其他类别的产品(例如 “soda - 苏打水”)也可能包括在内。
2. 区域术语和词汇变化
问题:一位客户可能会搜索“soda - 苏打水”,而另一位客户可能会使用 “pop” 来搜索同一款产品。传统的词汇搜索无法识别这两个术语指的是同一款产品。
查询词汇搜索
response = client.search(index="grocery-catalog",size=5,source_excludes="description_embedding",query={"multi_match": {"query": "refreshing pop drink low sugar","fields": ["name","description"]}})
结果:
Search Type | Name | Score |
---|---|---|
Lexical | Prime Hydration+ Sticks Electrolyte Drink Mix | 14.492869 |
Lexical | Capri Sun, 100% Juice, Variety Pack | 12.340851 |
Lexical | Joyburst Energy Drink, Frose Rose, 12 | 11.839179 |
Lexical | Kellogg’s Pop-Tarts, Frosted Brown Sugar Cinnamon | 9.97788 |
Lexical | Kind Mini Bars, Variety Pack, 0.7 | 9.336912 |
词汇搜索侧重于精确匹配单词。虽然它返回了 Prime Hydration 和 Capri Sun 等产品,但直接匹配 “pop” 一词也会导致不相关的结果,例如 Kellogg’s Pop-Tarts,它是一种零食而不是饮料。这凸显了当一个术语具有多重含义或可能含糊不清时,词汇搜索的效率会降低。
语义搜索解决方案
在语义查询中,我们可以克服词汇搜索无法解决的词汇变化问题。通过扩展搜索词,我们能够根据上下文含义获得结果,从而提供更相关、更全面的响应。
查询:
es_client.search(index="grocery-catalog-elser",size=size,source_excludes="description_embedding",query={"semantic": {"field": "description_embedding","query": "refreshing pop drink low sugar"}})
结果:
Search Type | Name | Score |
---|---|---|
Semantic | Olipop 12 oz Prebiotics Soda Variety | 14.776867 |
Semantic | Bai Antioxidant Cocofusion, Variety Pack, 18 | 14.663253 |
Semantic | Monster Energy Drink, Zero Ultra, 24 | 14.486348 |
Semantic | Joyburst Energy Variety, 12 fl oz | 14.007214 |
Semantic | Joyburst Energy Drink, Frose Rose, 12 | 13.641038 |
语义搜索能够返回与 “pop” 作为 “soda” 同义词直接匹配的产品(例如 Olipop Prebiotics Soda),即使产品名称中未必出现 “pop” 这个确切的词。该搜索理解了用户的意图 —— 一种清爽、低糖的饮料 —— 并能够返回相关产品,包括益生元苏打(如 Olipop)和无糖能量饮料(如 Monster Energy Drink)等选项。
结论
事实证明,在杂货店环境中实施语义搜索对于理解“烧烤海鲜”和“简单的工作日晚餐”等复杂查询非常有效。这种方法使我们能够更准确地解释用户意图,返回高度相关的产品。
通过使用 Elasticsearch 并使用 ELSER 简化流程,我们能够快速高效地应用语义搜索,显著改善搜索结果并提供更灵活、更有针对性的购物体验。这不仅优化了搜索过程,还提高了向客户提供的结果的相关性。
参考资料 ELSER 模型:
Create inference API | Elasticsearch Guide [8.15] | Elastic
ELSER inference service | Elasticsearch Guide [8.15] | Elastic
语义文本:
Semantic text field type | Elasticsearch Guide [8.15] | Elastic
Semantic search | Elasticsearch Guide [8.15] | Elastic
数据集:
https://www.kaggle.com/datasets/bhavikjikadara/grocery-store-dataset?select=GroceryDataset.csv
语义搜索:
Semantic search | Elasticsearch Guide [8.15] | Elastic
Tutorial: semantic search with semantic_text | Elasticsearch Guide [8.15] | Elastic
准备好自己试试了吗?开始免费试用。
想要获得 Elastic 认证?查看下一次 Elasticsearch 工程师培训的时间!
原文:Building a recipe search with Elasticsearch - Search Labs
相关文章:

使用 Elasticsearch 构建食谱搜索(一)
作者:来自 Elastic Andre Luiz 了解如何使用 Elasticsearch 构建基于语义搜索的食谱搜索。 简介 许多电子商务网站都希望增强其食谱搜索体验。正确使用语义搜索可以让客户根据更自然的查询(例如 “something for Valentines Day - 情人节的礼物” 或 “…...

sealos部署K8s,安装docker时master节点突然NotReady
1、集群正常运行中,在集群master-1上安装了dockerharbor,却发现master-1节点NotReady,使用的网络插件为 Cilium #安装docker和harbor(docker运行正常) rootmaster-1:/etc/apt# apt install docker-ce5:19.03.15~3-0~u…...

使用vite+react+ts+Ant Design开发后台管理项目(五)
前言 本文将引导开发者从零基础开始,运用vite、react、react-router、react-redux、Ant Design、less、tailwindcss、axios等前沿技术栈,构建一个高效、响应式的后台管理系统。通过详细的步骤和实践指导,文章旨在为开发者揭示如何利用这些技术…...
Spring Boot实现多数据源连接和切换
文章目录 前言一、多数据源配置与切换方案二、实现步骤1. 创建多个 DataSource 配置类2. 创建 DataSource 配置类3. 创建动态数据源路由类4. 实现 DynamicDataSource 类5. 创建 DataSourceContextHolder 来存储当前的数据源标识6. AOP 方式切换数据源7. 自定义注解来指定数据源…...

发布 VectorTraits v3.0(支持 X86架构的Avx512系列指令集,支持 Wasm架构及PackedSimd指令集等)
文章目录 支持 X86架构的Avx512系列指令集支持Avx512时的输出信息 支持 Wasm架构及PackedSimd指令集支持PackedSimd时的输出信息VectorTraits.Benchmarks.Wasm 使用说明 新增了向量方法支持 .NET 8.0 新增的向量方法提供交织与解交织的向量方法YGroup3Unzip的范例代码 提供重新…...

详解如何创建SpringBoot项目
目录 点击New Project 选择依赖 简单使用SpringBoot 前面已经讲解了如何获取IDEA专业版,下面将以此为基础来讲解如何创建SpringBoot项目。 点击New Project 选择依赖 注意,在选择SpringBoot版本时,不要选择带SNAPSHOT的版本。 这样&#…...

IT架构管理
目录 总则 IT架构管理目的 明确组织与职责 IT架构管理旨在桥接技术实施与业务需求之间的鸿沟,通过深入理解业务战略和技术能力,推动技术创新以支持业务增长,实现技术投资的最大价值。 设定目标与范围 IT架构管理的首要目的是确立清晰的组织…...
Feign入门实践
引言 随着微服务架构的兴起,服务间的通信变得越来越频繁和复杂。为了简化服务之间的调用过程,提高开发效率和系统的可维护性,Spring Cloud 生态系统提供了多种解决方案,其中 OpenFeign 是一种声明式的 HTTP 客户端,它使…...

Leetcode 买卖股票的最佳时机 Ⅱ
使用贪心算法来解决此问题,通过在价格上涨的每一天买入并在第二天卖出的方式,累计所有上涨的利润,以实现最大收益。关键点是从第二天开始遍历,并且只要当前比前一天价格高,我们就在前一天买入然后第二天卖出去。下面是…...

书生大模型实战营-玩转HF/魔搭社区闯关任务
通过Github Codespace下载InternLM模型并运行 本篇博客是记录《书生大模型实战营第四期-玩转HF/魔搭/魔乐》章节的闯关任务从HF上下载模型文件,对实战营感兴趣的小伙伴也可以扫码报名哦。 一、通过模版创建Codespace环境 访问codespace 点击Jupyter Notebook 模版…...
混响(Reverb):原理、应用与发展趋势的深度解析
目录 引言1. 混响的基本原理2. 混响的应用3. 混响的技术实现4. 混响的未来发展趋势5. 总结 引言 混响(Reverb)是音频信号处理中的重要概念之一,在自然界和音频工程中都扮演着关键角色。从音乐制作到语音识别,从电影音效到虚拟现实…...
Java学习教程,从入门到精通,Java修饰符语法知识点及案例代码(23)
1.Java修饰符语法知识点及案例代码 Java修饰符用于改变类、方法、变量、接口等元素的行为和可见性。主要分为两大类:访问修饰符和非访问修饰符。 访问修饰符(Access Modifiers) public 提供最大的访问权限,任何类都可以访问。使…...
钉钉小程序使用getApp实现类型provide inject的功能 应用场景:解决页面同步子组件弹窗的滚动问题
前言:在开发钉钉小程序的时候 组件内部的弹窗滚动会带着视图同步滚动 所以需要在组件内部弹窗显示的时候禁用视图的scroll滚动 由于我组件封装的比较深 不可能逐级传递 dd也么有provide的语法 所以我使用的getApp 完成控制的效果 最终完美运行 觉得有帮助相互关注一下 后续会持…...
标准化 Git 提交信息的约定
在使用 Git 进行版本控制时,良好的提交信息可以帮助团队成员更好地理解每次提交的目的和影响。为了规范化提交信息,一些团队采用了特定的格式或约定,比如 Angular 团队提出的 Commit Message Conventions。这种规范有助于自动化工具的使用&am…...

React教程(详细版)
React教程(详细版) 1,简介 1.1 概念 react是一个渲染html界面的一个js库,类似于vue,但是更加灵活,写法也比较像原生js,之前我们写出一个完成的是分为html,js,css&…...

Perfect Forwarding(完美转发)
文章目录 1. 引用折叠2. 万能引用3. 完美转发3.1对比:std::move and std::forward比较 3.2使用时机3.3 返回值优化(RVO)两个前提条件注意事项 4. 完美转发失败情况完美转发失败五种情况 完美转发的实现要依赖于模版类型推导和引用折叠和万能引用。 1. 引…...

PHP露营地管理平台小程序系统源码
⛺️【露营新风尚】露营地管理平台系统全攻略⛺️ 🏕️一、露营热潮下的管理难题:如何高效运营露营地?🤔 随着露营文化的兴起,越来越多的人选择在大自然中享受宁静与自由。然而,露营地的管理却面临着诸多…...
速盾:vue的cdn是干嘛的?
CDN,即内容分发网络(Content Delivery Network),是一种将网站的静态资源分发到全球各个节点并缓存起来的技术。它可以帮助网站提供更快的加载速度,更好的用户体验,并且可以减轻源服务器的负载压力。 Vue.j…...

线性代数:Matrix2x2和Matrix3x3
今天整理自己的框架代码,将Matrix2x2和Matrix3x3给扩展了一下,发现网上unity数学计算相关挺少的,所以记录一下。 首先扩展Matrix2x2: using System.Collections; using System.Collections.Generic; using Unity.Mathemati…...
Windows 中 Electron 项目实现运行时权限提升以杀掉特定进程
#Windows 中 Electron 项目实现运行时权限提升以杀掉特定进程 一、引言 在 Windows 操作系统中,有时我们需要以管理员权限来执行某些操作,特别是当需要杀掉由管理员启动的进程时。Electron 是一个开源的框架,用于使用 JavaScript、HTML 和 C…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...